Forbid defined operator generated by macro expansion
After lengthy debate, the GLES working group recommended that this
should be an error in WebGL, though old specs were not updated. Make
ANGLE follow the WebGL spec and generate an error in this case.
This is a partial revert of the patch which added support for defined
operator generated by macro expansion. The preprocessor unit tests
added by the reverted commit are kept, but their expectations are
changed.
This breaks some dEQP tests that are not in line with the WebGL spec.
BUG=angleproject:1335
TEST=angle_unittests, WebGL conformance tests
Change-Id: I7d8a1d42c61367197f2aed4ca4de9297cc48acfc
Reviewed-on: https://chromium-review.googlesource.com/352471
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/preprocessor/DirectiveParser.cpp b/src/compiler/preprocessor/DirectiveParser.cpp
index c1f202f..aceb3b2 100644
--- a/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/compiler/preprocessor/DirectiveParser.cpp
@@ -139,6 +139,66 @@
namespace pp
{
+class DefinedParser : public Lexer
+{
+ public:
+ DefinedParser(Lexer *lexer, const MacroSet *macroSet, Diagnostics *diagnostics)
+ : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics)
+ {
+ }
+
+ protected:
+ void lex(Token *token) override
+ {
+ const char kDefined[] = "defined";
+
+ mLexer->lex(token);
+ if (token->type != Token::IDENTIFIER)
+ return;
+ if (token->text != kDefined)
+ return;
+
+ bool paren = false;
+ mLexer->lex(token);
+ if (token->type == '(')
+ {
+ paren = true;
+ mLexer->lex(token);
+ }
+
+ if (token->type != Token::IDENTIFIER)
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
+ skipUntilEOD(mLexer, token);
+ return;
+ }
+ MacroSet::const_iterator iter = mMacroSet->find(token->text);
+ std::string expression = iter != mMacroSet->end() ? "1" : "0";
+
+ if (paren)
+ {
+ mLexer->lex(token);
+ if (token->type != ')')
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
+ skipUntilEOD(mLexer, token);
+ return;
+ }
+ }
+
+ // We have a valid defined operator.
+ // Convert the current token into a CONST_INT token.
+ token->type = Token::CONST_INT;
+ token->text = expression;
+ }
+
+ private:
+ Lexer *mLexer;
+ const MacroSet *mMacroSet;
+ Diagnostics *mDiagnostics;
+};
+
DirectiveParser::DirectiveParser(Tokenizer *tokenizer,
MacroSet *macroSet,
Diagnostics *diagnostics,
@@ -776,7 +836,7 @@
bool parsedFileNumber = false;
int line = 0, file = 0;
- MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
+ MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);
// Lex the first token after "#line" so we can check it for EOD.
macroExpander.lex(token);
@@ -885,7 +945,8 @@
assert((getDirective(token) == DIRECTIVE_IF) ||
(getDirective(token) == DIRECTIVE_ELIF));
- MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);
+ DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
+ MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
ExpressionParser expressionParser(¯oExpander, mDiagnostics);
int expression = 0;
diff --git a/src/compiler/preprocessor/MacroExpander.cpp b/src/compiler/preprocessor/MacroExpander.cpp
index e878ee3..3c0423e 100644
--- a/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/compiler/preprocessor/MacroExpander.cpp
@@ -46,11 +46,8 @@
TokenVector::const_iterator mIter;
};
-MacroExpander::MacroExpander(Lexer *lexer,
- MacroSet *macroSet,
- Diagnostics *diagnostics,
- bool parseDefined)
- : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined)
+MacroExpander::MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics)
+ : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics)
{
}
@@ -66,54 +63,11 @@
{
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;
@@ -367,7 +321,7 @@
{
MacroArg &arg = args->at(i);
TokenLexer lexer(&arg);
- MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
+ MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
arg.clear();
expander.lex(&token);
diff --git a/src/compiler/preprocessor/MacroExpander.h b/src/compiler/preprocessor/MacroExpander.h
index dc870f6..dbf9803 100644
--- a/src/compiler/preprocessor/MacroExpander.h
+++ b/src/compiler/preprocessor/MacroExpander.h
@@ -24,7 +24,7 @@
class MacroExpander : public Lexer
{
public:
- MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics, bool parseDefined);
+ MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics);
~MacroExpander() override;
void lex(Token *token) override;
@@ -81,7 +81,6 @@
Lexer *mLexer;
MacroSet *mMacroSet;
Diagnostics *mDiagnostics;
- bool mParseDefined;
std::unique_ptr<Token> mReserveToken;
std::vector<MacroContext *> mContextStack;
diff --git a/src/compiler/preprocessor/Preprocessor.cpp b/src/compiler/preprocessor/Preprocessor.cpp
index aeb9c46..2fa87fe 100644
--- a/src/compiler/preprocessor/Preprocessor.cpp
+++ b/src/compiler/preprocessor/Preprocessor.cpp
@@ -30,7 +30,7 @@
: diagnostics(diag),
tokenizer(diag),
directiveParser(&tokenizer, ¯oSet, diag, directiveHandler),
- macroExpander(&directiveParser, ¯oSet, diag, false)
+ macroExpander(&directiveParser, ¯oSet, diag)
{
}
};