diff --git a/Test/baseResults/preprocessor.line.frag.err b/Test/baseResults/preprocessor.line.frag.err new file mode 100644 index 00000000..5f177e6c --- /dev/null +++ b/Test/baseResults/preprocessor.line.frag.err @@ -0,0 +1,2 @@ +Warning, version 310 is not yet complete; most version-specific features are present, but some are missing. + diff --git a/Test/baseResults/preprocessor.line.frag.out b/Test/baseResults/preprocessor.line.frag.out new file mode 100644 index 00000000..3e2206f8 --- /dev/null +++ b/Test/baseResults/preprocessor.line.frag.out @@ -0,0 +1,5 @@ +#version 310 es +#line 1 2 +#pragma something +void main(){ } + diff --git a/Test/baseResults/preprocessor.line.vert.out b/Test/baseResults/preprocessor.line.vert.out index 2893521b..2bf09032 100644 --- a/Test/baseResults/preprocessor.line.vert.out +++ b/Test/baseResults/preprocessor.line.vert.out @@ -1,24 +1,39 @@ -#line 300 - -#line 2 - -#line 10 - -#line 2 - -#line 0 - -#line 4 - -#line 8 - -void main(){ - gl_Position = vec4(10); -} -#line 8 4 - -#line 12 3 - -#line 1 - - +#line 300 + +#line 2 + + + + + +#line 10 + + +#line 2 + +#line 0 + + + +#line 4 + + + + + +#line 8 + +void main(){ + gl_Position = vec4(10); +} + +#line 8 4 + + + + +#line 12 3 + +#line 1 + + diff --git a/Test/preprocessor.line.frag b/Test/preprocessor.line.frag new file mode 100644 index 00000000..0b7ac766 --- /dev/null +++ b/Test/preprocessor.line.frag @@ -0,0 +1,4 @@ +#version 310 es +#line 1 2 +#pragma something +void main() {} diff --git a/Test/test-preprocessor-list b/Test/test-preprocessor-list index 1baa5584..2816d409 100644 --- a/Test/test-preprocessor-list +++ b/Test/test-preprocessor-list @@ -3,6 +3,7 @@ preprocessor.errors.vert preprocessor.extensions.vert preprocessor.function_macro.vert preprocessor.line.vert +preprocessor.line.frag preprocessor.pragma.vert preprocessor.simple.vert preprocessor.success_if_parse_would_fail.vert diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index a1ad7479..0657cf12 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2673,6 +2673,19 @@ void TParseContext::updateImplicitArraySize(TSourceLoc loc, TIntermNode *node, i symbol->getWritableType().setImplicitArraySize(index + 1); } +// Returns true if the first argument to the #line directive is the line number for the next line. +// +// Desktop, pre-version 3.30: "After processing this directive +// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and +// source string number source-string-number." +// +// Desktop, version 3.30 and later, and ES: "After processing this directive +// (including its new-line), the implementation will behave as if it is compiling at line number line and +// source string number source-string-number. +bool TParseContext::lineDirectiveShouldSetNextLine() const { + return profile == EEsProfile || version >= 330; +} + // // Enforce non-initializer type/qualifier rules. // @@ -5291,10 +5304,10 @@ void TParseContext::notifyErrorDirective(int line, const char* error_message) } } -void TParseContext::notifyLineDirective(int line, bool has_source, int source) +void TParseContext::notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum) { if (lineCallback) { - lineCallback(line, has_source, source); + lineCallback(curLineNo, newLineNo, hasSource, sourceNum); } } diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index d48ae9d6..176bcf7b 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -217,9 +217,11 @@ public: void setCurrentString(int string) { currentScanner->setString(string); } void setScanner(TInputScanner* scanner) { currentScanner = scanner; } + bool lineDirectiveShouldSetNextLine() const; + void notifyVersion(int line, int version, const char* type_string); void notifyErrorDirective(int line, const char* error_message); - void notifyLineDirective(int line, bool has_source, int source); + void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum); // The following are implemented in Versions.cpp to localize version/profile/stage/extensions control void initializeExtensionBehavior(); @@ -240,7 +242,7 @@ public: void setVersionCallback(const std::function& func) { versionCallback = func; } void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } - void setLineCallback(const std::function& func) { lineCallback = func; } + void setLineCallback(const std::function& func) { lineCallback = func; } void setExtensionCallback(const std::function& func) { extensionCallback = func; } void setErrorCallback(const std::function& func) { errorCallback = func; } @@ -354,7 +356,7 @@ protected: // These, if set, will be called when a line, pragma ... is preprocessed. // They will be called with any parameters to the original directive. - std::function lineCallback; + std::function lineCallback; std::function&)> pragmaCallback; std::function versionCallback; std::function extensionCallback; diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index a58cbff6..15bc258f 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -639,30 +639,33 @@ struct DoPreprocessing { adjustLine(line); outputStream << "#extension " << extension << " : " << behavior; }); - parseContext.setLineCallback([&lastLine, &outputStream]( - int line, bool hasSource, int sourceNum) { + parseContext.setLineCallback([&adjustLine, &lastLine, &outputStream, &parseContext]( + int curLineNo, int newLineNo, bool hasSource, int sourceNum) { // SourceNum is the number of the source-string that is being parsed. - if (lastLine != -1) { - outputStream << std::endl; - } - outputStream << "#line " << line; + adjustLine(curLineNo); + outputStream << "#line " << newLineNo; if (hasSource) { outputStream << " " << sourceNum; } + if (parseContext.lineDirectiveShouldSetNextLine()) { + // newLineNo is the new line number for the line following the #line + // directive. So the new line number for the current line is + newLineNo -= 1; + } outputStream << std::endl; - lastLine = std::max(line - 1, 1); + // Line number starts from 1. And we are at the next line of the #line + // directive now. So lastLine (from 0) should be (newLineNo - 1) + 1. + lastLine = newLineNo; }); parseContext.setVersionCallback( - [&adjustLine, &lastLine, &outputStream](int line, int version, const char* str) { + [&adjustLine, &outputStream](int line, int version, const char* str) { adjustLine(line); outputStream << "#version " << version; if (str) { outputStream << " " << str; } - outputStream << std::endl; - ++lastLine; }); parseContext.setPragmaCallback([&adjustLine, &outputStream]( diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index 1d03b43b..0e035c24 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -624,6 +624,7 @@ int TPpContext::CPPline(TPpToken* ppToken) // "#line line source-string-number" int token = scanToken(ppToken); + const int directiveLoc = ppToken->loc.line; if (token == '\n') { parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); return token; @@ -641,14 +642,7 @@ int TPpContext::CPPline(TPpToken* ppToken) if (token == '\n') ++lineRes; - // Desktop, pre-version 3.30: "After processing this directive - // (including its new-line), the implementation will behave as if it is compiling at line number line+1 and - // source string number source-string-number." - // - // Desktop, version 3.30 and later, and ES: "After processing this directive - // (including its new-line), the implementation will behave as if it is compiling at line number line and - // source string number source-string-number. - if (parseContext.profile == EEsProfile || parseContext.version >= 330) + if (parseContext.lineDirectiveShouldSetNextLine()) --lineRes; parseContext.setCurrentLine(lineRes); @@ -660,7 +654,7 @@ int TPpContext::CPPline(TPpToken* ppToken) } } if (!fileErr && !lineErr) { - parseContext.notifyLineDirective(lineToken, hasFile, fileRes); + parseContext.notifyLineDirective(directiveLoc, lineToken, hasFile, fileRes); } token = extraTokenCheck(lineAtom, ppToken, token);