diff --git a/Test/baseResults/preprocess.inactive_stringify.vert.err b/Test/baseResults/preprocess.inactive_stringify.vert.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Test/baseResults/preprocess.inactive_stringify.vert.out b/Test/baseResults/preprocess.inactive_stringify.vert.out new file mode 100755 index 0000000000..70cf1de86d --- /dev/null +++ b/Test/baseResults/preprocess.inactive_stringify.vert.out @@ -0,0 +1,29 @@ +#version 460 + + + + + + + + + + + + + + + + + + + + + + + +void main() +{ + gl_Position = vec4(1.0); +} + diff --git a/Test/preprocess.inactive_stringify.vert b/Test/preprocess.inactive_stringify.vert new file mode 100755 index 0000000000..8f3a942552 --- /dev/null +++ b/Test/preprocess.inactive_stringify.vert @@ -0,0 +1,28 @@ +#version 460 + +// This tests that the preprocessor error +// "error: '#' : (#) can be preceded in its line only by spaces or horizontal tab" +// isn't enforced when inactive (e.g. inside #if 0) + +#if 0 +#define STRINGIFY(X) #X +#endif + +#define C 0 + +#if 1 +#ifdef A +#elif defined B +#elif C +// OK, since preprocessor evaluates to inactive +#define STRINGIFY(X) #X +#endif +#endif + +// OK in comments +// #define STRINGIFY(X) #X + +void main() +{ + gl_Position = vec4(1.0); +} \ No newline at end of file diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index 56f1f0b386..5b44b1304e 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -241,6 +241,7 @@ int TPpContext::CPPundef(TPpToken* ppToken) */ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) { + inElseSkip = true; int depth = 0; int token = scanToken(ppToken); @@ -297,7 +298,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) elseSeen[elsetracker] = false; --elsetracker; } - + inElseSkip = false; return CPPif(ppToken); } } else if (nextAtom == PpAtomElse) { @@ -311,7 +312,8 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); } } - + + inElseSkip = false; return token; } diff --git a/glslang/MachineIndependent/preprocessor/PpContext.cpp b/glslang/MachineIndependent/preprocessor/PpContext.cpp index 70f511978c..f27204bc4a 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ b/glslang/MachineIndependent/preprocessor/PpContext.cpp @@ -88,7 +88,8 @@ TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, T preamble(nullptr), strings(nullptr), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false), rootFileName(rootFileName), currentSourceFile(rootFileName), - disableEscapeSequences(false) + disableEscapeSequences(false), + inElseSkip(false) { ifdepth = 0; for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++) diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index 1ec30491ce..3446f1e1c9 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -371,7 +371,7 @@ class TPpContext { break; popInput(); } - if (!inputStack.empty() && inputStack.back()->isStringInput()) { + if (!inputStack.empty() && inputStack.back()->isStringInput() && !inElseSkip) { if (token == '\n') { bool seenNumSign = false; for (int i = 0; i < (int)lastLineTokens.size() - 1;) { @@ -732,6 +732,9 @@ class TPpContext { std::istringstream strtodStream; bool disableEscapeSequences; + // True if we're skipping a section enclosed by #if/#ifdef/#elif/#else which was evaluated to + // be inactive, e.g. #if 0 + bool inElseSkip; }; } // end namespace glslang diff --git a/gtests/Pp.FromFile.cpp b/gtests/Pp.FromFile.cpp index 1f960847d3..9cadd226ee 100644 --- a/gtests/Pp.FromFile.cpp +++ b/gtests/Pp.FromFile.cpp @@ -69,6 +69,7 @@ INSTANTIATE_TEST_SUITE_P( "preprocessor.eof_missing.vert", "preprocess.arb_shading_language_include.vert", "preprocess.include_directive_missing_extension.vert", + "preprocess.inactive_stringify.vert" })), FileNameAsCustomTestSuffix );