diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp index 69e2f39069..e878ee345a 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -26,7 +26,7 @@ class TokenLexer : public Lexer mIter = mTokens.begin(); } - virtual void lex(Token *token) + void lex(Token *token) override { if (mIter == mTokens.end()) { @@ -48,10 +48,9 @@ class TokenLexer : public Lexer MacroExpander::MacroExpander(Lexer *lexer, MacroSet *macroSet, - Diagnostics *diagnostics) - : mLexer(lexer), - mMacroSet(macroSet), - mDiagnostics(diagnostics) + Diagnostics *diagnostics, + bool parseDefined) + : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined) { } @@ -67,11 +66,54 @@ void MacroExpander::lex(Token *token) { while (true) { + const char kDefined[] = "defined"; + getToken(token); if (token->type != Token::IDENTIFIER) break; + // Defined operator is parsed here since it may be generated by macro expansion. + // Defined operator produced by macro expansion has undefined behavior according to C++ + // spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this + // behavior is needed for passing dEQP tests, which enforce stricter compatibility between + // implementations. + if (mParseDefined && token->text == kDefined) + { + bool paren = false; + getToken(token); + if (token->type == '(') + { + paren = true; + getToken(token); + } + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, + token->text); + break; + } + auto iter = mMacroSet->find(token->text); + std::string expression = iter != mMacroSet->end() ? "1" : "0"; + + if (paren) + { + getToken(token); + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, + token->text); + break; + } + } + + // We have a valid defined operator. + // Convert the current token into a CONST_INT token. + token->type = Token::CONST_INT; + token->text = expression; + break; + } + if (token->expansionDisabled()) break; @@ -187,6 +229,12 @@ bool MacroExpander::expandMacro(const Macro ¯o, std::vector<Token> *replacements) { replacements->clear(); + + // In the case of an object-like macro, the replacement list gets its location + // from the identifier, but in the case of a function-like macro, the replacement + // list gets its location from the closing parenthesis of the macro invocation. + // This is tested by dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.* + SourceLocation replacementLocation = identifier.location; if (macro.type == Macro::kTypeObj) { replacements->assign(macro.replacements.begin(), @@ -218,7 +266,7 @@ bool MacroExpander::expandMacro(const Macro ¯o, assert(macro.type == Macro::kTypeFunc); std::vector<MacroArg> args; args.reserve(macro.parameters.size()); - if (!collectMacroArgs(macro, identifier, &args)) + if (!collectMacroArgs(macro, identifier, &args, &replacementLocation)) return false; replaceMacroParams(macro, args, replacements); @@ -234,14 +282,15 @@ bool MacroExpander::expandMacro(const Macro ¯o, repl.setAtStartOfLine(identifier.atStartOfLine()); repl.setHasLeadingSpace(identifier.hasLeadingSpace()); } - repl.location = identifier.location; + repl.location = replacementLocation; } return true; } bool MacroExpander::collectMacroArgs(const Macro ¯o, const Token &identifier, - std::vector<MacroArg> *args) + std::vector<MacroArg> *args, + SourceLocation *closingParenthesisLocation) { Token token; getToken(&token); @@ -271,6 +320,7 @@ bool MacroExpander::collectMacroArgs(const Macro ¯o, case ')': --openParens; isArg = openParens != 0; + *closingParenthesisLocation = token.location; break; case ',': // The individual arguments are separated by comma tokens, but @@ -317,7 +367,7 @@ bool MacroExpander::collectMacroArgs(const Macro ¯o, { MacroArg &arg = args->at(i); TokenLexer lexer(&arg); - MacroExpander expander(&lexer, mMacroSet, mDiagnostics); + MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined); arg.clear(); expander.lex(&token); |