diff options
author | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2014-08-05 14:24:23 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2014-08-05 14:24:23 +0200 |
commit | f3a61e8bf7f5b8275c000a0cac70b561422d2230 (patch) | |
tree | 0cf0631a5b53fdab930f8a7936aff9c9c1c0952f /src/libs/3rdparty/cplusplus/Parser.cpp | |
parent | 59b34b6b539c78384ea3fc4fd018fe063b4ede53 (diff) | |
parent | b2ac3fd90ccfc21cf4c5bce353d8e08208961eeb (diff) |
Merge remote-tracking branch 'origin/3.2'
Conflicts:
qtcreator.pri
qtcreator.qbs
src/plugins/android/androidglobal.h
Change-Id: I3367bf2ea47c088989175dddeed2210294346f4c
Diffstat (limited to 'src/libs/3rdparty/cplusplus/Parser.cpp')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 249 |
1 files changed, 192 insertions, 57 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index af7f6dfa7d..bcd70fbb36 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -26,8 +26,13 @@ #include "Literals.h" #include "ObjectiveCTypeQualifiers.h" #include "QtContextKeywords.h" + +#include <unordered_map> +#include <utility> + #include <string> #include <cstdio> // for putchar + #if defined(_MSC_VER) && (_MSC_VER < 1800) # define va_copy(dst, src) ((dst) = (src)) #elif defined(__INTEL_COMPILER) && !defined(va_copy) @@ -43,9 +48,9 @@ using namespace CPlusPlus; namespace { class DebugRule { +public: static int depth; -public: DebugRule(const char *name, const char *spell, unsigned idx, bool blocked) { for (int i = 0; i <= depth; ++i) @@ -150,12 +155,93 @@ inline bool isRightAssociative(int tokenKind) } // end of anonymous namespace +class Parser::ASTCache +{ + ASTCache(const ASTCache &other); + void operator =(const ASTCache &other); + +public: + enum ASTKind { + Expression, + ExpressionList, + ParameterDeclarationClause, + TypeId + }; + +public: + ASTCache() {} + + void insert(ASTKind astKind, unsigned tokenIndexBeforeParsing, + AST *resultingAST, unsigned resultingTokenIndex) + { + const auto key = std::make_pair(astKind, tokenIndexBeforeParsing); + const auto value = std::make_pair(resultingAST, resultingTokenIndex); + const auto keyValue = std::make_pair(key, value); + _cache.insert(keyValue); + } + + AST *find(ASTKind astKind, unsigned tokenIndex, + unsigned *resultingTokenIndex, bool *foundInCache) const + { + const auto key = std::make_pair(astKind, tokenIndex); + const auto it = _cache.find(key); + if (it == _cache.end()) { + *foundInCache = false; + return 0; + } else { + *foundInCache = true; + *resultingTokenIndex = it->second.second; + return it->second.first; + } + } + + void clear() + { + _cache.clear(); + } + +private: + struct KeyHasher { + size_t operator()(const std::pair<int, unsigned> &key) const + { return std::hash<int>()(key.first) ^ std::hash<unsigned>()(key.second); } + }; + + typedef std::pair<int, unsigned> ASTKindAndTokenIndex; + typedef std::pair<AST *, unsigned> ASTAndTokenIndex; + std::unordered_map<ASTKindAndTokenIndex, ASTAndTokenIndex, KeyHasher> _cache; +}; + #ifndef CPLUSPLUS_NO_DEBUG_RULE # define DEBUG_THIS_RULE() DebugRule __debug_rule__(__func__, tok().spell(), cursor(), _translationUnit->blockErrors()) +inline void debugPrintCheckCache(bool goodCase) +{ + for (int i = 0; i <= DebugRule::depth - 1; ++i) + fputc('-', stderr); + if (goodCase) + fprintf(stderr, " CACHE: Re-using AST from Cache.\n"); + else + fprintf(stderr, " CACHE: Already tried to parse this, skipping.\n"); +} #else # define DEBUG_THIS_RULE() do {} while (0) +inline void debugPrintCheckCache(bool) {} #endif +#define CHECK_CACHE(ASTKind, ASTType, returnValueInBadCase) \ + do { \ + bool foundInCache; \ + unsigned newTokenIndex; \ + if (AST *ast = _astCache->find(ASTKind, cursor(), &newTokenIndex, &foundInCache)) { \ + debugPrintCheckCache(true); \ + node = (ASTType *) ast; \ + _tokenIndex = newTokenIndex; \ + return true; \ + } else if (foundInCache) { \ + debugPrintCheckCache(false); \ + return returnValueInBadCase; \ + } \ + } while (0) + #define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \ if (LA() == T_THROW) { \ if (!parseThrowExpression(node)) \ @@ -175,14 +261,18 @@ Parser::Parser(TranslationUnit *unit) _tokenIndex(1), _templateArguments(0), _inFunctionBody(false), - _inObjCImplementationContext(false), _inExpressionStatement(false), _expressionDepth(0), - _statementDepth(0) + _statementDepth(0), + _astCache(new ASTCache), + _expressionStatementAstCache(new ASTCache) { } Parser::~Parser() -{ } +{ + delete _expressionStatementAstCache; + delete _astCache; +} bool Parser::switchTemplateArguments(bool templateArguments) { @@ -633,7 +723,7 @@ bool Parser::parseDeclaration(DeclarationAST *&node) if (_languageFeatures.objCEnabled && LA() == T___ATTRIBUTE__) { const unsigned start = cursor(); SpecifierListAST *attributes = 0, **attr = &attributes; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; if (LA() == T_AT_INTERFACE) return parseObjCInterface(node, attributes); @@ -761,11 +851,7 @@ bool Parser::parseNamespace(DeclarationAST *&node) ast->namespace_token = namespace_token; if (LA() == T_IDENTIFIER) ast->identifier_token = consumeToken(); - SpecifierListAST **attr_ptr = &ast->attribute_list; - while (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*attr_ptr); - attr_ptr = &(*attr_ptr)->next; - } + parseOptionalAttributeSpecifierSequence(ast->attribute_list); if (LA() == T_LBRACE) { parseLinkageBody(ast->linkage_body); } else { // attempt to do error recovery @@ -1196,9 +1282,8 @@ bool Parser::parseCvQualifiers(SpecifierListAST *&node) spec->specifier_token = consumeToken(); *ast = new (_pool) SpecifierListAST(spec); ast = &(*ast)->next; - } else if (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*ast); - ast = &(*ast)->next; + } else if (parseOptionalAttributeSpecifierSequence(*ast)) { + continue; } else { break; } @@ -1398,11 +1483,7 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp DEBUG_THIS_RULE(); unsigned start = cursor(); SpecifierListAST *attributes = 0; - SpecifierListAST **attribute_ptr = &attributes; - while (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*attribute_ptr); - attribute_ptr = &(*attribute_ptr)->next; - } + parseOptionalAttributeSpecifierSequence(attributes); PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; while (parsePtrOperator(*ptr_operators_tail)) @@ -1577,12 +1658,7 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specif consumeToken(); // skip T_RPAREN } - SpecifierListAST **spec_ptr = &node->post_attribute_list; - while (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*spec_ptr); - spec_ptr = &(*spec_ptr)->next; - } - + parseOptionalAttributeSpecifierSequence(node->post_attribute_list); return true; } @@ -1856,6 +1932,8 @@ bool Parser::parseTypeParameter(DeclarationAST *&node) bool Parser::parseTypeId(ExpressionAST *&node) { DEBUG_THIS_RULE(); + CHECK_CACHE(ASTCache::TypeId, ExpressionAST, false); + SpecifierListAST *type_specifier = 0; if (parseTypeSpecifier(type_specifier)) { TypeIdAST *ast = new (_pool) TypeIdAST; @@ -1872,6 +1950,8 @@ bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&nod DEBUG_THIS_RULE(); if (LA() == T_RPAREN) return true; // nothing to do + CHECK_CACHE(ASTCache::ParameterDeclarationClause, ParameterDeclarationClauseAST, true); + const unsigned initialCursor = cursor(); ParameterDeclarationListAST *parameter_declarations = 0; @@ -1896,6 +1976,7 @@ bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&nod node = ast; } + _astCache->insert(ASTCache::ParameterDeclarationClause, initialCursor, node, cursor()); return true; } @@ -1985,11 +2066,8 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node) unsigned classkey_token = consumeToken(); - SpecifierListAST *attributes = 0, **attr_ptr = &attributes; - while (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*attr_ptr); - attr_ptr = &(*attr_ptr)->next; - } + SpecifierListAST *attributes = 0; + parseOptionalAttributeSpecifierSequence(attributes); if (LA(1) == T_IDENTIFIER && LA(2) == T_IDENTIFIER) { const Identifier *id = tok(2).identifier; @@ -2464,12 +2542,8 @@ bool Parser::parseElaboratedTypeSpecifier(SpecifierListAST *&node) if (lookAtClassKey() || LA() == T_ENUM || LA() == T_TYPENAME) { unsigned classkey_token = consumeToken(); - SpecifierListAST *attributes = 0, **attr_ptr = &attributes; - while (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*attr_ptr); - attr_ptr = &(*attr_ptr)->next; - } - + SpecifierListAST *attributes = 0; + parseOptionalAttributeSpecifierSequence(attributes); NameAST *name = 0; if (parseName(name)) { ElaboratedTypeSpecifierAST *ast = new (_pool) ElaboratedTypeSpecifierAST; @@ -2838,9 +2912,14 @@ bool Parser::parseTypeIdList(ExpressionListAST *&node) bool Parser::parseExpressionList(ExpressionListAST *&node) { DEBUG_THIS_RULE(); + CHECK_CACHE(ASTCache::ExpressionList, ExpressionListAST, false); + unsigned initialCursor = cursor(); - if (_languageFeatures.cxx11Enabled) - return parseInitializerList0x(node); + if (_languageFeatures.cxx11Enabled) { + bool result = parseInitializerList0x(node); + _astCache->insert(ASTCache::ExpressionList, initialCursor, (AST *) node, cursor()); + return result; + } ExpressionListAST **expression_list_ptr = &node; ExpressionAST *expression = 0; @@ -2857,9 +2936,11 @@ bool Parser::parseExpressionList(ExpressionListAST *&node) expression_list_ptr = &(*expression_list_ptr)->next; } } + _astCache->insert(ASTCache::ExpressionList, initialCursor, (AST *) node, cursor()); return true; } + _astCache->insert(ASTCache::ExpressionList, initialCursor, 0, cursor()); return false; } @@ -3022,9 +3103,11 @@ bool Parser::parseExpressionStatement(StatementAST *&node) const bool wasInExpressionStatement = _inExpressionStatement; _inExpressionStatement = true; - // switch to the temp pool + // switch to the temp pool and cache MemoryPool *previousPool = _pool; _pool = &_expressionStatementTempPool; + ASTCache *previousASTCache = _astCache; + _astCache = _expressionStatementAstCache; bool parsed = false; @@ -3041,12 +3124,15 @@ bool Parser::parseExpressionStatement(StatementAST *&node) _inExpressionStatement = wasInExpressionStatement; if (! _inExpressionStatement) { - // rewind the memory pool after parsing a toplevel expression statement. + // rewind the memory pool and cache after parsing a toplevel expression statement. _expressionStatementTempPool.reset(); + _astCache->clear(); } - // restore the pool + // restore the pool and cache _pool = previousPool; + _astCache = previousASTCache; + return parsed; } @@ -3799,39 +3885,83 @@ bool Parser::lookAtClassKey() const } } -bool Parser::parseAttributeSpecifier(SpecifierListAST *&node) +bool Parser::parseOptionalAttributeSpecifierSequence(SpecifierListAST *&attribute_list) +{ + bool didRead = false; + while (parseAttributeSpecifier(attribute_list)) + didRead = true; + return didRead; +} + +bool Parser::parseAttributeSpecifier(SpecifierListAST *&attribute_list) +{ + SpecifierListAST **attr_ptr = &attribute_list; + switch (LA()) { + case T_ALIGNAS: { + AlignmentSpecifierAST *ast = new (_pool) AlignmentSpecifierAST; + ast->align_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + + const unsigned saved = cursor(); + if (!parseTypeId(ast->typeIdExprOrAlignmentExpr) || + (LA() != T_RPAREN && + (LA(1) != T_DOT_DOT_DOT || LA(2) != T_RPAREN))) { + rewind(saved); + parseExpression(ast->typeIdExprOrAlignmentExpr); + } + + if (LA() == T_DOT_DOT_DOT) + ast->ellipses_token = consumeToken(); + match(T_RPAREN, &ast->rparen_token); + attribute_list = new (_pool) SpecifierListAST(ast); + return true; + } + //### TODO: C++11-style attributes +// case T_LBRACKET: + case T___ATTRIBUTE__: + while (LA() == T___ATTRIBUTE__) { + parseGnuAttributeSpecifier(*attr_ptr); + attr_ptr = &(*attr_ptr)->next; + } + return true; + default: + return false; + } +} + +bool Parser::parseGnuAttributeSpecifier(SpecifierListAST *&node) { DEBUG_THIS_RULE(); if (LA() != T___ATTRIBUTE__) return false; - AttributeSpecifierAST *ast = new (_pool) AttributeSpecifierAST; + GnuAttributeSpecifierAST *ast = new (_pool) GnuAttributeSpecifierAST; ast->attribute_token = consumeToken(); match(T_LPAREN, &ast->first_lparen_token); match(T_LPAREN, &ast->second_lparen_token); - parseAttributeList(ast->attribute_list); + parseGnuAttributeList(ast->attribute_list); match(T_RPAREN, &ast->first_rparen_token); match(T_RPAREN, &ast->second_rparen_token); node = new (_pool) SpecifierListAST(ast); return true; } -bool Parser::parseAttributeList(AttributeListAST *&node) +bool Parser::parseGnuAttributeList(GnuAttributeListAST *&node) { DEBUG_THIS_RULE(); - AttributeListAST **iter = &node; + GnuAttributeListAST **iter = &node; while (LA() == T_CONST || LA() == T_IDENTIFIER) { - *iter = new (_pool) AttributeListAST; + *iter = new (_pool) GnuAttributeListAST; if (LA() == T_CONST) { - AttributeAST *attr = new (_pool) AttributeAST; + GnuAttributeAST *attr = new (_pool) GnuAttributeAST; attr->identifier_token = consumeToken(); (*iter)->value = attr; iter = &(*iter)->next; } else if (LA() == T_IDENTIFIER) { - AttributeAST *attr = new (_pool) AttributeAST; + GnuAttributeAST *attr = new (_pool) GnuAttributeAST; attr->identifier_token = consumeToken(); if (LA() == T_LPAREN) { attr->lparen_token = consumeToken(); @@ -3856,7 +3986,7 @@ bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node) { DEBUG_THIS_RULE(); if (LA() == T___ATTRIBUTE__) { - return parseAttributeSpecifier(node); + return parseGnuAttributeSpecifier(node); } else if (LA() == T___TYPEOF__) { TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST; ast->typeof_token = consumeToken(); @@ -3912,8 +4042,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de spec->specifier_token = consumeToken(); *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; - } else if (LA() == T___ATTRIBUTE__) { - parseAttributeSpecifier(*decl_specifier_seq_ptr); + } else if (parseAttributeSpecifier(*decl_specifier_seq_ptr)) { decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; } else if (! named_type_specifier && ! has_complex_type_specifier && lookAtBuiltinTypeSpecifier()) { parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr); @@ -5244,6 +5373,7 @@ bool Parser::parseCastExpression(ExpressionAST *&node) DEBUG_THIS_RULE(); if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); + unsigned initialCursor = cursor(); ExpressionAST *type_id = 0; if (parseTypeId(type_id) && LA() == T_RPAREN) { @@ -5298,6 +5428,7 @@ bool Parser::parseCastExpression(ExpressionAST *&node) } parse_as_unary_expression: + _astCache->insert(ASTCache::TypeId, initialCursor, 0, cursor()); rewind(lparen_token); } @@ -5398,6 +5529,8 @@ bool Parser::parseConstantExpression(ExpressionAST *&node) bool Parser::parseExpression(ExpressionAST *&node) { DEBUG_THIS_RULE(); + CHECK_CACHE(ASTCache::Expression, ExpressionAST, false); + unsigned initialCursor = cursor(); if (_expressionDepth > MAX_EXPRESSION_DEPTH) return false; @@ -5405,6 +5538,8 @@ bool Parser::parseExpression(ExpressionAST *&node) ++_expressionDepth; bool success = parseCommaExpression(node); --_expressionDepth; + + _astCache->insert(ASTCache::Expression, initialCursor, node, cursor()); return success; } @@ -5628,7 +5763,7 @@ bool Parser::parseObjCInterface(DeclarationAST *&node, DEBUG_THIS_RULE(); if (! attributes && LA() == T___ATTRIBUTE__) { SpecifierListAST **attr = &attributes; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; } @@ -5717,7 +5852,7 @@ bool Parser::parseObjCProtocol(DeclarationAST *&node, DEBUG_THIS_RULE(); if (! attributes && LA() == T___ATTRIBUTE__) { SpecifierListAST **attr = &attributes; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; } @@ -6219,7 +6354,7 @@ bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node) } SpecifierListAST **attr = &ast->attribute_list; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; node = ast; @@ -6328,7 +6463,7 @@ bool Parser::parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, Obj parseObjCTypeName(node->type_name); SpecifierListAST **attr = &node->attribute_list; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; SimpleNameAST *param_name = new (_pool) SimpleNameAST; @@ -6528,7 +6663,7 @@ bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node) match(T_RPAREN, &ast->rparen_token); SpecifierListAST **attr = &ast->attributes; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; if (LA() == T_MUTABLE) @@ -6552,7 +6687,7 @@ bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node) ast->arrow_token = consumeToken(); SpecifierListAST **attr = &ast->attributes; - while (parseAttributeSpecifier(*attr)) + while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; parseTrailingTypeSpecifierSeq(ast->type_specifier_list); |