namespace pp\r
{\r
\r
-class DefinedParser : public Lexer\r
-{\r
- public:\r
- DefinedParser(Lexer* lexer,\r
- const MacroSet* macroSet,\r
- Diagnostics* diagnostics) :\r
- mLexer(lexer),\r
- mMacroSet(macroSet),\r
- mDiagnostics(diagnostics)\r
- {\r
- }\r
-\r
- protected:\r
- virtual void lex(Token* token)\r
- {\r
- static const std::string kDefined("defined");\r
-\r
- mLexer->lex(token);\r
- if (token->type != Token::IDENTIFIER)\r
- return;\r
- if (token->text != kDefined)\r
- return;\r
-\r
- bool paren = false;\r
- mLexer->lex(token);\r
- if (token->type == '(')\r
- {\r
- paren = true;\r
- mLexer->lex(token);\r
- }\r
-\r
- if (token->type != Token::IDENTIFIER)\r
- {\r
- mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,\r
- token->location, token->text);\r
- skipUntilEOD(mLexer, token);\r
- return;\r
- }\r
- MacroSet::const_iterator iter = mMacroSet->find(token->text);\r
- std::string expression = iter != mMacroSet->end() ? "1" : "0";\r
-\r
- if (paren)\r
- {\r
- mLexer->lex(token);\r
- if (token->type != ')')\r
- {\r
- mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,\r
- token->location, token->text);\r
- skipUntilEOD(mLexer, token);\r
- return;\r
- }\r
- }\r
-\r
- // We have a valid defined operator.\r
- // Convert the current token into a CONST_INT token.\r
- token->type = Token::CONST_INT;\r
- token->text = expression;\r
- }\r
-\r
- private:\r
- Lexer* mLexer;\r
- const MacroSet* mMacroSet;\r
- Diagnostics* mDiagnostics;\r
-};\r
-\r
DirectiveParser::DirectiveParser(Tokenizer* tokenizer,\r
MacroSet* macroSet,\r
Diagnostics* diagnostics,\r
int line = 0, file = 0;\r
int state = LINE_NUMBER;\r
\r
- MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);\r
+ MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);\r
macroExpander.lex(token);\r
while ((token->type != '\n') && (token->type != Token::LAST))\r
{\r
assert((getDirective(token) == DIRECTIVE_IF) ||\r
(getDirective(token) == DIRECTIVE_ELIF));\r
\r
- DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);\r
- MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);\r
+ MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);\r
ExpressionParser expressionParser(¯oExpander, mDiagnostics);\r
\r
int expression = 0;\r
\r
MacroExpander::MacroExpander(Lexer* lexer,\r
MacroSet* macroSet,\r
- Diagnostics* diagnostics) :\r
- mLexer(lexer),\r
- mMacroSet(macroSet),\r
- mDiagnostics(diagnostics)\r
+ Diagnostics* diagnostics,\r
+ bool parseDefined) :\r
+ mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined)\r
{\r
}\r
\r
if (token->type != Token::IDENTIFIER)\r
break;\r
\r
+ // Defined operator is parsed here since it may be generated by macro expansion.\r
+ // Defined operator produced by macro expansion has undefined behavior according to C++\r
+ // spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this\r
+ // behavior is needed for passing dEQP tests, which enforce stricter compatibility between\r
+ // implementations.\r
+ if (mParseDefined && token->text == "defined")\r
+ {\r
+ bool paren = false;\r
+ getToken(token);\r
+ if (token->type == '(')\r
+ {\r
+ paren = true;\r
+ getToken(token);\r
+ }\r
+ if (token->type != Token::IDENTIFIER)\r
+ {\r
+ mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location,\r
+ token->text);\r
+ break;\r
+ }\r
+ auto iter = mMacroSet->find(token->text);\r
+ std::string expression = iter != mMacroSet->end() ? "1" : "0";\r
+\r
+ if (paren)\r
+ {\r
+ getToken(token);\r
+ if (token->type != ')')\r
+ {\r
+ mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location,\r
+ token->text);\r
+ break;\r
+ }\r
+ }\r
+\r
+ // We have a valid defined operator.\r
+ // Convert the current token into a CONST_INT token.\r
+ token->type = Token::CONST_INT;\r
+ token->text = expression;\r
+ break;\r
+ }\r
+\r
if (token->expansionDisabled())\r
break;\r
\r
{\r
MacroArg& arg = args->at(i);\r
TokenLexer lexer(&arg);\r
- MacroExpander expander(&lexer, mMacroSet, mDiagnostics);\r
+ MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);\r
\r
arg.clear();\r
expander.lex(&token);\r
class MacroExpander : public Lexer\r
{\r
public:\r
- MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics);\r
+ MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics, bool parseDefined);\r
virtual ~MacroExpander();\r
\r
virtual void lex(Token* token);\r
Lexer* mLexer;\r
MacroSet* mMacroSet;\r
Diagnostics* mDiagnostics;\r
+ const bool mParseDefined;\r
\r
std::auto_ptr<Token> mReserveToken;\r
std::vector<MacroContext*> mContextStack;\r
DirectiveParser directiveParser;\r
MacroExpander macroExpander;\r
\r
- PreprocessorImpl(Diagnostics* diag,\r
- DirectiveHandler* directiveHandler) :\r
+ PreprocessorImpl(Diagnostics* diag, DirectiveHandler* directiveHandler) :\r
diagnostics(diag),\r
tokenizer(diag),\r
directiveParser(&tokenizer, ¯oSet, diag, directiveHandler),\r
- macroExpander(&directiveParser, ¯oSet, diag)\r
+ macroExpander(&directiveParser, ¯oSet, diag, false)\r
{\r
}\r
};\r