summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/preprocessor
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/preprocessor')
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp214
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h17
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h6
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp630
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h24
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h8
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y85
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Input.cpp31
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Input.h26
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Lexer.h4
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp35
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Macro.h12
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp297
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h55
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp72
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h20
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h12
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Token.cpp21
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Token.h29
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h17
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l55
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h18
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h18
25 files changed, 938 insertions, 772 deletions
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
index 68c6e9cea4..c89bc9fa76 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -4,9 +4,9 @@
// found in the LICENSE file.
//
-#include "DiagnosticsBase.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
-#include <cassert>
+#include "common/debug.h"
namespace pp
{
@@ -15,122 +15,128 @@ Diagnostics::~Diagnostics()
{
}
-void Diagnostics::report(ID id,
- const SourceLocation &loc,
- const std::string &text)
+void Diagnostics::report(ID id, const SourceLocation &loc, const std::string &text)
{
- // TODO(alokp): Keep a count of errors and warnings.
print(id, loc, text);
}
-Diagnostics::Severity Diagnostics::severity(ID id)
+bool Diagnostics::isError(ID id)
{
if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END))
- return PP_ERROR;
+ return true;
if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
- return PP_WARNING;
+ return false;
- assert(false);
- return PP_ERROR;
+ UNREACHABLE();
+ return true;
}
-std::string Diagnostics::message(ID id)
+const char *Diagnostics::message(ID id)
{
switch (id)
{
- // Errors begin.
- case PP_INTERNAL_ERROR:
- return "internal error";
- case PP_OUT_OF_MEMORY:
- return "out of memory";
- case PP_INVALID_CHARACTER:
- return "invalid character";
- case PP_INVALID_NUMBER:
- return "invalid number";
- case PP_INTEGER_OVERFLOW:
- return "integer overflow";
- case PP_FLOAT_OVERFLOW:
- return "float overflow";
- case PP_TOKEN_TOO_LONG:
- return "token too long";
- case PP_INVALID_EXPRESSION:
- return "invalid expression";
- case PP_DIVISION_BY_ZERO:
- return "division by zero";
- case PP_EOF_IN_COMMENT:
- return "unexpected end of file found in comment";
- case PP_UNEXPECTED_TOKEN:
- return "unexpected token";
- case PP_DIRECTIVE_INVALID_NAME:
- return "invalid directive name";
- case PP_MACRO_NAME_RESERVED:
- return "macro name is reserved";
- case PP_MACRO_REDEFINED:
- return "macro redefined";
- case PP_MACRO_PREDEFINED_REDEFINED:
- return "predefined macro redefined";
- case PP_MACRO_PREDEFINED_UNDEFINED:
- return "predefined macro undefined";
- case PP_MACRO_UNTERMINATED_INVOCATION:
- return "unterminated macro invocation";
- case PP_MACRO_TOO_FEW_ARGS:
- return "Not enough arguments for macro";
- case PP_MACRO_TOO_MANY_ARGS:
- return "Too many arguments for macro";
- case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
- return "duplicate macro parameter name";
- case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
- return "unexpected #endif found without a matching #if";
- case PP_CONDITIONAL_ELSE_WITHOUT_IF:
- return "unexpected #else found without a matching #if";
- case PP_CONDITIONAL_ELSE_AFTER_ELSE:
- return "unexpected #else found after another #else";
- case PP_CONDITIONAL_ELIF_WITHOUT_IF:
- return "unexpected #elif found without a matching #if";
- case PP_CONDITIONAL_ELIF_AFTER_ELSE:
- return "unexpected #elif found after #else";
- case PP_CONDITIONAL_UNTERMINATED:
- return "unexpected end of file found in conditional block";
- case PP_INVALID_EXTENSION_NAME:
- return "invalid extension name";
- case PP_INVALID_EXTENSION_BEHAVIOR:
- return "invalid extension behavior";
- case PP_INVALID_EXTENSION_DIRECTIVE:
- return "invalid extension directive";
- case PP_INVALID_VERSION_NUMBER:
- return "invalid version number";
- case PP_INVALID_VERSION_DIRECTIVE:
- return "invalid version directive";
- case PP_VERSION_NOT_FIRST_STATEMENT:
- return "#version directive must occur before anything else, "
- "except for comments and white space";
- case PP_VERSION_NOT_FIRST_LINE_ESSL3:
- return "#version directive must occur on the first line of the shader";
- case PP_INVALID_LINE_NUMBER:
- return "invalid line number";
- case PP_INVALID_FILE_NUMBER:
- return "invalid file number";
- case PP_INVALID_LINE_DIRECTIVE:
- return "invalid line directive";
- case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
- return "extension directive must occur before any non-preprocessor tokens in ESSL3";
- // Errors end.
- // Warnings begin.
- case PP_EOF_IN_DIRECTIVE:
- return "unexpected end of file found in directive";
- case PP_CONDITIONAL_UNEXPECTED_TOKEN:
- return "unexpected token after conditional expression";
- case PP_UNRECOGNIZED_PRAGMA:
- return "unrecognized pragma";
- case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
- return "extension directive should occur before any non-preprocessor tokens";
- case PP_WARNING_MACRO_NAME_RESERVED:
- return "macro name with a double underscore is reserved - unintented behavior is possible";
- // Warnings end.
- default:
- assert(false);
- return "";
+ // Errors begin.
+ case PP_INTERNAL_ERROR:
+ return "internal error";
+ case PP_OUT_OF_MEMORY:
+ return "out of memory";
+ case PP_INVALID_CHARACTER:
+ return "invalid character";
+ case PP_INVALID_NUMBER:
+ return "invalid number";
+ case PP_INTEGER_OVERFLOW:
+ return "integer overflow";
+ case PP_FLOAT_OVERFLOW:
+ return "float overflow";
+ case PP_TOKEN_TOO_LONG:
+ return "token too long";
+ case PP_INVALID_EXPRESSION:
+ return "invalid expression";
+ case PP_DIVISION_BY_ZERO:
+ return "division by zero";
+ case PP_EOF_IN_COMMENT:
+ return "unexpected end of file found in comment";
+ case PP_UNEXPECTED_TOKEN:
+ return "unexpected token";
+ case PP_DIRECTIVE_INVALID_NAME:
+ return "invalid directive name";
+ case PP_MACRO_NAME_RESERVED:
+ return "macro name is reserved";
+ case PP_MACRO_REDEFINED:
+ return "macro redefined";
+ case PP_MACRO_PREDEFINED_REDEFINED:
+ return "predefined macro redefined";
+ case PP_MACRO_PREDEFINED_UNDEFINED:
+ return "predefined macro undefined";
+ case PP_MACRO_UNTERMINATED_INVOCATION:
+ return "unterminated macro invocation";
+ case PP_MACRO_UNDEFINED_WHILE_INVOKED:
+ return "macro undefined while being invoked";
+ case PP_MACRO_TOO_FEW_ARGS:
+ return "Not enough arguments for macro";
+ case PP_MACRO_TOO_MANY_ARGS:
+ return "Too many arguments for macro";
+ case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
+ return "duplicate macro parameter name";
+ case PP_MACRO_INVOCATION_CHAIN_TOO_DEEP:
+ return "macro invocation chain too deep";
+ case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
+ return "unexpected #endif found without a matching #if";
+ case PP_CONDITIONAL_ELSE_WITHOUT_IF:
+ return "unexpected #else found without a matching #if";
+ case PP_CONDITIONAL_ELSE_AFTER_ELSE:
+ return "unexpected #else found after another #else";
+ case PP_CONDITIONAL_ELIF_WITHOUT_IF:
+ return "unexpected #elif found without a matching #if";
+ case PP_CONDITIONAL_ELIF_AFTER_ELSE:
+ return "unexpected #elif found after #else";
+ case PP_CONDITIONAL_UNTERMINATED:
+ return "unexpected end of file found in conditional block";
+ case PP_INVALID_EXTENSION_NAME:
+ return "invalid extension name";
+ case PP_INVALID_EXTENSION_BEHAVIOR:
+ return "invalid extension behavior";
+ case PP_INVALID_EXTENSION_DIRECTIVE:
+ return "invalid extension directive";
+ case PP_INVALID_VERSION_NUMBER:
+ return "invalid version number";
+ case PP_INVALID_VERSION_DIRECTIVE:
+ return "invalid version directive";
+ case PP_VERSION_NOT_FIRST_STATEMENT:
+ return "#version directive must occur before anything else, "
+ "except for comments and white space";
+ case PP_VERSION_NOT_FIRST_LINE_ESSL3:
+ return "#version directive must occur on the first line of the shader";
+ case PP_INVALID_LINE_NUMBER:
+ return "invalid line number";
+ case PP_INVALID_FILE_NUMBER:
+ return "invalid file number";
+ case PP_INVALID_LINE_DIRECTIVE:
+ return "invalid line directive";
+ case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
+ return "extension directive must occur before any non-preprocessor tokens in ESSL3";
+ case PP_UNDEFINED_SHIFT:
+ return "shift exponent is negative or undefined";
+ case PP_TOKENIZER_ERROR:
+ return "internal tokenizer error";
+ // Errors end.
+ // Warnings begin.
+ case PP_EOF_IN_DIRECTIVE:
+ return "unexpected end of file found in directive";
+ case PP_CONDITIONAL_UNEXPECTED_TOKEN:
+ return "unexpected token after conditional expression";
+ case PP_UNRECOGNIZED_PRAGMA:
+ return "unrecognized pragma";
+ case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
+ return "extension directive should occur before any non-preprocessor tokens";
+ case PP_WARNING_MACRO_NAME_RESERVED:
+ return "macro name with a double underscore is reserved - unintented behavior is "
+ "possible";
+ // Warnings end.
+ default:
+ UNREACHABLE();
+ return "";
}
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
index d26c174f01..ea37614606 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
@@ -19,11 +19,6 @@ struct SourceLocation;
class Diagnostics
{
public:
- enum Severity
- {
- PP_ERROR,
- PP_WARNING
- };
enum ID
{
PP_ERROR_BEGIN,
@@ -44,9 +39,11 @@ class Diagnostics
PP_MACRO_PREDEFINED_REDEFINED,
PP_MACRO_PREDEFINED_UNDEFINED,
PP_MACRO_UNTERMINATED_INVOCATION,
+ PP_MACRO_UNDEFINED_WHILE_INVOKED,
PP_MACRO_TOO_FEW_ARGS,
PP_MACRO_TOO_MANY_ARGS,
PP_MACRO_DUPLICATE_PARAMETER_NAMES,
+ PP_MACRO_INVOCATION_CHAIN_TOO_DEEP,
PP_CONDITIONAL_ENDIF_WITHOUT_IF,
PP_CONDITIONAL_ELSE_WITHOUT_IF,
PP_CONDITIONAL_ELSE_AFTER_ELSE,
@@ -65,6 +62,8 @@ class Diagnostics
PP_INVALID_FILE_NUMBER,
PP_INVALID_LINE_DIRECTIVE,
PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+ PP_UNDEFINED_SHIFT,
+ PP_TOKENIZER_ERROR,
PP_ERROR_END,
PP_WARNING_BEGIN,
@@ -80,12 +79,10 @@ class Diagnostics
void report(ID id, const SourceLocation &loc, const std::string &text);
protected:
- Severity severity(ID id);
- std::string message(ID id);
+ bool isError(ID id);
+ const char *message(ID id);
- virtual void print(ID id,
- const SourceLocation &loc,
- const std::string &text) = 0;
+ virtual void print(ID id, const SourceLocation &loc, const std::string &text) = 0;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
index ef35c6ed50..049dae9071 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "DirectiveHandlerBase.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
namespace pp
{
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
index cf67895764..6c81d015f5 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
@@ -23,8 +23,7 @@ class DirectiveHandler
public:
virtual ~DirectiveHandler();
- virtual void handleError(const SourceLocation &loc,
- const std::string &msg) = 0;
+ virtual void handleError(const SourceLocation &loc, const std::string &msg) = 0;
// Handle pragma of form: #pragma name[(value)]
virtual void handlePragma(const SourceLocation &loc,
@@ -36,8 +35,7 @@ class DirectiveHandler
const std::string &name,
const std::string &behavior) = 0;
- virtual void handleVersion(const SourceLocation &loc,
- int version) = 0;
+ virtual void handleVersion(const SourceLocation &loc, int version) = 0;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
index 2faa331378..f6c5763990 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
@@ -4,21 +4,22 @@
// found in the LICENSE file.
//
-#include "DirectiveParser.h"
+#include "compiler/preprocessor/DirectiveParser.h"
#include <algorithm>
-#include <cassert>
#include <cstdlib>
#include <sstream>
-#include "DiagnosticsBase.h"
-#include "DirectiveHandlerBase.h"
-#include "ExpressionParser.h"
-#include "MacroExpander.h"
-#include "Token.h"
-#include "Tokenizer.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+#include "compiler/preprocessor/ExpressionParser.h"
+#include "compiler/preprocessor/MacroExpander.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
-namespace {
+namespace
+{
enum DirectiveType
{
DIRECTIVE_NONE,
@@ -39,19 +40,19 @@ enum DirectiveType
DirectiveType getDirective(const pp::Token *token)
{
- const char kDirectiveDefine[] = "define";
- const char kDirectiveUndef[] = "undef";
- const char kDirectiveIf[] = "if";
- const char kDirectiveIfdef[] = "ifdef";
- const char kDirectiveIfndef[] = "ifndef";
- const char kDirectiveElse[] = "else";
- const char kDirectiveElif[] = "elif";
- const char kDirectiveEndif[] = "endif";
- const char kDirectiveError[] = "error";
- const char kDirectivePragma[] = "pragma";
+ const char kDirectiveDefine[] = "define";
+ const char kDirectiveUndef[] = "undef";
+ const char kDirectiveIf[] = "if";
+ const char kDirectiveIfdef[] = "ifdef";
+ const char kDirectiveIfndef[] = "ifndef";
+ const char kDirectiveElse[] = "else";
+ const char kDirectiveElif[] = "elif";
+ const char kDirectiveEndif[] = "endif";
+ const char kDirectiveError[] = "error";
+ const char kDirectivePragma[] = "pragma";
const char kDirectiveExtension[] = "extension";
- const char kDirectiveVersion[] = "version";
- const char kDirectiveLine[] = "line";
+ const char kDirectiveVersion[] = "version";
+ const char kDirectiveLine[] = "line";
if (token->type != pp::Token::IDENTIFIER)
return DIRECTIVE_NONE;
@@ -90,15 +91,15 @@ bool isConditionalDirective(DirectiveType directive)
{
switch (directive)
{
- case DIRECTIVE_IF:
- case DIRECTIVE_IFDEF:
- case DIRECTIVE_IFNDEF:
- case DIRECTIVE_ELSE:
- case DIRECTIVE_ELIF:
- case DIRECTIVE_ENDIF:
- return true;
- default:
- return false;
+ case DIRECTIVE_IF:
+ case DIRECTIVE_IFDEF:
+ case DIRECTIVE_IFNDEF:
+ case DIRECTIVE_ELSE:
+ case DIRECTIVE_ELIF:
+ case DIRECTIVE_ENDIF:
+ return true;
+ default:
+ return false;
}
}
@@ -110,7 +111,7 @@ bool isEOD(const pp::Token *token)
void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
{
- while(!isEOD(token))
+ while (!isEOD(token))
{
lexer->lex(token);
}
@@ -118,8 +119,8 @@ void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
bool isMacroNameReserved(const std::string &name)
{
- // Names prefixed with "GL_" are reserved.
- return (name.substr(0, 3) == "GL_");
+ // Names prefixed with "GL_" and the name "defined" are reserved.
+ return name == "defined" || (name.substr(0, 3) == "GL_");
}
bool hasDoubleUnderscores(const std::string &name)
@@ -127,11 +128,10 @@ bool hasDoubleUnderscores(const std::string &name)
return (name.find("__") != std::string::npos);
}
-bool isMacroPredefined(const std::string &name,
- const pp::MacroSet &macroSet)
+bool isMacroPredefined(const std::string &name, const pp::MacroSet &macroSet)
{
pp::MacroSet::const_iterator iter = macroSet.find(name);
- return iter != macroSet.end() ? iter->second.predefined : false;
+ return iter != macroSet.end() ? iter->second->predefined : false;
}
} // namespace anonymous
@@ -139,17 +139,83 @@ bool isMacroPredefined(const std::string &name,
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,
- DirectiveHandler *directiveHandler)
+ DirectiveHandler *directiveHandler,
+ int maxMacroExpansionDepth)
: mPastFirstStatement(false),
mSeenNonPreprocessorToken(false),
mTokenizer(tokenizer),
mMacroSet(macroSet),
mDiagnostics(diagnostics),
mDirectiveHandler(directiveHandler),
- mShaderVersion(100)
+ mShaderVersion(100),
+ mMaxMacroExpansionDepth(maxMacroExpansionDepth)
+{
+}
+
+DirectiveParser::~DirectiveParser()
{
}
@@ -174,21 +240,20 @@ void DirectiveParser::lex(Token *token)
if (!mConditionalStack.empty())
{
const ConditionalBlock &block = mConditionalStack.back();
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED,
- block.location, block.type);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED, block.location,
+ block.type);
}
break;
}
- }
- while (skipping() || (token->type == '\n'));
+ } while (skipping() || (token->type == '\n'));
mPastFirstStatement = true;
}
void DirectiveParser::parseDirective(Token *token)
{
- assert(token->type == Token::PP_HASH);
+ ASSERT(token->type == Token::PP_HASH);
mTokenizer->lex(token);
if (isEOD(token))
@@ -207,86 +272,83 @@ void DirectiveParser::parseDirective(Token *token)
return;
}
- switch(directive)
+ switch (directive)
{
- case DIRECTIVE_NONE:
- mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME,
- token->location, token->text);
- skipUntilEOD(mTokenizer, token);
- break;
- case DIRECTIVE_DEFINE:
- parseDefine(token);
- break;
- case DIRECTIVE_UNDEF:
- parseUndef(token);
- break;
- case DIRECTIVE_IF:
- parseIf(token);
- break;
- case DIRECTIVE_IFDEF:
- parseIfdef(token);
- break;
- case DIRECTIVE_IFNDEF:
- parseIfndef(token);
- break;
- case DIRECTIVE_ELSE:
- parseElse(token);
- break;
- case DIRECTIVE_ELIF:
- parseElif(token);
- break;
- case DIRECTIVE_ENDIF:
- parseEndif(token);
- break;
- case DIRECTIVE_ERROR:
- parseError(token);
- break;
- case DIRECTIVE_PRAGMA:
- parsePragma(token);
- break;
- case DIRECTIVE_EXTENSION:
- parseExtension(token);
- break;
- case DIRECTIVE_VERSION:
- parseVersion(token);
- break;
- case DIRECTIVE_LINE:
- parseLine(token);
- break;
- default:
- assert(false);
- break;
+ case DIRECTIVE_NONE:
+ mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME, token->location,
+ token->text);
+ skipUntilEOD(mTokenizer, token);
+ break;
+ case DIRECTIVE_DEFINE:
+ parseDefine(token);
+ break;
+ case DIRECTIVE_UNDEF:
+ parseUndef(token);
+ break;
+ case DIRECTIVE_IF:
+ parseIf(token);
+ break;
+ case DIRECTIVE_IFDEF:
+ parseIfdef(token);
+ break;
+ case DIRECTIVE_IFNDEF:
+ parseIfndef(token);
+ break;
+ case DIRECTIVE_ELSE:
+ parseElse(token);
+ break;
+ case DIRECTIVE_ELIF:
+ parseElif(token);
+ break;
+ case DIRECTIVE_ENDIF:
+ parseEndif(token);
+ break;
+ case DIRECTIVE_ERROR:
+ parseError(token);
+ break;
+ case DIRECTIVE_PRAGMA:
+ parsePragma(token);
+ break;
+ case DIRECTIVE_EXTENSION:
+ parseExtension(token);
+ break;
+ case DIRECTIVE_VERSION:
+ parseVersion(token);
+ break;
+ case DIRECTIVE_LINE:
+ parseLine(token);
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
skipUntilEOD(mTokenizer, token);
if (token->type == Token::LAST)
{
- mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE, token->location, token->text);
}
}
void DirectiveParser::parseDefine(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_DEFINE);
+ ASSERT(getDirective(token) == DIRECTIVE_DEFINE);
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
return;
}
if (isMacroPredefined(token->text, *mMacroSet))
{
- mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED, token->location,
+ token->text);
return;
}
if (isMacroNameReserved(token->text))
{
- mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED, token->location, token->text);
return;
}
// Using double underscores is allowed, but may result in unintended
@@ -300,39 +362,37 @@ void DirectiveParser::parseDefine(Token *token)
token->text);
}
- Macro macro;
- macro.type = Macro::kTypeObj;
- macro.name = token->text;
+ std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+ macro->type = Macro::kTypeObj;
+ macro->name = token->text;
mTokenizer->lex(token);
if (token->type == '(' && !token->hasLeadingSpace())
{
// Function-like macro. Collect arguments.
- macro.type = Macro::kTypeFunc;
+ macro->type = Macro::kTypeFunc;
do
{
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
break;
- if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end())
+ if (std::find(macro->parameters.begin(), macro->parameters.end(), token->text) !=
+ macro->parameters.end())
{
mDiagnostics->report(Diagnostics::PP_MACRO_DUPLICATE_PARAMETER_NAMES,
token->location, token->text);
return;
}
- macro.parameters.push_back(token->text);
+ macro->parameters.push_back(token->text);
mTokenizer->lex(token); // Get ','.
- }
- while (token->type == ',');
+ } while (token->type == ',');
if (token->type != ')')
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location,
- token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
return;
}
mTokenizer->lex(token); // Get ')'.
@@ -344,47 +404,51 @@ void DirectiveParser::parseDefine(Token *token)
// list. Resetting it also allows us to reuse Token::equals() to
// compare macros.
token->location = SourceLocation();
- macro.replacements.push_back(*token);
+ macro->replacements.push_back(*token);
mTokenizer->lex(token);
}
- if (!macro.replacements.empty())
+ if (!macro->replacements.empty())
{
// Whitespace preceding the replacement list is not considered part of
// the replacement list for either form of macro.
- macro.replacements.front().setHasLeadingSpace(false);
+ macro->replacements.front().setHasLeadingSpace(false);
}
// Check for macro redefinition.
- MacroSet::const_iterator iter = mMacroSet->find(macro.name);
- if (iter != mMacroSet->end() && !macro.equals(iter->second))
+ MacroSet::const_iterator iter = mMacroSet->find(macro->name);
+ if (iter != mMacroSet->end() && !macro->equals(*iter->second))
{
- mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED,
- token->location,
- macro.name);
+ mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED, token->location, macro->name);
return;
}
- mMacroSet->insert(std::make_pair(macro.name, macro));
+ mMacroSet->insert(std::make_pair(macro->name, macro));
}
void DirectiveParser::parseUndef(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_UNDEF);
+ ASSERT(getDirective(token) == DIRECTIVE_UNDEF);
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
return;
}
MacroSet::iterator iter = mMacroSet->find(token->text);
if (iter != mMacroSet->end())
{
- if (iter->second.predefined)
+ if (iter->second->predefined)
{
- mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED, token->location,
+ token->text);
+ return;
+ }
+ else if (iter->second->expansionCount > 0)
+ {
+ mDiagnostics->report(Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED, token->location,
+ token->text);
+ return;
}
else
{
@@ -395,38 +459,37 @@ void DirectiveParser::parseUndef(Token *token)
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
skipUntilEOD(mTokenizer, token);
}
}
void DirectiveParser::parseIf(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_IF);
+ ASSERT(getDirective(token) == DIRECTIVE_IF);
parseConditionalIf(token);
}
void DirectiveParser::parseIfdef(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_IFDEF);
+ ASSERT(getDirective(token) == DIRECTIVE_IFDEF);
parseConditionalIf(token);
}
void DirectiveParser::parseIfndef(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_IFNDEF);
+ ASSERT(getDirective(token) == DIRECTIVE_IFNDEF);
parseConditionalIf(token);
}
void DirectiveParser::parseElse(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ELSE);
+ ASSERT(getDirective(token) == DIRECTIVE_ELSE);
if (mConditionalStack.empty())
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -440,34 +503,34 @@ void DirectiveParser::parseElse(Token *token)
}
if (block.foundElseGroup)
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
- block.foundElseGroup = true;
- block.skipGroup = block.foundValidGroup;
+ block.foundElseGroup = true;
+ block.skipGroup = block.foundValidGroup;
block.foundValidGroup = true;
// Check if there are extra tokens after #else.
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
}
void DirectiveParser::parseElif(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ELIF);
+ ASSERT(getDirective(token) == DIRECTIVE_ELIF);
if (mConditionalStack.empty())
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -481,8 +544,8 @@ void DirectiveParser::parseElif(Token *token)
}
if (block.foundElseGroup)
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -495,19 +558,19 @@ void DirectiveParser::parseElif(Token *token)
return;
}
- int expression = parseExpressionIf(token);
- block.skipGroup = expression == 0;
+ int expression = parseExpressionIf(token);
+ block.skipGroup = expression == 0;
block.foundValidGroup = expression != 0;
}
void DirectiveParser::parseEndif(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ENDIF);
+ ASSERT(getDirective(token) == DIRECTIVE_ENDIF);
if (mConditionalStack.empty())
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -518,15 +581,15 @@ void DirectiveParser::parseEndif(Token *token)
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
}
void DirectiveParser::parseError(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ERROR);
+ ASSERT(getDirective(token) == DIRECTIVE_ERROR);
std::ostringstream stream;
mTokenizer->lex(token);
@@ -541,7 +604,7 @@ void DirectiveParser::parseError(Token *token)
// Parses pragma of form: #pragma name[(value)].
void DirectiveParser::parsePragma(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_PRAGMA);
+ ASSERT(getDirective(token) == DIRECTIVE_PRAGMA);
enum State
{
@@ -563,25 +626,25 @@ void DirectiveParser::parsePragma(Token *token)
}
while ((token->type != '\n') && (token->type != Token::LAST))
{
- switch(state++)
+ switch (state++)
{
- case PRAGMA_NAME:
- name = token->text;
- valid = valid && (token->type == Token::IDENTIFIER);
- break;
- case LEFT_PAREN:
- valid = valid && (token->type == '(');
- break;
- case PRAGMA_VALUE:
- value = token->text;
- valid = valid && (token->type == Token::IDENTIFIER);
- break;
- case RIGHT_PAREN:
- valid = valid && (token->type == ')');
- break;
- default:
- valid = false;
- break;
+ case PRAGMA_NAME:
+ name = token->text;
+ valid = valid && (token->type == Token::IDENTIFIER);
+ break;
+ case LEFT_PAREN:
+ valid = valid && (token->type == '(');
+ break;
+ case PRAGMA_VALUE:
+ value = token->text;
+ valid = valid && (token->type == Token::IDENTIFIER);
+ break;
+ case RIGHT_PAREN:
+ valid = valid && (token->type == ')');
+ break;
+ default:
+ valid = false;
+ break;
}
mTokenizer->lex(token);
}
@@ -591,8 +654,7 @@ void DirectiveParser::parsePragma(Token *token)
(state == RIGHT_PAREN + 1)); // With value.
if (!valid)
{
- mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA,
- token->location, name);
+ mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA, token->location, name);
}
else if (state > PRAGMA_NAME) // Do not notify for empty pragma.
{
@@ -602,7 +664,7 @@ void DirectiveParser::parsePragma(Token *token)
void DirectiveParser::parseExtension(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_EXTENSION);
+ ASSERT(getDirective(token) == DIRECTIVE_EXTENSION);
enum State
{
@@ -620,47 +682,49 @@ void DirectiveParser::parseExtension(Token *token)
{
switch (state++)
{
- case EXT_NAME:
- if (valid && (token->type != Token::IDENTIFIER))
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME,
- token->location, token->text);
- valid = false;
- }
- if (valid) name = token->text;
- break;
- case COLON:
- if (valid && (token->type != ':'))
- {
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
- valid = false;
- }
- break;
- case EXT_BEHAVIOR:
- if (valid && (token->type != Token::IDENTIFIER))
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
- token->location, token->text);
- valid = false;
- }
- if (valid) behavior = token->text;
- break;
- default:
- if (valid)
- {
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
- valid = false;
- }
- break;
+ case EXT_NAME:
+ if (valid && (token->type != Token::IDENTIFIER))
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME, token->location,
+ token->text);
+ valid = false;
+ }
+ if (valid)
+ name = token->text;
+ break;
+ case COLON:
+ if (valid && (token->type != ':'))
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
+ valid = false;
+ }
+ break;
+ case EXT_BEHAVIOR:
+ if (valid && (token->type != Token::IDENTIFIER))
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
+ token->location, token->text);
+ valid = false;
+ }
+ if (valid)
+ behavior = token->text;
+ break;
+ default:
+ if (valid)
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
+ valid = false;
+ }
+ break;
}
mTokenizer->lex(token);
}
if (valid && (state != EXT_BEHAVIOR + 1))
{
- mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE, token->location,
+ token->text);
valid = false;
}
if (valid && mSeenNonPreprocessorToken)
@@ -683,12 +747,12 @@ void DirectiveParser::parseExtension(Token *token)
void DirectiveParser::parseVersion(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_VERSION);
+ ASSERT(getDirective(token) == DIRECTIVE_VERSION);
if (mPastFirstStatement)
{
- mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -700,47 +764,47 @@ void DirectiveParser::parseVersion(Token *token)
VERSION_ENDLINE
};
- bool valid = true;
+ bool valid = true;
int version = 0;
- int state = VERSION_NUMBER;
+ int state = VERSION_NUMBER;
mTokenizer->lex(token);
while (valid && (token->type != '\n') && (token->type != Token::LAST))
{
switch (state)
{
- case VERSION_NUMBER:
- if (token->type != Token::CONST_INT)
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER,
- token->location, token->text);
- valid = false;
- }
- if (valid && !token->iValue(&version))
- {
- mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
- token->location, token->text);
- valid = false;
- }
- if (valid)
- {
- state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
- }
- break;
- case VERSION_PROFILE:
- if (token->type != Token::IDENTIFIER || token->text != "es")
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
- token->location, token->text);
+ case VERSION_NUMBER:
+ if (token->type != Token::CONST_INT)
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER, token->location,
+ token->text);
+ valid = false;
+ }
+ if (valid && !token->iValue(&version))
+ {
+ mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location,
+ token->text);
+ valid = false;
+ }
+ if (valid)
+ {
+ state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
+ }
+ break;
+ case VERSION_PROFILE:
+ if (token->type != Token::IDENTIFIER || token->text != "es")
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
+ token->text);
+ valid = false;
+ }
+ state = VERSION_ENDLINE;
+ break;
+ default:
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
valid = false;
- }
- state = VERSION_ENDLINE;
- break;
- default:
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
- valid = false;
- break;
+ break;
}
mTokenizer->lex(token);
@@ -748,15 +812,15 @@ void DirectiveParser::parseVersion(Token *token)
if (valid && (state != VERSION_ENDLINE))
{
- mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
+ token->text);
valid = false;
}
if (valid && version >= 300 && token->location.line > 1)
{
- mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3, token->location,
+ token->text);
valid = false;
}
@@ -770,13 +834,13 @@ void DirectiveParser::parseVersion(Token *token)
void DirectiveParser::parseLine(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_LINE);
+ ASSERT(getDirective(token) == DIRECTIVE_LINE);
- bool valid = true;
+ bool valid = true;
bool parsedFileNumber = false;
int line = 0, file = 0;
- MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
+ MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, mMaxMacroExpansionDepth);
// Lex the first token after "#line" so we can check it for EOD.
macroExpander.lex(token);
@@ -814,8 +878,8 @@ void DirectiveParser::parseLine(Token *token)
{
if (valid)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
valid = false;
}
skipUntilEOD(mTokenizer, token);
@@ -835,14 +899,14 @@ bool DirectiveParser::skipping() const
if (mConditionalStack.empty())
return false;
- const ConditionalBlock& block = mConditionalStack.back();
+ const ConditionalBlock &block = mConditionalStack.back();
return block.skipBlock || block.skipGroup;
}
void DirectiveParser::parseConditionalIf(Token *token)
{
ConditionalBlock block;
- block.type = token->text;
+ block.type = token->text;
block.location = token->location;
if (skipping())
@@ -861,20 +925,20 @@ void DirectiveParser::parseConditionalIf(Token *token)
int expression = 0;
switch (directive)
{
- case DIRECTIVE_IF:
- expression = parseExpressionIf(token);
- break;
- case DIRECTIVE_IFDEF:
- expression = parseExpressionIfdef(token);
- break;
- case DIRECTIVE_IFNDEF:
- expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
- break;
- default:
- assert(false);
- break;
+ case DIRECTIVE_IF:
+ expression = parseExpressionIf(token);
+ break;
+ case DIRECTIVE_IFDEF:
+ expression = parseExpressionIfdef(token);
+ break;
+ case DIRECTIVE_IFNDEF:
+ expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
- block.skipGroup = expression == 0;
+ block.skipGroup = expression == 0;
block.foundValidGroup = expression != 0;
}
mConditionalStack.push_back(block);
@@ -882,16 +946,16 @@ void DirectiveParser::parseConditionalIf(Token *token)
int DirectiveParser::parseExpressionIf(Token *token)
{
- assert((getDirective(token) == DIRECTIVE_IF) ||
- (getDirective(token) == DIRECTIVE_ELIF));
+ 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, mMaxMacroExpansionDepth);
ExpressionParser expressionParser(&macroExpander, mDiagnostics);
int expression = 0;
ExpressionParser::ErrorSettings errorSettings;
errorSettings.integerLiteralsMustFit32BitSignedRange = false;
- errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
+ errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
bool valid = true;
expressionParser.parse(token, &expression, false, errorSettings, &valid);
@@ -899,8 +963,8 @@ int DirectiveParser::parseExpressionIf(Token *token)
// Check if there are tokens after #if expression.
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
@@ -909,27 +973,25 @@ int DirectiveParser::parseExpressionIf(Token *token)
int DirectiveParser::parseExpressionIfdef(Token *token)
{
- assert((getDirective(token) == DIRECTIVE_IFDEF) ||
- (getDirective(token) == DIRECTIVE_IFNDEF));
+ ASSERT((getDirective(token) == DIRECTIVE_IFDEF) || (getDirective(token) == DIRECTIVE_IFNDEF));
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
skipUntilEOD(mTokenizer, token);
return 0;
}
MacroSet::const_iterator iter = mMacroSet->find(token->text);
- int expression = iter != mMacroSet->end() ? 1 : 0;
+ int expression = iter != mMacroSet->end() ? 1 : 0;
// Check if there are tokens after #ifdef expression.
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
return expression;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
index 2888e289ce..29c30a8239 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
@@ -7,10 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
-#include "Lexer.h"
-#include "Macro.h"
-#include "pp_utils.h"
-#include "SourceLocation.h"
+#include "compiler/preprocessor/Lexer.h"
+#include "compiler/preprocessor/Macro.h"
+#include "compiler/preprocessor/SourceLocation.h"
namespace pp
{
@@ -25,13 +24,13 @@ class DirectiveParser : public Lexer
DirectiveParser(Tokenizer *tokenizer,
MacroSet *macroSet,
Diagnostics *diagnostics,
- DirectiveHandler *directiveHandler);
+ DirectiveHandler *directiveHandler,
+ int maxMacroExpansionDepth);
+ ~DirectiveParser() override;
void lex(Token *token) override;
private:
- PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
-
void parseDirective(Token *token);
void parseDefine(Token *token);
void parseUndef(Token *token);
@@ -62,22 +61,21 @@ class DirectiveParser : public Lexer
bool foundElseGroup;
ConditionalBlock()
- : skipBlock(false),
- skipGroup(false),
- foundValidGroup(false),
- foundElseGroup(false)
+ : skipBlock(false), skipGroup(false), foundValidGroup(false), foundElseGroup(false)
{
}
};
bool mPastFirstStatement;
- bool mSeenNonPreprocessorToken; // Tracks if a non-preprocessor token has been seen yet. Some macros, such as
- // #extension must be declared before all shader code.
+ bool mSeenNonPreprocessorToken; // Tracks if a non-preprocessor token has been seen yet. Some
+ // macros, such as
+ // #extension must be declared before all shader code.
std::vector<ConditionalBlock> mConditionalStack;
Tokenizer *mTokenizer;
MacroSet *mMacroSet;
Diagnostics *mDiagnostics;
DirectiveHandler *mDirectiveHandler;
int mShaderVersion;
+ int mMaxMacroExpansionDepth;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
index 841c67b61c..0f2901b878 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
@@ -7,8 +7,8 @@
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
-#include "DiagnosticsBase.h"
-#include "pp_utils.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
namespace pp
{
@@ -16,7 +16,7 @@ namespace pp
class Lexer;
struct Token;
-class ExpressionParser
+class ExpressionParser : angle::NonCopyable
{
public:
struct ErrorSettings
@@ -34,8 +34,6 @@ class ExpressionParser
bool *valid);
private:
- PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
-
Lexer *mLexer;
Diagnostics *mDiagnostics;
};
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
index 7b5d9e9cee..68d7cc3958 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
+++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
@@ -41,17 +41,15 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#include <cassert>
#include <sstream>
+#include <stdint.h>
#include "DiagnosticsBase.h"
#include "Lexer.h"
#include "Token.h"
+#include "common/mathutil.h"
-#if defined(_MSC_VER)
-typedef __int64 YYSTYPE;
-#else
-#include <stdint.h>
-typedef intmax_t YYSTYPE;
-#endif // _MSC_VER
+typedef int32_t YYSTYPE;
+typedef uint32_t UNSIGNED_TYPE;
#define YYENABLE_NLS 0
#define YYLTYPE_IS_TRIVIAL 1
@@ -196,16 +194,57 @@ expression
$$ = $1 < $3;
}
| expression TOK_OP_RIGHT expression {
- $$ = $1 >> $3;
+ if ($3 < 0 || $3 > 31)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << $1 << " >> " << $3;
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location,
+ text.c_str());
+ *(context->valid) = false;
+ }
+ $$ = static_cast<YYSTYPE>(0);
+ }
+ else if ($1 < 0)
+ {
+ // Logical shift right.
+ $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) >> $3);
+ }
+ else
+ {
+ $$ = $1 >> $3;
+ }
}
| expression TOK_OP_LEFT expression {
- $$ = $1 << $3;
+ if ($3 < 0 || $3 > 31)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << $1 << " << " << $3;
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location,
+ text.c_str());
+ *(context->valid) = false;
+ }
+ $$ = static_cast<YYSTYPE>(0);
+ }
+ else
+ {
+ // Logical shift left. Casting to unsigned is needed to ensure there's no signed integer
+ // overflow, which some tools treat as an error.
+ $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3);
+ }
}
| expression '-' expression {
- $$ = $1 - $3;
+ $$ = gl::WrappingDiff<YYSTYPE>($1, $3);
}
| expression '+' expression {
- $$ = $1 + $3;
+ $$ = gl::WrappingSum<YYSTYPE>($1, $3);
}
| expression '%' expression {
if ($3 == 0)
@@ -222,6 +261,12 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
+ else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+ {
+ // Check for the special case where the minimum representable number is
+ // divided by -1. If left alone this has undefined results.
+ $$ = 0;
+ }
else
{
$$ = $1 % $3;
@@ -242,13 +287,20 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
+ else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+ {
+ // Check for the special case where the minimum representable number is
+ // divided by -1. If left alone this leads to integer overflow in C++, which
+ // has undefined results.
+ $$ = std::numeric_limits<YYSTYPE>::max();
+ }
else
{
$$ = $1 / $3;
}
}
| expression '*' expression {
- $$ = $1 * $3;
+ $$ = gl::WrappingMul($1, $3);
}
| '!' expression %prec TOK_UNARY {
$$ = ! $2;
@@ -257,7 +309,16 @@ expression
$$ = ~ $2;
}
| '-' expression %prec TOK_UNARY {
- $$ = - $2;
+ // Check for negation of minimum representable integer to prevent undefined signed int
+ // overflow.
+ if ($2 == std::numeric_limits<YYSTYPE>::min())
+ {
+ $$ = std::numeric_limits<YYSTYPE>::min();
+ }
+ else
+ {
+ $$ = -$2;
+ }
}
| '+' expression %prec TOK_UNARY {
$$ = + $2;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp
index 5541d46f72..0f2327b823 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp
@@ -4,12 +4,13 @@
// found in the LICENSE file.
//
-#include "Input.h"
+#include "compiler/preprocessor/Input.h"
#include <algorithm>
-#include <cassert>
#include <cstring>
+#include "common/debug.h"
+
namespace pp
{
@@ -17,9 +18,12 @@ Input::Input() : mCount(0), mString(0)
{
}
-Input::Input(size_t count, const char *const string[], const int length[]) :
- mCount(count),
- mString(string)
+Input::~Input()
+{
+}
+
+Input::Input(size_t count, const char *const string[], const int length[])
+ : mCount(count), mString(string)
{
mLength.reserve(mCount);
for (size_t i = 0; i < mCount; ++i)
@@ -32,7 +36,7 @@ Input::Input(size_t count, const char *const string[], const int length[]) :
const char *Input::skipChar()
{
// This function should only be called when there is a character to skip.
- assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
+ ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
++mReadLoc.cIndex;
if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
{
@@ -61,6 +65,11 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
{
// Line continuation of backslash + newline.
skipChar();
+ // Fake an EOF if the line number would overflow.
+ if (*lineNo == INT_MAX)
+ {
+ return 0;
+ }
++(*lineNo);
}
else if (c != nullptr && (*c) == '\r')
@@ -71,6 +80,11 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
{
skipChar();
}
+ // Fake an EOF if the line number would overflow.
+ if (*lineNo == INT_MAX)
+ {
+ return 0;
+ }
++(*lineNo);
}
else
@@ -86,7 +100,7 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
{
size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
- size = std::min(size, maxSize);
+ size = std::min(size, maxSize);
for (size_t i = 0; i < size; ++i)
{
// Stop if a possible line continuation is encountered.
@@ -94,7 +108,7 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
// and increments line number if necessary.
if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
{
- size = i;
+ size = i;
maxRead = nRead + size; // Stop reading right before the backslash.
}
}
@@ -113,4 +127,3 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
}
} // namespace pp
-
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h
index a1de7ddd86..8c7c7ee19e 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Input.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_PREPROCESSOR_INPUT_H_
#define COMPILER_PREPROCESSOR_INPUT_H_
-#include <stddef.h>
+#include <cstddef>
#include <vector>
namespace pp
@@ -18,20 +18,12 @@ class Input
{
public:
Input();
+ ~Input();
Input(size_t count, const char *const string[], const int length[]);
- size_t count() const
- {
- return mCount;
- }
- const char *string(size_t index) const
- {
- return mString[index];
- }
- size_t length(size_t index) const
- {
- return mLength[index];
- }
+ size_t count() const { return mCount; }
+ const char *string(size_t index) const { return mString[index]; }
+ size_t length(size_t index) const { return mLength[index]; }
size_t read(char *buf, size_t maxSize, int *lineNo);
@@ -40,11 +32,7 @@ class Input
size_t sIndex; // String index;
size_t cIndex; // Char index.
- Location()
- : sIndex(0),
- cIndex(0)
- {
- }
+ Location() : sIndex(0), cIndex(0) {}
};
const Location &readLoc() const { return mReadLoc; }
@@ -55,7 +43,7 @@ class Input
// Input.
size_t mCount;
- const char * const *mString;
+ const char *const *mString;
std::vector<size_t> mLength;
Location mReadLoc;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp
index 7c663ee761..89cb3cf44e 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "Lexer.h"
+#include "compiler/preprocessor/Lexer.h"
namespace pp
{
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
index 990dc5e21d..775bc0a202 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
@@ -7,12 +7,14 @@
#ifndef COMPILER_PREPROCESSOR_LEXER_H_
#define COMPILER_PREPROCESSOR_LEXER_H_
+#include "common/angleutils.h"
+
namespace pp
{
struct Token;
-class Lexer
+class Lexer : angle::NonCopyable
{
public:
virtual ~Lexer();
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp
index 4c4d5fd2e2..52e2312fe6 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp
@@ -4,40 +4,41 @@
// found in the LICENSE file.
//
-#include "Macro.h"
+#include "compiler/preprocessor/Macro.h"
-#include <sstream>
-
-#include "Token.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/Token.h"
namespace pp
{
+Macro::Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj)
+{
+}
+
+Macro::~Macro()
+{
+}
+
bool Macro::equals(const Macro &other) const
{
- return (type == other.type) &&
- (name == other.name) &&
- (parameters == other.parameters) &&
+ return (type == other.type) && (name == other.name) && (parameters == other.parameters) &&
(replacements == other.replacements);
}
void PredefineMacro(MacroSet *macroSet, const char *name, int value)
{
- std::ostringstream stream;
- stream << value;
-
Token token;
token.type = Token::CONST_INT;
- token.text = stream.str();
+ token.text = ToString(value);
- Macro macro;
- macro.predefined = true;
- macro.type = Macro::kTypeObj;
- macro.name = name;
- macro.replacements.push_back(token);
+ std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+ macro->predefined = true;
+ macro->type = Macro::kTypeObj;
+ macro->name = name;
+ macro->replacements.push_back(token);
(*macroSet)[name] = macro;
}
} // namespace pp
-
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
index 31ee22c26a..c42e172ef9 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
@@ -8,6 +8,7 @@
#define COMPILER_PREPROCESSOR_MACRO_H_
#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -26,16 +27,13 @@ struct Macro
typedef std::vector<std::string> Parameters;
typedef std::vector<Token> Replacements;
- Macro()
- : predefined(false),
- disabled(false),
- type(kTypeObj)
- {
- }
+ Macro();
+ ~Macro();
bool equals(const Macro &other) const;
bool predefined;
mutable bool disabled;
+ mutable int expansionCount;
Type type;
std::string name;
@@ -43,7 +41,7 @@ struct Macro
Replacements replacements;
};
-typedef std::map<std::string, Macro> MacroSet;
+typedef std::map<std::string, std::shared_ptr<Macro>> MacroSet;
void PredefineMacro(MacroSet *macroSet, const char *name, int value);
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
index e878ee345a..d88d3a6853 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
@@ -4,20 +4,25 @@
// found in the LICENSE file.
//
-#include "MacroExpander.h"
+#include "compiler/preprocessor/MacroExpander.h"
#include <algorithm>
-#include <sstream>
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
namespace pp
{
+namespace
+{
+
+const size_t kMaxContextTokens = 10000;
+
class TokenLexer : public Lexer
{
- public:
+ public:
typedef std::vector<Token> TokenVector;
TokenLexer(TokenVector *tokens)
@@ -39,26 +44,61 @@ class TokenLexer : public Lexer
}
}
- private:
- PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer);
-
+ private:
TokenVector mTokens;
TokenVector::const_iterator mIter;
};
+} // anonymous namespace
+
+class MacroExpander::ScopedMacroReenabler final : angle::NonCopyable
+{
+ public:
+ ScopedMacroReenabler(MacroExpander *expander);
+ ~ScopedMacroReenabler();
+
+ private:
+ MacroExpander *mExpander;
+};
+
+MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
+ : mExpander(expander)
+{
+ mExpander->mDeferReenablingMacros = true;
+}
+
+MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
+{
+ mExpander->mDeferReenablingMacros = false;
+ for (auto macro : mExpander->mMacrosToReenable)
+ {
+ // Copying the string here by using substr is a check for use-after-free. It detects
+ // use-after-free more reliably than just toggling the disabled flag.
+ ASSERT(macro->name.substr() != "");
+ macro->disabled = false;
+ }
+ mExpander->mMacrosToReenable.clear();
+}
+
MacroExpander::MacroExpander(Lexer *lexer,
MacroSet *macroSet,
Diagnostics *diagnostics,
- bool parseDefined)
- : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined)
+ int allowedMacroExpansionDepth)
+ : mLexer(lexer),
+ mMacroSet(macroSet),
+ mDiagnostics(diagnostics),
+ mTotalTokensInContexts(0),
+ mAllowedMacroExpansionDepth(allowedMacroExpansionDepth),
+ mDeferReenablingMacros(false)
{
}
MacroExpander::~MacroExpander()
{
- for (std::size_t i = 0; i < mContextStack.size(); ++i)
+ ASSERT(mMacrosToReenable.empty());
+ for (MacroContext *context : mContextStack)
{
- delete mContextStack[i];
+ delete context;
}
}
@@ -66,54 +106,11 @@ 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;
@@ -121,17 +118,22 @@ void MacroExpander::lex(Token *token)
if (iter == mMacroSet->end())
break;
- const Macro& macro = iter->second;
- if (macro.disabled)
+ std::shared_ptr<Macro> macro = iter->second;
+ if (macro->disabled)
{
// If a particular token is not expanded, it is never expanded.
token->setExpansionDisabled(true);
break;
}
- if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())
+
+ // Bump the expansion count before peeking if the next token is a '('
+ // otherwise there could be a #undef of the macro before the next token.
+ macro->expansionCount++;
+ if ((macro->type == Macro::kTypeFunc) && !isNextTokenLeftParen())
{
// If the token immediately after the macro name is not a '(',
// this macro should not be expanded.
+ macro->expansionCount--;
break;
}
@@ -160,6 +162,7 @@ void MacroExpander::getToken(Token *token)
}
else
{
+ ASSERT(mTotalTokensInContexts == 0);
mLexer->lex(token);
}
}
@@ -170,11 +173,11 @@ void MacroExpander::ungetToken(const Token &token)
{
MacroContext *context = mContextStack.back();
context->unget();
- assert(context->replacements[context->index] == token);
+ ASSERT(context->replacements[context->index] == token);
}
else
{
- assert(!mReserveToken.get());
+ ASSERT(!mReserveToken.get());
mReserveToken.reset(new Token(token));
}
}
@@ -190,37 +193,48 @@ bool MacroExpander::isNextTokenLeftParen()
return lparen;
}
-bool MacroExpander::pushMacro(const Macro &macro, const Token &identifier)
+bool MacroExpander::pushMacro(std::shared_ptr<Macro> macro, const Token &identifier)
{
- assert(!macro.disabled);
- assert(!identifier.expansionDisabled());
- assert(identifier.type == Token::IDENTIFIER);
- assert(identifier.text == macro.name);
+ ASSERT(!macro->disabled);
+ ASSERT(!identifier.expansionDisabled());
+ ASSERT(identifier.type == Token::IDENTIFIER);
+ ASSERT(identifier.text == macro->name);
std::vector<Token> replacements;
- if (!expandMacro(macro, identifier, &replacements))
+ if (!expandMacro(*macro, identifier, &replacements))
return false;
// Macro is disabled for expansion until it is popped off the stack.
- macro.disabled = true;
+ macro->disabled = true;
MacroContext *context = new MacroContext;
- context->macro = &macro;
+ context->macro = macro;
context->replacements.swap(replacements);
mContextStack.push_back(context);
+ mTotalTokensInContexts += context->replacements.size();
return true;
}
void MacroExpander::popMacro()
{
- assert(!mContextStack.empty());
+ ASSERT(!mContextStack.empty());
MacroContext *context = mContextStack.back();
mContextStack.pop_back();
- assert(context->empty());
- assert(context->macro->disabled);
- context->macro->disabled = false;
+ ASSERT(context->empty());
+ ASSERT(context->macro->disabled);
+ ASSERT(context->macro->expansionCount > 0);
+ if (mDeferReenablingMacros)
+ {
+ mMacrosToReenable.push_back(context->macro);
+ }
+ else
+ {
+ context->macro->disabled = false;
+ }
+ context->macro->expansionCount--;
+ mTotalTokensInContexts -= context->replacements.size();
delete context;
}
@@ -237,33 +251,28 @@ bool MacroExpander::expandMacro(const Macro &macro,
SourceLocation replacementLocation = identifier.location;
if (macro.type == Macro::kTypeObj)
{
- replacements->assign(macro.replacements.begin(),
- macro.replacements.end());
+ replacements->assign(macro.replacements.begin(), macro.replacements.end());
if (macro.predefined)
{
const char kLine[] = "__LINE__";
const char kFile[] = "__FILE__";
- assert(replacements->size() == 1);
- Token& repl = replacements->front();
+ ASSERT(replacements->size() == 1);
+ Token &repl = replacements->front();
if (macro.name == kLine)
{
- std::ostringstream stream;
- stream << identifier.location.line;
- repl.text = stream.str();
+ repl.text = ToString(identifier.location.line);
}
else if (macro.name == kFile)
{
- std::ostringstream stream;
- stream << identifier.location.file;
- repl.text = stream.str();
+ repl.text = ToString(identifier.location.file);
}
}
}
else
{
- assert(macro.type == Macro::kTypeFunc);
+ ASSERT(macro.type == Macro::kTypeFunc);
std::vector<MacroArg> args;
args.reserve(macro.parameters.size());
if (!collectMacroArgs(macro, identifier, &args, &replacementLocation))
@@ -274,7 +283,7 @@ bool MacroExpander::expandMacro(const Macro &macro,
for (std::size_t i = 0; i < replacements->size(); ++i)
{
- Token& repl = replacements->at(i);
+ Token &repl = replacements->at(i);
if (i == 0)
{
// The first token in the replacement list inherits the padding
@@ -294,45 +303,52 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
{
Token token;
getToken(&token);
- assert(token.type == '(');
+ ASSERT(token.type == '(');
args->push_back(MacroArg());
- for (int openParens = 1; openParens != 0; )
+
+ // Defer reenabling macros until args collection is finished to avoid the possibility of
+ // infinite recursion. Otherwise infinite recursion might happen when expanding the args after
+ // macros have been popped from the context stack when parsing the args.
+ ScopedMacroReenabler deferReenablingMacros(this);
+
+ int openParens = 1;
+ while (openParens != 0)
{
getToken(&token);
if (token.type == Token::LAST)
{
- mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION,
- identifier.location, identifier.text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION, identifier.location,
+ identifier.text);
// Do not lose EOF token.
ungetToken(token);
return false;
}
- bool isArg = false; // True if token is part of the current argument.
+ bool isArg = false; // True if token is part of the current argument.
switch (token.type)
{
- case '(':
- ++openParens;
- isArg = true;
- break;
- case ')':
- --openParens;
- isArg = openParens != 0;
- *closingParenthesisLocation = token.location;
- break;
- case ',':
- // The individual arguments are separated by comma tokens, but
- // the comma tokens between matching inner parentheses do not
- // seperate arguments.
- if (openParens == 1)
- args->push_back(MacroArg());
- isArg = openParens != 1;
- break;
- default:
- isArg = true;
- break;
+ case '(':
+ ++openParens;
+ isArg = true;
+ break;
+ case ')':
+ --openParens;
+ isArg = openParens != 0;
+ *closingParenthesisLocation = token.location;
+ break;
+ case ',':
+ // The individual arguments are separated by comma tokens, but
+ // the comma tokens between matching inner parentheses do not
+ // seperate arguments.
+ if (openParens == 1)
+ args->push_back(MacroArg());
+ isArg = openParens != 1;
+ break;
+ default:
+ isArg = true;
+ break;
}
if (isArg)
{
@@ -353,9 +369,9 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
// Validate the number of arguments.
if (args->size() != params.size())
{
- Diagnostics::ID id = args->size() < macro.parameters.size() ?
- Diagnostics::PP_MACRO_TOO_FEW_ARGS :
- Diagnostics::PP_MACRO_TOO_MANY_ARGS;
+ Diagnostics::ID id = args->size() < macro.parameters.size()
+ ? Diagnostics::PP_MACRO_TOO_FEW_ARGS
+ : Diagnostics::PP_MACRO_TOO_MANY_ARGS;
mDiagnostics->report(id, identifier.location, identifier.text);
return false;
}
@@ -363,11 +379,17 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
// Pre-expand each argument before substitution.
// This step expands each argument individually before they are
// inserted into the macro body.
- for (std::size_t i = 0; i < args->size(); ++i)
+ size_t numTokens = 0;
+ for (auto &arg : *args)
{
- MacroArg &arg = args->at(i);
TokenLexer lexer(&arg);
- MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
+ if (mAllowedMacroExpansionDepth < 1)
+ {
+ mDiagnostics->report(Diagnostics::PP_MACRO_INVOCATION_CHAIN_TOO_DEEP, token.location,
+ token.text);
+ return false;
+ }
+ MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mAllowedMacroExpansionDepth - 1);
arg.clear();
expander.lex(&token);
@@ -375,6 +397,12 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
{
arg.push_back(token);
expander.lex(&token);
+ numTokens++;
+ if (numTokens + mTotalTokensInContexts > kMaxContextTokens)
+ {
+ mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+ return false;
+ }
}
}
return true;
@@ -386,6 +414,14 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
{
for (std::size_t i = 0; i < macro.replacements.size(); ++i)
{
+ if (!replacements->empty() &&
+ replacements->size() + mTotalTokensInContexts > kMaxContextTokens)
+ {
+ const Token &token = replacements->back();
+ mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+ return;
+ }
+
const Token &repl = macro.replacements[i];
if (repl.type != Token::IDENTIFIER)
{
@@ -396,15 +432,15 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
// TODO(alokp): Optimize this.
// There is no need to search for macro params every time.
// The param index can be cached with the replacement token.
- Macro::Parameters::const_iterator iter = std::find(
- macro.parameters.begin(), macro.parameters.end(), repl.text);
+ Macro::Parameters::const_iterator iter =
+ std::find(macro.parameters.begin(), macro.parameters.end(), repl.text);
if (iter == macro.parameters.end())
{
replacements->push_back(repl);
continue;
}
- std::size_t iArg = std::distance(macro.parameters.begin(), iter);
+ std::size_t iArg = std::distance(macro.parameters.begin(), iter);
const MacroArg &arg = args[iArg];
if (arg.empty())
{
@@ -418,5 +454,28 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
}
}
-} // namespace pp
+MacroExpander::MacroContext::MacroContext() : macro(0), index(0)
+{
+}
+MacroExpander::MacroContext::~MacroContext()
+{
+}
+
+bool MacroExpander::MacroContext::empty() const
+{
+ return index == replacements.size();
+}
+
+const Token &MacroExpander::MacroContext::get()
+{
+ return replacements[index++];
+}
+
+void MacroExpander::MacroContext::unget()
+{
+ ASSERT(index > 0);
+ --index;
+}
+
+} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
index dc870f626f..fae7676fb0 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
@@ -7,13 +7,11 @@
#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
-#include <cassert>
#include <memory>
#include <vector>
-#include "Lexer.h"
-#include "Macro.h"
-#include "pp_utils.h"
+#include "compiler/preprocessor/Lexer.h"
+#include "compiler/preprocessor/Macro.h"
namespace pp
{
@@ -24,24 +22,23 @@ struct SourceLocation;
class MacroExpander : public Lexer
{
public:
- MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics, bool parseDefined);
+ MacroExpander(Lexer *lexer,
+ MacroSet *macroSet,
+ Diagnostics *diagnostics,
+ int allowedMacroExpansionDepth);
~MacroExpander() override;
void lex(Token *token) override;
private:
- PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
-
void getToken(Token *token);
void ungetToken(const Token &token);
bool isNextTokenLeftParen();
- bool pushMacro(const Macro &macro, const Token &identifier);
+ bool pushMacro(std::shared_ptr<Macro> macro, const Token &identifier);
void popMacro();
- bool expandMacro(const Macro &macro,
- const Token &identifier,
- std::vector<Token> *replacements);
+ bool expandMacro(const Macro &macro, const Token &identifier, std::vector<Token> *replacements);
typedef std::vector<Token> MacroArg;
bool collectMacroArgs(const Macro &macro,
@@ -54,37 +51,31 @@ class MacroExpander : public Lexer
struct MacroContext
{
- const Macro *macro;
+ MacroContext();
+ ~MacroContext();
+ bool empty() const;
+ const Token &get();
+ void unget();
+
+ std::shared_ptr<Macro> macro;
std::size_t index;
std::vector<Token> replacements;
-
- MacroContext()
- : macro(0),
- index(0)
- {
- }
- bool empty() const
- {
- return index == replacements.size();
- }
- const Token &get()
- {
- return replacements[index++];
- }
- void unget()
- {
- assert(index > 0);
- --index;
- }
};
Lexer *mLexer;
MacroSet *mMacroSet;
Diagnostics *mDiagnostics;
- bool mParseDefined;
std::unique_ptr<Token> mReserveToken;
std::vector<MacroContext *> mContextStack;
+ size_t mTotalTokensInContexts;
+
+ int mAllowedMacroExpansionDepth;
+
+ bool mDeferReenablingMacros;
+ std::vector<std::shared_ptr<Macro>> mMacrosToReenable;
+
+ class ScopedMacroReenabler;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
index aeb9c46f9d..349c7b06c7 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
@@ -4,16 +4,15 @@
// found in the LICENSE file.
//
-#include "Preprocessor.h"
+#include "compiler/preprocessor/Preprocessor.h"
-#include <cassert>
-
-#include "DiagnosticsBase.h"
-#include "DirectiveParser.h"
-#include "Macro.h"
-#include "MacroExpander.h"
-#include "Token.h"
-#include "Tokenizer.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/DirectiveParser.h"
+#include "compiler/preprocessor/Macro.h"
+#include "compiler/preprocessor/MacroExpander.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
namespace pp
{
@@ -26,19 +25,26 @@ struct PreprocessorImpl
DirectiveParser directiveParser;
MacroExpander macroExpander;
- PreprocessorImpl(Diagnostics *diag, DirectiveHandler *directiveHandler)
+ PreprocessorImpl(Diagnostics *diag,
+ DirectiveHandler *directiveHandler,
+ const PreprocessorSettings &settings)
: diagnostics(diag),
tokenizer(diag),
- directiveParser(&tokenizer, &macroSet, diag, directiveHandler),
- macroExpander(&directiveParser, &macroSet, diag, false)
+ directiveParser(&tokenizer,
+ &macroSet,
+ diag,
+ directiveHandler,
+ settings.maxMacroExpansionDepth),
+ macroExpander(&directiveParser, &macroSet, diag, settings.maxMacroExpansionDepth)
{
}
};
Preprocessor::Preprocessor(Diagnostics *diagnostics,
- DirectiveHandler *directiveHandler)
+ DirectiveHandler *directiveHandler,
+ const PreprocessorSettings &settings)
{
- mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
+ mImpl = new PreprocessorImpl(diagnostics, directiveHandler, settings);
}
Preprocessor::~Preprocessor()
@@ -46,9 +52,7 @@ Preprocessor::~Preprocessor()
delete mImpl;
}
-bool Preprocessor::init(size_t count,
- const char * const string[],
- const int length[])
+bool Preprocessor::init(size_t count, const char *const string[], const int length[])
{
static const int kDefaultGLSLVersion = 100;
@@ -74,23 +78,23 @@ void Preprocessor::lex(Token *token)
mImpl->macroExpander.lex(token);
switch (token->type)
{
- // We should not be returning internal preprocessing tokens.
- // Convert preprocessing tokens to compiler tokens or report
- // diagnostics.
- case Token::PP_HASH:
- assert(false);
- break;
- case Token::PP_NUMBER:
- mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER,
- token->location, token->text);
- break;
- case Token::PP_OTHER:
- mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER,
- token->location, token->text);
- break;
- default:
- validToken = true;
- break;
+ // We should not be returning internal preprocessing tokens.
+ // Convert preprocessing tokens to compiler tokens or report
+ // diagnostics.
+ case Token::PP_HASH:
+ UNREACHABLE();
+ break;
+ case Token::PP_NUMBER:
+ mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, token->location,
+ token->text);
+ break;
+ case Token::PP_OTHER:
+ mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, token->location,
+ token->text);
+ break;
+ default:
+ validToken = true;
+ break;
}
}
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
index fe25daa123..2fe504f7f9 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
@@ -7,9 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_
#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_
-#include <stddef.h>
+#include <cstddef>
-#include "pp_utils.h"
+#include "common/angleutils.h"
namespace pp
{
@@ -19,10 +19,18 @@ class DirectiveHandler;
struct PreprocessorImpl;
struct Token;
-class Preprocessor
+struct PreprocessorSettings : private angle::NonCopyable
+{
+ PreprocessorSettings() : maxMacroExpansionDepth(1000) {}
+ int maxMacroExpansionDepth;
+};
+
+class Preprocessor : angle::NonCopyable
{
public:
- Preprocessor(Diagnostics *diagnostics, DirectiveHandler *directiveHandler);
+ Preprocessor(Diagnostics *diagnostics,
+ DirectiveHandler *directiveHandler,
+ const PreprocessorSettings &settings);
~Preprocessor();
// count: specifies the number of elements in the string and length arrays.
@@ -34,7 +42,7 @@ class Preprocessor
// Each element in the length array may contain the length of the
// corresponding string or a value less than 0 to indicate that the string
// is null terminated.
- bool init(size_t count, const char * const string[], const int length[]);
+ bool init(size_t count, const char *const string[], const int length[]);
// Adds a pre-defined macro.
void predefineMacro(const char *name, int value);
@@ -44,8 +52,6 @@ class Preprocessor
void setMaxTokenSize(size_t maxTokenSize);
private:
- PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);
-
PreprocessorImpl *mImpl;
};
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
index af8a8d5d19..51908a3b4b 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
@@ -12,16 +12,8 @@ namespace pp
struct SourceLocation
{
- SourceLocation()
- : file(0),
- line(0)
- {
- }
- SourceLocation(int f, int l)
- : file(f),
- line(l)
- {
- }
+ SourceLocation() : file(0), line(0) {}
+ SourceLocation(int f, int l) : file(f), line(l) {}
bool equals(const SourceLocation &other) const
{
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp
index d102654747..ce0ce94f49 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp
@@ -4,28 +4,25 @@
// found in the LICENSE file.
//
-#include "Token.h"
+#include "compiler/preprocessor/Token.h"
-#include <cassert>
-
-#include "numeric_lex.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/numeric_lex.h"
namespace pp
{
void Token::reset()
{
- type = 0;
- flags = 0;
+ type = 0;
+ flags = 0;
location = SourceLocation();
text.clear();
}
bool Token::equals(const Token &other) const
{
- return (type == other.type) &&
- (flags == other.flags) &&
- (location == other.location) &&
+ return (type == other.type) && (flags == other.flags) && (location == other.location) &&
(text == other.text);
}
@@ -55,19 +52,19 @@ void Token::setExpansionDisabled(bool disable)
bool Token::iValue(int *value) const
{
- assert(type == CONST_INT);
+ ASSERT(type == CONST_INT);
return numeric_lex_int(text, value);
}
bool Token::uValue(unsigned int *value) const
{
- assert(type == CONST_INT);
+ ASSERT(type == CONST_INT);
return numeric_lex_int(text, value);
}
bool Token::fValue(float *value) const
{
- assert(type == CONST_FLOAT);
+ ASSERT(type == CONST_FLOAT);
return numeric_lex_float(text, value);
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h
index 347c47e307..26732ab64d 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Token.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h
@@ -10,7 +10,7 @@
#include <ostream>
#include <string>
-#include "SourceLocation.h"
+#include "compiler/preprocessor/SourceLocation.h"
namespace pp
{
@@ -19,7 +19,9 @@ struct Token
{
enum Type
{
- LAST = 0, // EOF.
+ // Calling this ERROR causes a conflict with wingdi.h
+ GOT_ERROR = -1,
+ LAST = 0, // EOF.
IDENTIFIER = 258,
@@ -62,33 +64,20 @@ struct Token
EXPANSION_DISABLED = 1 << 2
};
- Token()
- : type(0),
- flags(0)
- {
- }
+ Token() : type(0), flags(0) {}
void reset();
bool equals(const Token &other) const;
// Returns true if this is the first token on line.
// It disregards any leading whitespace.
- bool atStartOfLine() const
- {
- return (flags & AT_START_OF_LINE) != 0;
- }
+ bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; }
void setAtStartOfLine(bool start);
- bool hasLeadingSpace() const
- {
- return (flags & HAS_LEADING_SPACE) != 0;
- }
+ bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; }
void setHasLeadingSpace(bool space);
- bool expansionDisabled() const
- {
- return (flags & EXPANSION_DISABLED) != 0;
- }
+ bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; }
void setExpansionDisabled(bool disable);
// Converts text into numeric value for CONST_INT and CONST_FLOAT token.
@@ -113,7 +102,7 @@ inline bool operator!=(const Token &lhs, const Token &rhs)
return !lhs.equals(rhs);
}
-extern std::ostream &operator<<(std::ostream &out, const Token &token);
+std::ostream &operator<<(std::ostream &out, const Token &token);
} // namepsace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
index 49e64fa209..af4fd7ce7b 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
@@ -7,9 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_
#define COMPILER_PREPROCESSOR_TOKENIZER_H_
-#include "Input.h"
-#include "Lexer.h"
-#include "pp_utils.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/Input.h"
+#include "compiler/preprocessor/Lexer.h"
namespace pp
{
@@ -34,9 +34,9 @@ class Tokenizer : public Lexer
};
Tokenizer(Diagnostics *diagnostics);
- ~Tokenizer();
+ ~Tokenizer() override;
- bool init(size_t count, const char * const string[], const int length[]);
+ bool init(size_t count, const char *const string[], const int length[]);
void setFileNumber(int file);
void setLineNumber(int line);
@@ -45,13 +45,12 @@ class Tokenizer : public Lexer
void lex(Token *token) override;
private:
- PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
bool initScanner();
void destroyScanner();
- void *mHandle; // Scanner handle.
- Context mContext; // Scanner extra.
- size_t mMaxTokenSize; // Maximum token size
+ void *mHandle; // Scanner handle.
+ Context mContext; // Scanner extra.
+ size_t mMaxTokenSize; // Maximum token size
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
index d316da88b1..096812d45f 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
@@ -27,10 +27,10 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
#pragma warning(disable: 4005)
#endif
-#include "Tokenizer.h"
+#include "compiler/preprocessor/Tokenizer.h"
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
#if defined(__GNUC__)
// Triggered by the auto-generated yy_fatal_error function.
@@ -110,7 +110,14 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
"/*" { BEGIN(COMMENT); }
<COMMENT>[^*\r\n]+
<COMMENT>"*"
-<COMMENT>{NEWLINE} { ++yylineno; }
+<COMMENT>{NEWLINE} {
+ if (yylineno == INT_MAX)
+ {
+ *yylval = "Integer overflow on line number";
+ return pp::Token::GOT_ERROR;
+ }
+ ++yylineno;
+}
<COMMENT>"*/" {
yyextra->leadingSpace = true;
BEGIN(INITIAL);
@@ -237,13 +244,16 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
[ \t\v\f]+ { yyextra->leadingSpace = true; }
{NEWLINE} {
+ if (yylineno == INT_MAX)
+ {
+ *yylval = "Integer overflow on line number";
+ return pp::Token::GOT_ERROR;
+ }
++yylineno;
yylval->assign(1, '\n');
return '\n';
}
-\\{NEWLINE} { ++yylineno; }
-
. {
yylval->assign(1, yytext[0]);
return pp::Token::PP_OTHER;
@@ -267,11 +277,17 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
yylloc->line = yylineno;
yylval->clear();
- if (YY_START == COMMENT)
+ // Line number overflows fake EOFs to exit early, check for this case.
+ if (yylineno == INT_MAX) {
+ yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
+ pp::SourceLocation(yyfileno, yylineno),
+ "Integer overflow on line number");
+ }
+ else if (YY_START == COMMENT)
{
yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
pp::SourceLocation(yyfileno, yylineno),
- "");
+ "EOF while in a comment");
}
yyterminate();
}
@@ -280,9 +296,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
-Tokenizer::Tokenizer(Diagnostics *diagnostics)
- : mHandle(0),
- mMaxTokenSize(256)
+Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(256)
{
mContext.diagnostics = diagnostics;
}
@@ -320,7 +334,18 @@ void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
void Tokenizer::lex(Token *token)
{
- token->type = yylex(&token->text, &token->location, mHandle);
+ int tokenType = yylex(&token->text, &token->location, mHandle);
+
+ if (tokenType == Token::GOT_ERROR)
+ {
+ mContext.diagnostics->report(Diagnostics::PP_TOKENIZER_ERROR, token->location, token->text);
+ token->type = Token::LAST;
+ }
+ else
+ {
+ token->type = tokenType;
+ }
+
if (token->text.size() > mMaxTokenSize)
{
mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
@@ -339,7 +364,7 @@ void Tokenizer::lex(Token *token)
bool Tokenizer::initScanner()
{
- if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
+ if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
return false;
yyrestart(0, mHandle);
@@ -348,11 +373,11 @@ bool Tokenizer::initScanner()
void Tokenizer::destroyScanner()
{
- if (mHandle == NULL)
+ if (mHandle == nullptr)
return;
yylex_destroy(mHandle);
- mHandle = NULL;
+ mHandle = nullptr;
}
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
index b32e42253f..6ea779ab8f 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
@@ -9,15 +9,15 @@
#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
+#include <cmath>
#include <sstream>
-namespace pp {
+namespace pp
+{
inline std::ios::fmtflags numeric_base_int(const std::string &str)
{
- if ((str.size() >= 2) &&
- (str[0] == '0') &&
- (str[1] == 'x' || str[1] == 'X'))
+ if ((str.size() >= 2) && (str[0] == '0') && (str[1] == 'x' || str[1] == 'X'))
{
return std::ios::hex;
}
@@ -33,7 +33,7 @@ inline std::ios::fmtflags numeric_base_int(const std::string &str)
// of the correct form. They can only fail if the parsed value is too big,
// in which case false is returned.
-template<typename IntType>
+template <typename IntType>
bool numeric_lex_int(const std::string &str, IntType *value)
{
std::istringstream stream(str);
@@ -45,7 +45,7 @@ bool numeric_lex_int(const std::string &str, IntType *value)
return !stream.fail();
}
-template<typename FloatType>
+template <typename FloatType>
bool numeric_lex_float(const std::string &str, FloatType *value)
{
// On 64-bit Intel Android, istringstream is broken. Until this is fixed in
@@ -63,10 +63,10 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
stream.imbue(std::locale::classic());
stream >> (*value);
- return !stream.fail();
+ return !stream.fail() && std::isfinite(*value);
#endif
}
-} // namespace pp.
+} // namespace pp.
-#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_
+#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h
deleted file mode 100644
index 9fba9385c5..0000000000
--- a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// pp_utils.h: Common preprocessor utilities
-
-#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_
-#define COMPILER_PREPROCESSOR_PPUTILS_H_
-
-// A macro to disallow the copy constructor and operator= functions
-// This must be used in the private: declarations for a class.
-#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName &); \
- void operator=(const TypeName &)
-
-#endif // COMPILER_PREPROCESSOR_PPUTILS_H_