diff options
author | Flex Ferrum <flexferrum@gmail.com> | 2012-02-19 16:33:25 +0400 |
---|---|---|
committer | Roberto Raggi <roberto.raggi@nokia.com> | 2012-02-21 15:27:00 +0100 |
commit | da2aa0df72250811acbb6af51abc961b38bed77a (patch) | |
tree | 696c211293b82b7cb470f13899dc85d0da83d708 /src/libs/3rdparty/cplusplus | |
parent | 7f943caedbc583d73a7218d1f922a3e8afd2c0b4 (diff) |
C++: Add support for C++11 range-based 'for' loops
Change-Id: I7eef048a7952a79f031ae3d0abba68e3c5ffbfb8
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src/libs/3rdparty/cplusplus')
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.cpp | 58 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.h | 45 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTClone.cpp | 21 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatch0.cpp | 8 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.cpp | 41 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.h | 1 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTPatternBuilder.h | 11 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisit.cpp | 12 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisitor.cpp | 2 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisitor.h | 2 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTfwd.h | 1 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Bind.cpp | 50 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Bind.h | 1 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 27 |
14 files changed, 277 insertions, 3 deletions
diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 445afe81231..1b557d2872e 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -4343,3 +4343,61 @@ unsigned DecltypeSpecifierAST::lastToken() const return 1; } +/** \generated */ +unsigned RangeBasedForStatementAST::firstToken() const +{ + if (for_token) + return for_token; + if (lparen_token) + return lparen_token; + if (type_specifier_list) + if (unsigned candidate = type_specifier_list->firstToken()) + return candidate; + if (declarator) + if (unsigned candidate = declarator->firstToken()) + return candidate; + if (initializer) + if (unsigned candidate = initializer->firstToken()) + return candidate; + if (colon_token) + return colon_token; + if (expression) + if (unsigned candidate = expression->firstToken()) + return candidate; + if (rparen_token) + return rparen_token; + if (statement) + if (unsigned candidate = statement->firstToken()) + return candidate; + return 0; +} + +/** \generated */ +unsigned RangeBasedForStatementAST::lastToken() const +{ + if (statement) + if (unsigned candidate = statement->lastToken()) + return candidate; + if (rparen_token) + return rparen_token + 1; + if (expression) + if (unsigned candidate = expression->lastToken()) + return candidate; + if (colon_token) + return colon_token + 1; + if (initializer) + if (unsigned candidate = initializer->lastToken()) + return candidate; + if (declarator) + if (unsigned candidate = declarator->lastToken()) + return candidate; + if (type_specifier_list) + if (unsigned candidate = type_specifier_list->lastToken()) + return candidate; + if (lparen_token) + return lparen_token + 1; + if (for_token) + return for_token + 1; + return 1; +} + diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index f02cce10da4..9dbc2b0320e 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -247,6 +247,7 @@ public: virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return 0; } virtual QtPropertyDeclarationItemAST *asQtPropertyDeclarationItem() { return 0; } virtual QualifiedNameAST *asQualifiedName() { return 0; } + virtual RangeBasedForStatementAST *asRangeBasedForStatement() { return 0; } virtual ReferenceAST *asReference() { return 0; } virtual ReturnStatementAST *asReturnStatement() { return 0; } virtual SimpleDeclarationAST *asSimpleDeclaration() { return 0; } @@ -1906,6 +1907,50 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT RangeBasedForStatementAST : public StatementAST +{ +public: + unsigned for_token; + unsigned lparen_token; + // declaration + SpecifierListAST *type_specifier_list; + DeclaratorAST *declarator; + // or an expression + ExpressionAST *initializer; + unsigned colon_token; + ExpressionAST *expression; + unsigned rparen_token; + StatementAST *statement; + +public: // annotations + Block *symbol; + +public: + RangeBasedForStatementAST() + : for_token(0) + , lparen_token(0) + , type_specifier_list(0) + , declarator(0) + , initializer(0) + , colon_token(0) + , expression(0) + , rparen_token(0) + , statement(0) + , symbol(0) + {} + + virtual RangeBasedForStatementAST *asRangeBasedForStatement() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual RangeBasedForStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class CPLUSPLUS_EXPORT ForStatementAST: public StatementAST { public: diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 6d77e7e3dab..2478f4f7f29 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -669,6 +669,27 @@ ForeachStatementAST *ForeachStatementAST::clone(MemoryPool *pool) const return ast; } +RangeBasedForStatementAST *RangeBasedForStatementAST::clone(MemoryPool *pool) const +{ + RangeBasedForStatementAST *ast = new (pool) RangeBasedForStatementAST; + ast->for_token = for_token; + ast->lparen_token = lparen_token; + for (SpecifierListAST *iter = type_specifier_list, **ast_iter = &ast->type_specifier_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0); + if (declarator) + ast->declarator = declarator->clone(pool); + if (initializer) + ast->initializer = initializer->clone(pool); + ast->colon_token = colon_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const { ForStatementAST *ast = new (pool) ForStatementAST; diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp index e94a5eec60a..81e74316b6b 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp @@ -456,6 +456,14 @@ bool ForeachStatementAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool RangeBasedForStatementAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (RangeBasedForStatementAST *_other = pattern->asRangeBasedForStatement()) + return matcher->match(this, _other); + + return false; +} + bool ForStatementAST::match0(AST *pattern, ASTMatcher *matcher) { if (ForStatementAST *_other = pattern->asForStatement()) diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index 15595ac1700..a7b19ba99fb 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -1131,6 +1131,47 @@ bool ASTMatcher::match(ForeachStatementAST *node, ForeachStatementAST *pattern) return true; } +bool ASTMatcher::match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->for_token = node->for_token; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->type_specifier_list) + pattern->type_specifier_list = node->type_specifier_list; + else if (! AST::match(node->type_specifier_list, pattern->type_specifier_list, this)) + return false; + + if (! pattern->declarator) + pattern->declarator = node->declarator; + else if (! AST::match(node->declarator, pattern->declarator, this)) + return false; + + if (! pattern->initializer) + pattern->initializer = node->initializer; + else if (! AST::match(node->initializer, pattern->initializer, this)) + return false; + + pattern->colon_token = node->colon_token; + + if (! pattern->expression) + pattern->expression = node->expression; + else if (! AST::match(node->expression, pattern->expression, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + if (! pattern->statement) + pattern->statement = node->statement; + else if (! AST::match(node->statement, pattern->statement, this)) + return false; + + return true; +} + bool ASTMatcher::match(ForStatementAST *node, ForStatementAST *pattern) { (void) node; diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h index 1e32dababed..202a5777414 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.h +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h @@ -146,6 +146,7 @@ public: virtual bool match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern); virtual bool match(QtPropertyDeclarationItemAST *node, QtPropertyDeclarationItemAST *pattern); virtual bool match(QualifiedNameAST *node, QualifiedNameAST *pattern); + virtual bool match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *pattern); virtual bool match(ReferenceAST *node, ReferenceAST *pattern); virtual bool match(ReturnStatementAST *node, ReturnStatementAST *pattern); virtual bool match(SimpleDeclarationAST *node, SimpleDeclarationAST *pattern); diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h index dce4608cde7..e318a32f078 100644 --- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h +++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h @@ -447,6 +447,17 @@ public: return __ast; } + RangeBasedForStatementAST *RangeBasedForStatement(SpecifierListAST *type_specifier_list = 0, DeclaratorAST *declarator = 0, ExpressionAST *initializer = 0, ExpressionAST *expression = 0, StatementAST *statement = 0) + { + RangeBasedForStatementAST *__ast = new (&pool) RangeBasedForStatementAST; + __ast->type_specifier_list = type_specifier_list; + __ast->declarator = declarator; + __ast->initializer = initializer; + __ast->expression = expression; + __ast->statement = statement; + return __ast; + } + ForStatementAST *ForStatement(StatementAST *initializer = 0, ExpressionAST *condition = 0, ExpressionAST *expression = 0, StatementAST *statement = 0) { ForStatementAST *__ast = new (&pool) ForStatementAST; diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index 5d7ab2511de..41cf0cf7559 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -488,6 +488,18 @@ void ForeachStatementAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void RangeBasedForStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(type_specifier_list, visitor); + accept(declarator, visitor); + accept(initializer, visitor); + accept(expression, visitor); + accept(statement, visitor); + } + visitor->endVisit(this); +} + void ForStatementAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.cpp b/src/libs/3rdparty/cplusplus/ASTVisitor.cpp index 63127783af4..5aa1f2d52ff 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisitor.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisitor.cpp @@ -90,5 +90,3 @@ void ASTVisitor::getTokenStartPosition(unsigned index, unsigned *line, unsigned void ASTVisitor::getTokenEndPosition(unsigned index, unsigned *line, unsigned *column) const { getPosition(tokenAt(index).end(), line, column); } - - diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h index 599634090c4..eab93a20bba 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisitor.h +++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h @@ -188,6 +188,7 @@ public: virtual bool visit(QtPropertyDeclarationAST *) { return true; } virtual bool visit(QtPropertyDeclarationItemAST *) { return true; } virtual bool visit(QualifiedNameAST *) { return true; } + virtual bool visit(RangeBasedForStatementAST *) { return true; } virtual bool visit(ReferenceAST *) { return true; } virtual bool visit(ReturnStatementAST *) { return true; } virtual bool visit(SimpleDeclarationAST *) { return true; } @@ -331,6 +332,7 @@ public: virtual void endVisit(QtPropertyDeclarationAST *) {} virtual void endVisit(QtPropertyDeclarationItemAST *) {} virtual void endVisit(QualifiedNameAST *) {} + virtual void endVisit(RangeBasedForStatementAST *) {} virtual void endVisit(ReferenceAST *) {} virtual void endVisit(ReturnStatementAST *) {} virtual void endVisit(SimpleDeclarationAST *) {} diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h index b2036c0672c..f429fe71011 100644 --- a/src/libs/3rdparty/cplusplus/ASTfwd.h +++ b/src/libs/3rdparty/cplusplus/ASTfwd.h @@ -154,6 +154,7 @@ class QtPrivateSlotAST; class QtPropertyDeclarationAST; class QtPropertyDeclarationItemAST; class QualifiedNameAST; +class RangeBasedForStatementAST; class ReferenceAST; class ReturnStatementAST; class SimpleDeclarationAST; diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 1d33812d0ee..5f37dafc83b 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -1282,6 +1282,56 @@ bool Bind::visit(ForeachStatementAST *ast) return false; } +bool Bind::visit(RangeBasedForStatementAST *ast) +{ + Block *block = control()->newBlock(ast->firstToken()); + const unsigned startScopeToken = ast->lparen_token ? ast->lparen_token : ast->firstToken(); + block->setStartOffset(tokenAt(startScopeToken).end()); + block->setEndOffset(tokenAt(ast->lastToken()).begin()); + _scope->addMember(block); + ast->symbol = block; + + Scope *previousScope = switchScope(block); + + FullySpecifiedType type; + for (SpecifierListAST *it = ast->type_specifier_list; it; it = it->next) { + type = this->specifier(it->value, type); + } + DeclaratorIdAST *declaratorId = 0; + type = this->declarator(ast->declarator, type, &declaratorId); + const StringLiteral *initializer = 0; + if (type.isAuto() && translationUnit()->cxx0xEnabled()) { + ExpressionTy exprType = this->expression(ast->expression); + + ArrayType* arrayType = 0; + arrayType = exprType->asArrayType(); + + if (arrayType != 0) + type = arrayType->elementType(); + else if (ast->expression != 0) { + unsigned startOfExpression = ast->expression->firstToken(); + unsigned endOfExpression = ast->expression->lastToken(); + const StringLiteral *sl = asStringLiteral(startOfExpression, endOfExpression); + const std::string buff = std::string("*") + sl->chars() + ".begin()"; + initializer = control()->stringLiteral(buff.c_str(), buff.size()); + } + } + + if (declaratorId && declaratorId->name) { + unsigned sourceLocation = location(declaratorId->name, ast->firstToken()); + Declaration *decl = control()->newDeclaration(sourceLocation, declaratorId->name->name); + decl->setType(type); + decl->setInitializer(initializer); + block->addMember(decl); + } + + /*ExpressionTy initializer =*/ this->expression(ast->initializer); + /*ExpressionTy expression =*/ this->expression(ast->expression); + this->statement(ast->statement); + (void) switchScope(previousScope); + return false; +} + bool Bind::visit(ForStatementAST *ast) { Block *block = control()->newBlock(ast->firstToken()); diff --git a/src/libs/3rdparty/cplusplus/Bind.h b/src/libs/3rdparty/cplusplus/Bind.h index 66d8ed2a0db..d1fff79ea50 100644 --- a/src/libs/3rdparty/cplusplus/Bind.h +++ b/src/libs/3rdparty/cplusplus/Bind.h @@ -152,6 +152,7 @@ protected: virtual bool visit(ExpressionOrDeclarationStatementAST *ast); virtual bool visit(ExpressionStatementAST *ast); virtual bool visit(ForeachStatementAST *ast); + virtual bool visit(RangeBasedForStatementAST *ast); virtual bool visit(ForStatementAST *ast); virtual bool visit(IfStatementAST *ast); virtual bool visit(LabeledStatementAST *ast); diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index cf459dbffbb..8d08e390448 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -3230,6 +3230,32 @@ bool Parser::parseForStatement(StatementAST *&node) rewind(startOfTypeSpecifier); } + if (cxx0xEnabled()) { + RangeBasedForStatementAST *ast = new (_pool) RangeBasedForStatementAST; + ast->for_token = for_token; + ast->lparen_token = lparen_token; + + if (parseTypeSpecifier(ast->type_specifier_list)) + parseDeclarator(ast->declarator, ast->type_specifier_list); + + if ((ast->type_specifier_list || ast->declarator) && LA() == T_COLON) { + ast->colon_token = consumeToken(); + blockErrors(blocked); + + parseExpression(ast->expression); + match(T_RPAREN, &ast->rparen_token); + parseStatement(ast->statement); + + // We need both type specifier and declarator for C++11 range-based for + if (!ast->type_specifier_list || !ast->declarator) + error(for_token, "expected declaration with type specifier"); + + node = ast; + return true; + } + rewind(startOfTypeSpecifier); + } + blockErrors(blocked); // Normal C/C++ for-statement parsing @@ -6108,4 +6134,3 @@ void Parser::fatal(unsigned index, const char *format, ...) va_end(ap); va_end(args); } - |