From 8329d7db943bef3f7929d3802fc31f60e314e179 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Wed, 24 Mar 2010 12:54:25 +0100 Subject: [PATCH] Recognize C++0x lambda expressions. --- src/libs/cplusplus/CppDocument.cpp | 1 + src/shared/cplusplus/AST.cpp | 116 +++++++++++++++ src/shared/cplusplus/AST.h | 158 +++++++++++++++++++- src/shared/cplusplus/ASTClone.cpp | 70 +++++++++ src/shared/cplusplus/ASTMatch0.cpp | 48 ++++++ src/shared/cplusplus/ASTMatcher.cpp | 120 +++++++++++++++ src/shared/cplusplus/ASTMatcher.h | 6 + src/shared/cplusplus/ASTVisit.cpp | 54 +++++++ src/shared/cplusplus/ASTVisitor.h | 15 ++ src/shared/cplusplus/ASTfwd.h | 8 + src/shared/cplusplus/CheckExpression.cpp | 11 ++ src/shared/cplusplus/CheckExpression.h | 1 + src/shared/cplusplus/Keywords.cpp | 62 ++++---- src/shared/cplusplus/Lexer.cpp | 8 +- src/shared/cplusplus/Lexer.h | 6 +- src/shared/cplusplus/Parser.cpp | 181 ++++++++++++++++++++++- src/shared/cplusplus/Parser.h | 10 ++ src/shared/cplusplus/TranslationUnit.cpp | 8 + src/shared/cplusplus/TranslationUnit.h | 4 + 19 files changed, 850 insertions(+), 37 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index bc6605f2bc2..316d8d26e2c 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -123,6 +123,7 @@ Document::Document(const QString &fileName) localFileName.size()); _translationUnit = new TranslationUnit(_control, fileId); _translationUnit->setQtMocRunEnabled(true); + _translationUnit->setCxxOxEnabled(true); _translationUnit->setObjCEnabled(true); (void) _control->switchTranslationUnit(_translationUnit); } diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 785b8178d44..76771804550 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -2416,3 +2416,119 @@ unsigned ObjCSynchronizedStatementAST::lastToken() const if (lparen_token) return lparen_token + 1; return synchronized_token + 1; } + +unsigned LambdaExpressionAST::firstToken() const +{ + if (lambda_introducer) + return lambda_introducer->firstToken(); + + // assert? + return 0; +} + +unsigned LambdaExpressionAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (lambda_declarator) + return lambda_declarator->lastToken(); + + return lambda_introducer->lastToken(); +} + +unsigned LambdaIntroducerAST::firstToken() const +{ + return lbracket_token; +} + +unsigned LambdaIntroducerAST::lastToken() const +{ + if (rbracket_token) + return rbracket_token + 1; + else if (lambda_capture) + return lambda_capture->lastToken(); + return lbracket_token + 1; +} + +unsigned LambdaCaptureAST::firstToken() const +{ + if (default_capture) + return default_capture; + + else if (capture_list) + return capture_list->firstToken(); + + // assert? + return 0; +} + +unsigned LambdaCaptureAST::lastToken() const +{ + if (capture_list) + return capture_list->lastToken(); + + else if (default_capture) + return default_capture + 1; + + // assert? + return 0; +} + +unsigned CaptureAST::firstToken() const +{ + // ### implement me + return 0; +} + +unsigned CaptureAST::lastToken() const +{ + // ### implement me + return 0; +} + +unsigned LambdaDeclaratorAST::firstToken() const +{ + return lparen_token; +} + +unsigned LambdaDeclaratorAST::lastToken() const +{ + if (trailing_return_type) + return trailing_return_type->lastToken(); + + else if (exception_specification) + return exception_specification->lastToken(); + + else if (mutable_token) + return mutable_token + 1; + + else if (attributes) + return attributes->lastToken(); + + else if (rparen_token) + return rparen_token + 1; + + else if (parameter_declaration_clause) + return parameter_declaration_clause->lastToken(); + + return lparen_token + 1; +} + +unsigned TrailingReturnTypeAST::firstToken() const +{ + return arrow_token; +} + +unsigned TrailingReturnTypeAST::lastToken() const +{ + if (declarator) + return declarator->lastToken(); + + else if (type_specifiers) + return type_specifiers->lastToken(); + + else if (attributes) + return attributes->lastToken(); + + return arrow_token + 1; +} diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 11f038db5a6..6335fce4ba3 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -164,6 +164,7 @@ public: virtual BoolLiteralAST *asBoolLiteral() { return 0; } virtual BreakStatementAST *asBreakStatement() { return 0; } virtual CallAST *asCall() { return 0; } + virtual CaptureAST *asCapture() { return 0; } virtual CaseStatementAST *asCaseStatement() { return 0; } virtual CastExpressionAST *asCastExpression() { return 0; } virtual CatchClauseAST *asCatchClause() { return 0; } @@ -201,6 +202,10 @@ public: virtual GotoStatementAST *asGotoStatement() { return 0; } virtual IfStatementAST *asIfStatement() { return 0; } virtual LabeledStatementAST *asLabeledStatement() { return 0; } + virtual LambdaCaptureAST *asLambdaCapture() { return 0; } + virtual LambdaDeclaratorAST *asLambdaDeclarator() { return 0; } + virtual LambdaExpressionAST *asLambdaExpression() { return 0; } + virtual LambdaIntroducerAST *asLambdaIntroducer() { return 0; } virtual LinkageBodyAST *asLinkageBody() { return 0; } virtual LinkageSpecificationAST *asLinkageSpecification() { return 0; } virtual MemInitializerAST *asMemInitializer() { return 0; } @@ -280,6 +285,7 @@ public: virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return 0; } virtual ThisExpressionAST *asThisExpression() { return 0; } virtual ThrowExpressionAST *asThrowExpression() { return 0; } + virtual TrailingReturnTypeAST *asTrailingReturnType() { return 0; } virtual TranslationUnitAST *asTranslationUnit() { return 0; } virtual TryBlockStatementAST *asTryBlockStatement() { return 0; } virtual TypeConstructorCallAST *asTypeConstructorCall() { return 0; } @@ -4103,7 +4109,157 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; -} // end of namespace CPlusPlus +class LambdaExpressionAST: public ExpressionAST +{ +public: + LambdaIntroducerAST *lambda_introducer; + LambdaDeclaratorAST *lambda_declarator; + StatementAST *statement; + +public: + LambdaExpressionAST() + : lambda_introducer(0) + , lambda_declarator(0) + , statement(0) + {} + + virtual LambdaExpressionAST *asLambdaExpression() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + virtual LambdaExpressionAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class LambdaIntroducerAST: public AST +{ +public: + unsigned lbracket_token; + LambdaCaptureAST *lambda_capture; + unsigned rbracket_token; + +public: + LambdaIntroducerAST() + : lbracket_token(0) + , lambda_capture(0) + , rbracket_token(0) + {} + + virtual LambdaIntroducerAST *asLambdaIntroducer() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual LambdaIntroducerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class LambdaCaptureAST: public AST +{ +public: + unsigned default_capture; + CaptureListAST *capture_list; + +public: + LambdaCaptureAST() + : default_capture(0) + , capture_list(0) + {} + + virtual LambdaCaptureAST *asLambdaCapture() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual LambdaCaptureAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CaptureAST: public AST +{ +public: + CaptureAST() + {} + + virtual CaptureAST *asCapture() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual CaptureAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class LambdaDeclaratorAST: public AST +{ +public: + unsigned lparen_token; + ParameterDeclarationClauseAST *parameter_declaration_clause; + unsigned rparen_token; + SpecifierListAST *attributes; + unsigned mutable_token; + ExceptionSpecificationAST *exception_specification; + TrailingReturnTypeAST *trailing_return_type; + +public: + LambdaDeclaratorAST() + : lparen_token(0) + , parameter_declaration_clause(0) + , rparen_token(0) + , attributes(0) + , mutable_token(0) + , exception_specification(0) + , trailing_return_type(0) + {} + + virtual LambdaDeclaratorAST *asLambdaDeclarator() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual LambdaDeclaratorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class TrailingReturnTypeAST: public AST +{ +public: + unsigned arrow_token; + SpecifierListAST *attributes; + SpecifierListAST *type_specifiers; + DeclaratorAST *declarator; + +public: + TrailingReturnTypeAST() + : arrow_token(0) + , attributes(0) + , type_specifiers(0) + , declarator(0) + {} + + virtual TrailingReturnTypeAST *asTrailingReturnType() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual TrailingReturnTypeAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +} // end of namespace CPlusPlus #endif // CPLUSPLUS_AST_H diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index 586d88e21a7..425c81c76eb 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -1586,3 +1586,73 @@ ObjCSynchronizedStatementAST *ObjCSynchronizedStatementAST::clone(MemoryPool *po return ast; } +LambdaExpressionAST *LambdaExpressionAST::clone(MemoryPool *pool) const +{ + LambdaExpressionAST *ast = new (pool) LambdaExpressionAST; + if (lambda_introducer) + ast->lambda_introducer = lambda_introducer->clone(pool); + if (lambda_declarator) + ast->lambda_declarator = lambda_declarator->clone(pool); + if (statement) + ast->statement = statement->clone(pool); + return ast; +} + +LambdaIntroducerAST *LambdaIntroducerAST::clone(MemoryPool *pool) const +{ + LambdaIntroducerAST *ast = new (pool) LambdaIntroducerAST; + ast->lbracket_token = lbracket_token; + if (lambda_capture) + ast->lambda_capture = lambda_capture->clone(pool); + ast->rbracket_token = rbracket_token; + return ast; +} + +LambdaCaptureAST *LambdaCaptureAST::clone(MemoryPool *pool) const +{ + LambdaCaptureAST *ast = new (pool) LambdaCaptureAST; + for (CaptureListAST *iter = capture_list, **ast_iter = &ast->capture_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) CaptureListAST((iter->value) ? iter->value->clone(pool) : 0); + return ast; +} + +CaptureAST *CaptureAST::clone(MemoryPool *pool) const +{ + CaptureAST *ast = new (pool) CaptureAST; + return ast; +} + +LambdaDeclaratorAST *LambdaDeclaratorAST::clone(MemoryPool *pool) const +{ + LambdaDeclaratorAST *ast = new (pool) LambdaDeclaratorAST; + ast->lparen_token = lparen_token; + if (parameter_declaration_clause) + ast->parameter_declaration_clause = parameter_declaration_clause->clone(pool); + ast->rparen_token = rparen_token; + for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0); + ast->mutable_token = mutable_token; + if (exception_specification) + ast->exception_specification = exception_specification->clone(pool); + if (trailing_return_type) + ast->trailing_return_type = trailing_return_type->clone(pool); + return ast; +} + +TrailingReturnTypeAST *TrailingReturnTypeAST::clone(MemoryPool *pool) const +{ + TrailingReturnTypeAST *ast = new (pool) TrailingReturnTypeAST; + ast->arrow_token = arrow_token; + for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0); + for (SpecifierListAST *iter = type_specifiers, **ast_iter = &ast->type_specifiers; + 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); + return ast; +} + diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index 0b97e9c7fa2..bc2f252b819 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -1089,3 +1089,51 @@ bool ObjCSynchronizedStatementAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool LambdaExpressionAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (LambdaExpressionAST *_other = pattern->asLambdaExpression()) + return matcher->match(this, _other); + + return false; +} + +bool LambdaIntroducerAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (LambdaIntroducerAST *_other = pattern->asLambdaIntroducer()) + return matcher->match(this, _other); + + return false; +} + +bool LambdaCaptureAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (LambdaCaptureAST *_other = pattern->asLambdaCapture()) + return matcher->match(this, _other); + + return false; +} + +bool CaptureAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (CaptureAST *_other = pattern->asCapture()) + return matcher->match(this, _other); + + return false; +} + +bool LambdaDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (LambdaDeclaratorAST *_other = pattern->asLambdaDeclarator()) + return matcher->match(this, _other); + + return false; +} + +bool TrailingReturnTypeAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (TrailingReturnTypeAST *_other = pattern->asTrailingReturnType()) + return matcher->match(this, _other); + + return false; +} + diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 42cbadcbdbf..75ec26467dc 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -2669,3 +2669,123 @@ bool ASTMatcher::match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedState return true; } +bool ASTMatcher::match(LambdaExpressionAST *node, LambdaExpressionAST *pattern) +{ + (void) node; + (void) pattern; + + if (! pattern->lambda_introducer) + pattern->lambda_introducer = node->lambda_introducer; + else if (! AST::match(node->lambda_introducer, pattern->lambda_introducer, this)) + return false; + + if (! pattern->lambda_declarator) + pattern->lambda_declarator = node->lambda_declarator; + else if (! AST::match(node->lambda_declarator, pattern->lambda_declarator, this)) + return false; + + if (! pattern->statement) + pattern->statement = node->statement; + else if (! AST::match(node->statement, pattern->statement, this)) + return false; + + return true; +} + +bool ASTMatcher::match(LambdaIntroducerAST *node, LambdaIntroducerAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->lbracket_token = node->lbracket_token; + + if (! pattern->lambda_capture) + pattern->lambda_capture = node->lambda_capture; + else if (! AST::match(node->lambda_capture, pattern->lambda_capture, this)) + return false; + + pattern->rbracket_token = node->rbracket_token; + + return true; +} + +bool ASTMatcher::match(LambdaCaptureAST *node, LambdaCaptureAST *pattern) +{ + (void) node; + (void) pattern; + + if (! pattern->capture_list) + pattern->capture_list = node->capture_list; + else if (! AST::match(node->capture_list, pattern->capture_list, this)) + return false; + + return true; +} + +bool ASTMatcher::match(CaptureAST *node, CaptureAST *pattern) +{ + (void) node; + (void) pattern; + + return true; +} + +bool ASTMatcher::match(LambdaDeclaratorAST *node, LambdaDeclaratorAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->parameter_declaration_clause) + pattern->parameter_declaration_clause = node->parameter_declaration_clause; + else if (! AST::match(node->parameter_declaration_clause, pattern->parameter_declaration_clause, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + if (! pattern->attributes) + pattern->attributes = node->attributes; + else if (! AST::match(node->attributes, pattern->attributes, this)) + return false; + + pattern->mutable_token = node->mutable_token; + + if (! pattern->exception_specification) + pattern->exception_specification = node->exception_specification; + else if (! AST::match(node->exception_specification, pattern->exception_specification, this)) + return false; + + if (! pattern->trailing_return_type) + pattern->trailing_return_type = node->trailing_return_type; + else if (! AST::match(node->trailing_return_type, pattern->trailing_return_type, this)) + return false; + + return true; +} + +bool ASTMatcher::match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->arrow_token = node->arrow_token; + + if (! pattern->attributes) + pattern->attributes = node->attributes; + else if (! AST::match(node->attributes, pattern->attributes, this)) + return false; + + if (! pattern->type_specifiers) + pattern->type_specifiers = node->type_specifiers; + else if (! AST::match(node->type_specifiers, pattern->type_specifiers, this)) + return false; + + if (! pattern->declarator) + pattern->declarator = node->declarator; + else if (! AST::match(node->declarator, pattern->declarator, this)) + return false; + + return true; +} + diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index baae1ce874f..d3fcab5dcf6 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -170,6 +170,12 @@ public: virtual bool match(ObjCDynamicPropertiesDeclarationAST *node, ObjCDynamicPropertiesDeclarationAST *pattern); virtual bool match(ObjCFastEnumerationAST *node, ObjCFastEnumerationAST *pattern); virtual bool match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedStatementAST *pattern); + virtual bool match(LambdaExpressionAST *node, LambdaExpressionAST *pattern); + virtual bool match(LambdaIntroducerAST *node, LambdaIntroducerAST *pattern); + virtual bool match(LambdaCaptureAST *node, LambdaCaptureAST *pattern); + virtual bool match(LambdaDeclaratorAST *node, LambdaDeclaratorAST *pattern); + virtual bool match(CaptureAST *node, CaptureAST *pattern); + virtual bool match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern); }; } // end of namespace CPlusPlus diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index 8216f87b488..9e3b249ef3a 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -1159,3 +1159,57 @@ void ObjCSynchronizedStatementAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void LambdaExpressionAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(lambda_introducer, visitor); + accept(lambda_declarator, visitor); + accept(statement, visitor); + } + visitor->endVisit(this); +} + +void LambdaIntroducerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(lambda_capture, visitor); + } + visitor->endVisit(this); +} + +void LambdaCaptureAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(capture_list, visitor); + } + visitor->endVisit(this); +} + +void CaptureAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void LambdaDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(parameter_declaration_clause, visitor); + accept(attributes, visitor); + accept(exception_specification, visitor); + accept(trailing_return_type, visitor); + } + visitor->endVisit(this); +} + +void TrailingReturnTypeAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(attributes, visitor); + accept(type_specifiers, visitor); + accept(declarator, visitor); + } + visitor->endVisit(this); +} + diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 4490f11faab..078dfee89e2 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -209,6 +209,14 @@ public: virtual bool visit(QtInterfacesDeclarationAST *) { return true; } virtual bool visit(QtInterfaceNameAST *) { return true; } + // C++0x + virtual bool visit(LambdaExpressionAST *) { return true; } + virtual bool visit(LambdaIntroducerAST *) { return true; } + virtual bool visit(LambdaCaptureAST *) { return true; } + virtual bool visit(LambdaDeclaratorAST *) { return true; } + virtual bool visit(CaptureAST *) { return true; } + virtual bool visit(TrailingReturnTypeAST *) { return true; } + // ObjC++ virtual bool visit(ObjCClassDeclarationAST *) { return true; } virtual bool visit(ObjCClassForwardDeclarationAST *) { return true; } @@ -343,6 +351,13 @@ public: virtual void endVisit(QtInterfacesDeclarationAST *) { } virtual void endVisit(QtInterfaceNameAST *) { } + virtual void endVisit(LambdaExpressionAST *) { } + virtual void endVisit(LambdaIntroducerAST *) { } + virtual void endVisit(LambdaCaptureAST *) { } + virtual void endVisit(LambdaDeclaratorAST *) { } + virtual void endVisit(CaptureAST *) { } + virtual void endVisit(TrailingReturnTypeAST *) { } + // ObjC++ virtual void endVisit(ObjCClassDeclarationAST *) { } virtual void endVisit(ObjCClassForwardDeclarationAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index f8f129acb49..ac6006256b1 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -71,6 +71,7 @@ class BinaryExpressionAST; class BoolLiteralAST; class BreakStatementAST; class CallAST; +class CaptureAST; class CaseStatementAST; class CastExpressionAST; class CatchClauseAST; @@ -108,6 +109,10 @@ class FunctionDefinitionAST; class GotoStatementAST; class IfStatementAST; class LabeledStatementAST; +class LambdaCaptureAST; +class LambdaDeclaratorAST; +class LambdaExpressionAST; +class LambdaIntroducerAST; class LinkageBodyAST; class LinkageSpecificationAST; class MemInitializerAST; @@ -187,6 +192,7 @@ class TemplateIdAST; class TemplateTypeParameterAST; class ThisExpressionAST; class ThrowExpressionAST; +class TrailingReturnTypeAST; class TranslationUnitAST; class TryBlockStatementAST; class TypeConstructorCallAST; @@ -219,6 +225,8 @@ typedef List<QtPropertyDeclarationItemAST *> QtPropertyDeclarationItemListAST; typedef List<NameAST *> NameListAST; typedef List<QtInterfaceNameAST *> QtInterfaceNameListAST; +typedef List<CaptureAST *> CaptureListAST; + typedef List<ObjCMessageArgumentAST *> ObjCMessageArgumentListAST; typedef List<ObjCSelectorArgumentAST *> ObjCSelectorArgumentListAST; typedef List<ObjCPropertyAttributeAST *> ObjCPropertyAttributeListAST; diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index ecbf991c9ad..42f1d85a713 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -388,8 +388,19 @@ bool CheckExpression::visit(ObjCEncodeExpressionAST * /*ast*/) bool CheckExpression::visit(ObjCSelectorExpressionAST *ast) { + if (_scope->isPrototypeScope()) + return false; + (void) semantic()->check(ast->selector, _scope); return false; } +bool CheckExpression::visit(LambdaExpressionAST *ast) +{ + if (_scope->isPrototypeScope()) + return false; + + (void) semantic()->check(ast->statement, _scope); + return false; +} diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h index 6485d1236dd..736eefa0ed2 100644 --- a/src/shared/cplusplus/CheckExpression.h +++ b/src/shared/cplusplus/CheckExpression.h @@ -95,6 +95,7 @@ protected: virtual bool visit(QtMethodAST *ast); virtual bool visit(CompoundLiteralAST *ast); virtual bool visit(CompoundExpressionAST *ast); + virtual bool visit(LambdaExpressionAST *ast); //names virtual bool visit(QualifiedNameAST *ast); diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index 0e6beaf06f4..94699c1745e 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -51,7 +51,7 @@ using namespace CPlusPlus; -static inline int classify2(const char *s, bool) { +static inline int classify2(const char *s, bool, bool) { if (s[0] == 'd') { if (s[1] == 'o') { return T_DO; @@ -65,7 +65,7 @@ static inline int classify2(const char *s, bool) { return T_IDENTIFIER; } -static inline int classify3(const char *s, bool q) { +static inline int classify3(const char *s, bool q, bool) { if (s[0] == 'a') { if (s[1] == 's') { if (s[2] == 'm') { @@ -114,7 +114,7 @@ static inline int classify3(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify4(const char *s, bool q) { +static inline int classify4(const char *s, bool q, bool) { if (s[0] == 'a') { if (s[1] == 'u') { if (s[2] == 't') { @@ -220,7 +220,7 @@ static inline int classify4(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify5(const char *s, bool q) { +static inline int classify5(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { @@ -359,7 +359,7 @@ static inline int classify5(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify6(const char *s, bool q) { +static inline int classify6(const char *s, bool q, bool) { if (s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'l') { @@ -558,7 +558,7 @@ static inline int classify6(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify7(const char *s, bool q) { +static inline int classify7(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { @@ -745,7 +745,7 @@ static inline int classify7(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify8(const char *s, bool q) { +static inline int classify8(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'i') { @@ -956,7 +956,7 @@ static inline int classify8(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify9(const char *s, bool q) { +static inline int classify9(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'c') { @@ -1050,7 +1050,7 @@ static inline int classify9(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify10(const char *s, bool q) { +static inline int classify10(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'i') { @@ -1168,7 +1168,7 @@ static inline int classify10(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify11(const char *s, bool q) { +static inline int classify11(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { @@ -1241,7 +1241,7 @@ static inline int classify11(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify12(const char *s, bool q) { +static inline int classify12(const char *s, bool q, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'v') { @@ -1320,7 +1320,7 @@ static inline int classify12(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify13(const char *s, bool) { +static inline int classify13(const char *s, bool, bool) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { @@ -1351,7 +1351,7 @@ static inline int classify13(const char *s, bool) { return T_IDENTIFIER; } -static inline int classify16(const char *s, bool) { +static inline int classify16(const char *s, bool, bool) { if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 'i') { @@ -1388,7 +1388,7 @@ static inline int classify16(const char *s, bool) { return T_IDENTIFIER; } -static inline int classify14(const char *s, bool q) { +static inline int classify14(const char *s, bool q, bool) { if (q && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'P') { @@ -1421,7 +1421,7 @@ static inline int classify14(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify19(const char *s, bool q) { +static inline int classify19(const char *s, bool q, bool) { if (q && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'D') { @@ -1465,23 +1465,23 @@ static inline int classify19(const char *s, bool q) { } -int Lexer::classify(const char *s, int n, bool q) { +int Lexer::classify(const char *s, int n, bool q, bool x) { switch (n) { - case 2: return classify2(s, q); - case 3: return classify3(s, q); - case 4: return classify4(s, q); - case 5: return classify5(s, q); - case 6: return classify6(s, q); - case 7: return classify7(s, q); - case 8: return classify8(s, q); - case 9: return classify9(s, q); - case 10: return classify10(s, q); - case 11: return classify11(s, q); - case 12: return classify12(s, q); - case 13: return classify13(s, q); - case 14: return classify14(s, q); - case 16: return classify16(s, q); - case 19: return classify19(s, q); + case 2: return classify2(s, q, x); + case 3: return classify3(s, q, x); + case 4: return classify4(s, q, x); + case 5: return classify5(s, q, x); + case 6: return classify6(s, q, x); + case 7: return classify7(s, q, x); + case 8: return classify8(s, q, x); + case 9: return classify9(s, q, x); + case 10: return classify10(s, q, x); + case 11: return classify11(s, q, x); + case 12: return classify12(s, q, x); + case 13: return classify13(s, q, x); + case 14: return classify14(s, q, x); + case 16: return classify16(s, q, x); + case 19: return classify19(s, q, x); default: return T_IDENTIFIER; } // switch } diff --git a/src/shared/cplusplus/Lexer.cpp b/src/shared/cplusplus/Lexer.cpp index 36b2ba8b0b9..3b75c684219 100644 --- a/src/shared/cplusplus/Lexer.cpp +++ b/src/shared/cplusplus/Lexer.cpp @@ -119,6 +119,12 @@ bool Lexer::qtMocRunEnabled() const void Lexer::setQtMocRunEnabled(bool onoff) { f._qtMocRunEnabled = onoff; } +bool Lexer::cxx0xEnabled() const +{ return f._cxx0xEnabled; } + +void Lexer::setCxxOxEnabled(bool onoff) +{ f._cxx0xEnabled = onoff; } + bool Lexer::objCEnabled() const { return f._objCEnabled; } @@ -680,7 +686,7 @@ void Lexer::scan_helper(Token *tok) yyinp(); int yylen = _currentChar - yytext; if (f._scanKeywords) - tok->f.kind = classify(yytext, yylen, f._qtMocRunEnabled); + tok->f.kind = classify(yytext, yylen, f._qtMocRunEnabled, f._cxx0xEnabled); else tok->f.kind = T_IDENTIFIER; diff --git a/src/shared/cplusplus/Lexer.h b/src/shared/cplusplus/Lexer.h index 36bb8b1285d..f528455452c 100644 --- a/src/shared/cplusplus/Lexer.h +++ b/src/shared/cplusplus/Lexer.h @@ -77,6 +77,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); + bool cxx0xEnabled() const; + void setCxxOxEnabled(bool onoff); + bool objCEnabled() const; void setObjCEnabled(bool onoff); @@ -111,7 +114,7 @@ public: private: void scan_helper(Token *tok); void setSource(const char *firstChar, const char *lastChar); - static int classify(const char *string, int length, bool q); + static int classify(const char *string, int length, bool q, bool cxx0x); static int classifyObjCAtKeyword(const char *s, int n); static int classifyOperator(const char *string, int length); @@ -135,6 +138,7 @@ private: unsigned _scanKeywords: 1; unsigned _scanAngleStringLiteralTokens: 1; unsigned _qtMocRunEnabled: 1; + unsigned _cxx0xEnabled: 1; unsigned _objCEnabled: 1; }; diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 7be7e61dab7..d5c55a2c358 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -197,7 +197,7 @@ Parser::Parser(TranslationUnit *unit) _tokenIndex(1), _templateArguments(0), _qtMocRunEnabled(false), - _cxx0xEnabled(true), // C++0x is enabled by default + _cxx0xEnabled(false), _objCEnabled(false), _inFunctionBody(false), _inObjCImplementationContext(false), @@ -2524,7 +2524,8 @@ bool Parser::parseExpressionStatement(StatementAST *&node) ExpressionAST *expression = 0; if (parseExpression(expression)) { ExpressionStatementAST *ast = new (previousPool) ExpressionStatementAST; - ast->expression = expression->clone(previousPool); + if (expression) + ast->expression = expression->clone(previousPool); match(T_SEMICOLON, &ast->semicolon_token); node = ast; parsed = true; @@ -3646,7 +3647,20 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node) case T_SLOT: return parseQtMethod(node); - case T_LBRACKET: + case T_LBRACKET: { + const unsigned lbracket_token = cursor(); + + if (_cxx0xEnabled) { + if (parseLambdaExpression(node)) + return true; + } + + if (_objCEnabled) { + rewind(lbracket_token); + return parseObjCExpression(node); + } + } break; + case T_AT_STRING_LITERAL: case T_AT_ENCODE: case T_AT_PROTOCOL: @@ -5491,3 +5505,164 @@ int Parser::peekAtQtContextKeyword() const const Identifier *id = tok().identifier; return classifyQtContextKeyword(id->chars(), id->size()); } + +bool Parser::parseLambdaExpression(ExpressionAST *&node) +{ + DEBUG_THIS_RULE(); + + LambdaIntroducerAST *lambda_introducer = 0; + if (parseLambdaIntroducer(lambda_introducer)) { + LambdaExpressionAST *ast = new (_pool) LambdaExpressionAST; + ast->lambda_introducer = lambda_introducer; + parseLambdaDeclarator(ast->lambda_declarator); + parseCompoundStatement(ast->statement); + node = ast; + return true; + } + + return false; +} + +bool Parser::parseLambdaIntroducer(LambdaIntroducerAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() != T_LBRACKET) + return false; + + LambdaIntroducerAST *ast = new (_pool) LambdaIntroducerAST; + ast->lbracket_token = consumeToken(); + + if (LA() != T_RBRACKET) + parseLambdaCapture(ast->lambda_capture); + + if (LA() == T_RBRACKET) { + ast->rbracket_token = consumeToken(); + + if (LA() == T_LPAREN || LA() == T_LBRACE) { + node = ast; + return true; + } + } + + return false; +} + +bool Parser::parseLambdaCapture(LambdaCaptureAST *&node) +{ + DEBUG_THIS_RULE(); + bool startsWithDefaultCapture = false; + + unsigned default_capture = 0; + CaptureListAST *capture_list = 0; + + if (LA() == T_AMPER || LA() == T_EQUAL) { + if (LA(2) == T_COMMA || LA(2) == T_RBRACKET) { + startsWithDefaultCapture = true; + default_capture = consumeToken(); // consume capture-default + } + } + + if (startsWithDefaultCapture && LA() == T_COMMA) { + consumeToken(); // consume ',' + parseCaptureList(capture_list); // required + + } else if (LA() != T_RBRACKET) { + parseCaptureList(capture_list); // optional + + } + + LambdaCaptureAST *ast = new (_pool) LambdaCaptureAST; + ast->default_capture = default_capture; + ast->capture_list = capture_list; + node = ast; + + return true; +} + +bool Parser::parseCapture(CaptureAST *&) +{ + DEBUG_THIS_RULE(); + if (LA() == T_IDENTIFIER) { + consumeToken(); + return true; + + } else if (LA() == T_AMPER && LA(2) == T_IDENTIFIER) { + consumeToken(); + consumeToken(); + return true; + + } else if (LA() == T_THIS) { + consumeToken(); + return true; + } + + return false; +} + +bool Parser::parseCaptureList(CaptureListAST *&) +{ + DEBUG_THIS_RULE(); + + CaptureAST *capture = 0; + + if (parseCapture(capture)) { + while (LA() == T_COMMA) { + consumeToken(); // consume `,' + + parseCapture(capture); + } + } + + return true; +} + +bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() != T_LPAREN) + return false; + + LambdaDeclaratorAST *ast = new (_pool) LambdaDeclaratorAST; + + ast->lparen_token = consumeToken(); // consume `(' + parseParameterDeclarationClause(ast->parameter_declaration_clause); + match(T_RPAREN, &ast->rparen_token); + + SpecifierListAST **attr = &ast->attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + if (LA() == T_MUTABLE) + ast->mutable_token = consumeToken(); + + parseExceptionSpecification(ast->exception_specification); + parseTrailingReturnType(ast->trailing_return_type); + node = ast; + + return true; +} + +bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() != T_ARROW) + return false; + + TrailingReturnTypeAST *ast = new (_pool) TrailingReturnTypeAST; + + ast->arrow_token = consumeToken(); + + SpecifierListAST **attr = &ast->attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + parseTrailingTypeSpecifierSeq(ast->type_specifiers); + parseAbstractDeclarator(ast->declarator); + return true; +} + +bool Parser::parseTrailingTypeSpecifierSeq(SpecifierListAST *&node) +{ + DEBUG_THIS_RULE(); + return parseSimpleTypeSpecifier(node); +} diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index b6f28098371..d31551f1872 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -221,6 +221,16 @@ public: // Qt MOC run bool parseQtMethod(ExpressionAST *&node); + // C++0x + bool parseLambdaExpression(ExpressionAST *&node); + bool parseLambdaIntroducer(LambdaIntroducerAST *&node); + bool parseLambdaCapture(LambdaCaptureAST *&node); + bool parseLambdaDeclarator(LambdaDeclaratorAST *&node); + bool parseCapture(CaptureAST *&node); + bool parseCaptureList(CaptureListAST *&node); + bool parseTrailingReturnType(TrailingReturnTypeAST *&node); + bool parseTrailingTypeSpecifierSeq(SpecifierListAST *&node); + // ObjC++ bool parseObjCExpression(ExpressionAST *&node); bool parseObjCClassForwardDeclaration(DeclarationAST *&node); diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp index f19b78d851d..340b763fc51 100644 --- a/src/shared/cplusplus/TranslationUnit.cpp +++ b/src/shared/cplusplus/TranslationUnit.cpp @@ -87,6 +87,12 @@ bool TranslationUnit::qtMocRunEnabled() const void TranslationUnit::setQtMocRunEnabled(bool onoff) { f._qtMocRunEnabled = onoff; } +bool TranslationUnit::cxx0xEnabled() const +{ return f._cxx0xEnabled; } + +void TranslationUnit::setCxxOxEnabled(bool onoff) +{ f._cxx0xEnabled = onoff; } + bool TranslationUnit::objCEnabled() const { return f._objCEnabled; } @@ -173,6 +179,7 @@ void TranslationUnit::tokenize() Lexer lex(this); lex.setQtMocRunEnabled(f._qtMocRunEnabled); + lex.setCxxOxEnabled(f._cxx0xEnabled); lex.setObjCEnabled(f._objCEnabled); std::stack<unsigned> braces; @@ -256,6 +263,7 @@ bool TranslationUnit::parse(ParseMode mode) Parser parser(this); parser.setQtMocRunEnabled(f._qtMocRunEnabled); + parser.setCxxOxEnabled(f._cxx0xEnabled); parser.setObjCEnabled(f._objCEnabled); bool parsed = false; diff --git a/src/shared/cplusplus/TranslationUnit.h b/src/shared/cplusplus/TranslationUnit.h index 53e11abb9bd..19324f6b877 100644 --- a/src/shared/cplusplus/TranslationUnit.h +++ b/src/shared/cplusplus/TranslationUnit.h @@ -98,6 +98,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); + bool cxx0xEnabled() const; + void setCxxOxEnabled(bool onoff); + bool objCEnabled() const; void setObjCEnabled(bool onoff); @@ -195,6 +198,7 @@ private: unsigned _blockErrors: 1; unsigned _skipFunctionBody: 1; unsigned _qtMocRunEnabled: 1; + unsigned _cxx0xEnabled: 1; unsigned _objCEnabled: 1; }; union { -- GitLab