diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index fd8b4fcfedd..0e885862dad 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -403,12 +403,22 @@ unsigned CallAST::lastToken() const /** \generated */ unsigned CaptureAST::firstToken() const { + if (amper_token) + return amper_token; + if (identifier) + if (unsigned candidate = identifier->firstToken()) + return candidate; return 0; } /** \generated */ unsigned CaptureAST::lastToken() const { + if (identifier) + if (unsigned candidate = identifier->lastToken()) + return candidate; + if (amper_token) + return amper_token + 1; return 1; } diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index c792581d426..961bc2e1a7f 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -4394,8 +4394,14 @@ protected: class CaptureAST: public AST { +public: + unsigned amper_token; + NameAST *identifier; + public: CaptureAST() + : amper_token(0) + , identifier(0) {} virtual CaptureAST *asCapture() { return this; } diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 7c151f09f6d..79e8b7818dd 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -1703,6 +1703,9 @@ LambdaCaptureAST *LambdaCaptureAST::clone(MemoryPool *pool) const CaptureAST *CaptureAST::clone(MemoryPool *pool) const { CaptureAST *ast = new (pool) CaptureAST; + ast->amper_token = amper_token; + if (identifier) + ast->identifier = identifier->clone(pool); return ast; } diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index e2df7d75830..091a5dfd84c 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -2898,6 +2898,13 @@ bool ASTMatcher::match(CaptureAST *node, CaptureAST *pattern) (void) node; (void) pattern; + pattern->amper_token = node->amper_token; + + if (! pattern->identifier) + pattern->identifier = node->identifier; + else if (! AST::match(node->identifier, pattern->identifier, this)) + return false; + return true; } diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h index 142737d44e7..fcf1f56d043 100644 --- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h +++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h @@ -1107,9 +1107,10 @@ public: return __ast; } - CaptureAST *Capture() + CaptureAST *Capture(NameAST *identifier = 0) { CaptureAST *__ast = new (&pool) CaptureAST; + __ast->identifier = identifier; return __ast; } diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index 6434a7c5e2b..24c5a2372f7 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -1237,6 +1237,7 @@ void LambdaCaptureAST::accept0(ASTVisitor *visitor) void CaptureAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { + accept(identifier, visitor); } visitor->endVisit(this); } diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 19c99ae491d..ef71f2900e0 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -1069,7 +1069,7 @@ void Bind::capture(CaptureAST *ast) if (! ast) return; - // See QTCREATORBUG-7968 + name(ast->identifier); } bool Bind::visit(LambdaDeclaratorAST *ast) diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index c7abe2002bb..c7d00c9817b 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -6294,43 +6294,56 @@ bool Parser::parseLambdaCapture(LambdaCaptureAST *&node) return true; } -bool Parser::parseCapture(CaptureAST *&) +bool Parser::parseCapture(CaptureAST *&node) { - // See QTCREATORBUG-7968 - DEBUG_THIS_RULE(); + + if (LA() == T_THIS) { + consumeToken(); + return true; + } + + if (LA() == T_AMPER) + consumeToken(); + if (LA() == T_IDENTIFIER) { - consumeToken(); - return true; + SimpleNameAST *ast = new (_pool) SimpleNameAST; + ast->identifier_token = consumeToken(); - } else if (LA() == T_AMPER && LA(2) == T_IDENTIFIER) { - consumeToken(); - consumeToken(); - return true; - - } else if (LA() == T_THIS) { - consumeToken(); + node = new (_pool) CaptureAST; + node->identifier = ast; return true; } return false; } -bool Parser::parseCaptureList(CaptureListAST *&) +bool Parser::parseCaptureList(CaptureListAST *&node) { DEBUG_THIS_RULE(); CaptureAST *capture = 0; if (parseCapture(capture)) { + node = new (_pool) CaptureListAST; + node->value = capture; + + CaptureListAST **l = &node->next; while (LA() == T_COMMA) { consumeToken(); // consume `,' - + CaptureAST *capture = 0; parseCapture(capture); + if (capture) { + *l = new (_pool) CaptureListAST; + (*l)->value = capture; + l = &(*l)->next; + } } + + return true; } - return true; + return false; } bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node) diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index 392f58d0ee2..e83d7d220f0 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -869,7 +869,7 @@ void FindUsages::capture(CaptureAST *ast) if (! ast) return; - // See QTCREATORBUG-7968 + this->name(ast->identifier); } bool FindUsages::visit(LambdaDeclaratorAST *ast) diff --git a/src/plugins/cpptools/cpplocalsymbols.cpp b/src/plugins/cpptools/cpplocalsymbols.cpp index 026c0274cba..85221969576 100644 --- a/src/plugins/cpptools/cpplocalsymbols.cpp +++ b/src/plugins/cpptools/cpplocalsymbols.cpp @@ -127,6 +127,11 @@ protected: return true; } + virtual bool visit(CaptureAST *ast) + { + return checkLocalUse(ast->identifier, ast->firstToken()); + } + virtual bool visit(IdExpressionAST *ast) { return checkLocalUse(ast->name, ast->firstToken()); diff --git a/tests/auto/cplusplus/findusages/tst_findusages.cpp b/tests/auto/cplusplus/findusages/tst_findusages.cpp index e08138fe383..0137ac51bfd 100644 --- a/tests/auto/cplusplus/findusages/tst_findusages.cpp +++ b/tests/auto/cplusplus/findusages/tst_findusages.cpp @@ -77,7 +77,8 @@ class tst_FindUsages: public QObject private Q_SLOTS: void inlineMethod(); -// void lambdaArg(); + void lambdaCaptureByValue(); + void lambdaCaptureByReference(); // Qt keywords void qproperty_1(); @@ -124,15 +125,46 @@ void tst_FindUsages::inlineMethod() QCOMPARE(findUsages.references().size(), 2); } -#if 0 /* see QTCREATORBUG-7968 */ -void tst_FindUsages::lambdaArg() +void tst_FindUsages::lambdaCaptureByValue() { const QByteArray src = "\n" "void f() {\n" " int test;\n" " [test] { ++test; };\n" "}\n"; - Document::Ptr doc = Document::create("lambdaArg"); + Document::Ptr doc = Document::create("lambdaCaptureByValue"); + doc->setUtf8Source(src); + doc->parse(); + doc->check(); + + QVERIFY(doc->diagnosticMessages().isEmpty()); + QCOMPARE(doc->globalSymbolCount(), 1U); + + Snapshot snapshot; + snapshot.insert(doc); + + Function *f = doc->globalSymbolAt(0)->asFunction(); + QVERIFY(f); + QCOMPARE(f->memberCount(), 1U); + Block *b = f->memberAt(0)->asBlock(); + QCOMPARE(b->memberCount(), 2U); + Declaration *d = b->memberAt(0)->asDeclaration(); + QVERIFY(d); + QCOMPARE(d->name()->identifier()->chars(), "test"); + + FindUsages findUsages(src, doc, snapshot); + findUsages(d); + QCOMPARE(findUsages.usages().size(), 3); +} + +void tst_FindUsages::lambdaCaptureByReference() +{ + const QByteArray src = "\n" + "void f() {\n" + " int test;\n" + " [&test] { ++test; };\n" + "}\n"; + Document::Ptr doc = Document::create("lambdaCaptureByReference"); doc->setUtf8Source(src); doc->parse(); doc->check(); @@ -156,7 +188,6 @@ void tst_FindUsages::lambdaArg() findUsages(d); QCOMPARE(findUsages.usages().size(), 3); } -#endif #if 0 @interface Clazz {} +(void)method:(int)arg; @end diff --git a/tests/tools/cplusplus-dump/dumpers.inc b/tests/tools/cplusplus-dump/dumpers.inc index 4ce49361e63..a08981a8f7d 100644 --- a/tests/tools/cplusplus-dump/dumpers.inc +++ b/tests/tools/cplusplus-dump/dumpers.inc @@ -1645,6 +1645,9 @@ virtual bool visit(LambdaCaptureAST *ast) virtual bool visit(CaptureAST *ast) { + if (ast->amper_token) + terminal(ast->amper_token, ast); + nonterminal(ast->identifier); return false; }