diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out index 5b8794149e2f461f77ade993db367c3996cc9ed8..1b6e6b50d824270a5eba9f429986c38f6ea174b1 100644 --- a/Test/baseResults/cppSimple.vert.out +++ b/Test/baseResults/cppSimple.vert.out @@ -90,8 +90,10 @@ ERROR: 12:9504: '#if' : unexpected tokens following directive ERROR: 12:9506: '#error' : \ 377 ERROR: 12:9507: '#error' : \ 376 ERROR: 12:9508: '#error' : \ 377 +ERROR: 12:9602: 'defined' : cannot use in preprocessor expression when expanded from macros +ERROR: 12:9603: '#error' : DEF_DEFINED then ERROR: 12:10002: '' : missing #endif -ERROR: 88 compilation errors. No code generated. +ERROR: 90 compilation errors. No code generated. Shader version: 400 diff --git a/Test/cppSimple.vert b/Test/cppSimple.vert index 198203a69d7a9f42c0ed0ce54e1a2b88cadca0dc..fdd14221b63b291d2ce2a35bc927a7d867ecf6be 100644 --- a/Test/cppSimple.vert +++ b/Test/cppSimple.vert @@ -337,6 +337,16 @@ int aoeua = FOOOM; #error \ 376 #error \377 +// ERROR for macro expansion to yield 'defined' +#line 9600 +#define DEF_MAC +#define DEF_DEFINED defined +#if DEF_DEFINED DEF_MAC +#error DEF_DEFINED then +#else +#error DEF_DEFINED else +#endif + #line 10000 #if 1 #else diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index da432bd547e5a51ddf217d9e2323b7353a868c56..5c6e247976e2408ca5298ee8574281963eb01f71 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -393,6 +393,14 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error if (token == PpAtomIdentifier) { if (strcmp("defined", ppToken->name) == 0) { + if (isMacroInput()) { + if (parseContext.relaxedErrors()) + parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression", + "defined", ""); + else + parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros", + "defined", ""); + } bool needclose = 0; token = scanToken(ppToken); if (token == '(') { diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index a459d9a2a684cf69d90fe6efc4cd72c93a86ed48..de48e2794bcdcfaadefc8de2d98687dfe229fc0b 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -200,6 +200,7 @@ public: virtual void ungetch() = 0; virtual bool peekPasting() { return false; } // true when about to see ## virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) + virtual bool isMacroInput() { return false; } // Will be called when we start reading tokens from this instance virtual void notifyActivated() {} @@ -306,6 +307,7 @@ protected: void ungetChar() { inputStack.back()->ungetch(); } bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } + bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } static const int maxIfNesting = 64; @@ -329,6 +331,7 @@ protected: virtual void ungetch() override { assert(0); } bool peekPasting() override { return prepaste; } bool endOfReplacementList() override { return mac->body.atEnd(); } + bool isMacroInput() override { return true; } MacroSymbol *mac; TVector<TokenStream*> args;