forked from qt-creator/qt-creator
C++: Add support for C++11 range-based 'for' loops
Change-Id: I7eef048a7952a79f031ae3d0abba68e3c5ffbfb8 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
committed by
Roberto Raggi
parent
7f943caedb
commit
da2aa0df72
58
src/libs/3rdparty/cplusplus/AST.cpp
vendored
58
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
45
src/libs/3rdparty/cplusplus/AST.h
vendored
45
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -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:
|
||||
|
||||
21
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
21
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -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;
|
||||
|
||||
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -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())
|
||||
|
||||
41
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
41
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -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;
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -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);
|
||||
|
||||
11
src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
vendored
11
src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
vendored
@@ -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;
|
||||
|
||||
12
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
12
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -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)) {
|
||||
|
||||
2
src/libs/3rdparty/cplusplus/ASTVisitor.cpp
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.cpp
vendored
@@ -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); }
|
||||
|
||||
|
||||
|
||||
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -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 *) {}
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -154,6 +154,7 @@ class QtPrivateSlotAST;
|
||||
class QtPropertyDeclarationAST;
|
||||
class QtPropertyDeclarationItemAST;
|
||||
class QualifiedNameAST;
|
||||
class RangeBasedForStatementAST;
|
||||
class ReferenceAST;
|
||||
class ReturnStatementAST;
|
||||
class SimpleDeclarationAST;
|
||||
|
||||
50
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
50
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -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());
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
@@ -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);
|
||||
|
||||
27
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
27
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user