summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp68
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 &macro,
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 &macro,
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 &macro,
repl.setAtStartOfLine(identifier.atStartOfLine());
repl.setHasLeadingSpace(identifier.hasLeadingSpace());
}
- repl.location = identifier.location;
+ repl.location = replacementLocation;
}
return true;
}
bool MacroExpander::collectMacroArgs(const Macro &macro,
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 &macro,
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 &macro,
{
MacroArg &arg = args->at(i);
TokenLexer lexer(&arg);
- MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
+ MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
arg.clear();
expander.lex(&token);