diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2022-08-17 18:10:53 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2022-08-23 13:52:11 +0000 |
commit | ca00b874a75d8cd64f9768d21959a530b928c6dc (patch) | |
tree | 8292188e0ac3952854cd653bfa573c1cf94772de /src/libs/3rdparty/cplusplus | |
parent | 5fab54d95aadaf28c4f7d10e601cc12feb682429 (diff) |
CPlusPlus: Support structured bindings
While we do recommend clangd for modern code bases, we should still be
able to parse basic language constructs.
Fixes: QTCREATORBUG-27975
Change-Id: I189b991685a5cd5f62f2afce77878b60c895e8f9
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/libs/3rdparty/cplusplus')
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.cpp | 1 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.h | 19 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTClone.cpp | 8 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatch0.cpp | 8 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.cpp | 9 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.h | 1 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTPatternBuilder.h | 7 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisit.cpp | 8 | ||||
-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 | 100 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Bind.h | 6 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 42 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.h | 1 |
14 files changed, 175 insertions, 38 deletions
diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 360918d2af..5d7c9e2a90 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -4634,4 +4634,3 @@ int NoExceptOperatorExpressionAST::lastToken() const return noexcept_token + 1; return 1; } - diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index be73cab1ed..9aa81ccdf6 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -210,6 +210,7 @@ public: virtual DeclarationStatementAST *asDeclarationStatement() { return nullptr; } virtual DeclaratorAST *asDeclarator() { return nullptr; } virtual DeclaratorIdAST *asDeclaratorId() { return nullptr; } + virtual DecompositionDeclaratorAST *asDecompositionDeclarator() { return nullptr; } virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return nullptr; } virtual DeleteExpressionAST *asDeleteExpression() { return nullptr; } virtual DesignatedInitializerAST *asDesignatedInitializer() { return nullptr; } @@ -1277,6 +1278,24 @@ protected: bool match0(AST *, ASTMatcher *) override; }; +class CPLUSPLUS_EXPORT DecompositionDeclaratorAST: public CoreDeclaratorAST +{ +public: + NameListAST *identifiers = nullptr; + +public: + DecompositionDeclaratorAST *asDecompositionDeclarator() override { return this; } + + int firstToken() const override { return identifiers->firstToken(); } + int lastToken() const override { return identifiers->lastToken(); } + + DecompositionDeclaratorAST *clone(MemoryPool *pool) const override; + +protected: + void accept0(ASTVisitor *visitor) override; + bool match0(AST *, ASTMatcher *) override; +}; + class CPLUSPLUS_EXPORT NestedDeclaratorAST: public CoreDeclaratorAST { public: diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 9ca371f3a9..9e5a773bdb 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -1840,3 +1840,11 @@ DesignatedInitializerAST *DesignatedInitializerAST::clone(MemoryPool *pool) cons return ast; } +DecompositionDeclaratorAST *DecompositionDeclaratorAST::clone(MemoryPool *pool) const +{ + const auto theClone = new (pool) DecompositionDeclaratorAST; + for (NameListAST *iter = identifiers, **ast_iter = &theClone->identifiers; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : nullptr); + return theClone; +} diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp index 1a82d29f6e..4105ec3c52 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp @@ -352,6 +352,14 @@ bool DeclaratorIdAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool DecompositionDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (DecompositionDeclaratorAST *_other = pattern->asDecompositionDeclarator()) + return matcher->match(this, _other); + + return false; +} + bool NestedDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher) { if (NestedDeclaratorAST *_other = pattern->asNestedDeclarator()) diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index 321d14a263..fcfe86ab57 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -836,6 +836,15 @@ bool ASTMatcher::match(DeclaratorIdAST *node, DeclaratorIdAST *pattern) return true; } +bool ASTMatcher::match(DecompositionDeclaratorAST *node, DecompositionDeclaratorAST *pattern) +{ + if (!pattern->identifiers) + pattern->identifiers = node->identifiers; + else if (! AST::match(node->identifiers, pattern->identifiers, this)) + return false; + return true; +} + bool ASTMatcher::match(NestedDeclaratorAST *node, NestedDeclaratorAST *pattern) { (void) node; diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h index 47d9ecf5bf..c243e18b7b 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.h +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h @@ -63,6 +63,7 @@ public: virtual bool match(DeclarationStatementAST *node, DeclarationStatementAST *pattern); virtual bool match(DeclaratorAST *node, DeclaratorAST *pattern); virtual bool match(DeclaratorIdAST *node, DeclaratorIdAST *pattern); + virtual bool match(DecompositionDeclaratorAST *node, DecompositionDeclaratorAST *pattern); virtual bool match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern); virtual bool match(DeleteExpressionAST *node, DeleteExpressionAST *pattern); virtual bool match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern); diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h index 9e2a263533..1e23ed6b54 100644 --- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h +++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h @@ -339,6 +339,13 @@ public: return ast; } + DecompositionDeclaratorAST *DecompositionDeclarator(NameListAST *names = nullptr) + { + const auto ast = new (&pool) DecompositionDeclaratorAST; + ast->identifiers = names; + return ast; + } + NestedDeclaratorAST *NestedDeclarator(DeclaratorAST *declarator = nullptr) { NestedDeclaratorAST *ast = new (&pool) NestedDeclaratorAST; diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index b9e954972e..2248f51a50 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -368,6 +368,14 @@ void DeclaratorIdAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void DecompositionDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(identifiers, visitor); + } + visitor->endVisit(this); +} + void NestedDeclaratorAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h index 7f45d4d06d..691b57e9ac 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisitor.h +++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h @@ -105,6 +105,7 @@ public: virtual bool visit(DeclarationStatementAST *) { return true; } virtual bool visit(DeclaratorAST *) { return true; } virtual bool visit(DeclaratorIdAST *) { return true; } + virtual bool visit(DecompositionDeclaratorAST *) { return true; } virtual bool visit(DecltypeSpecifierAST *) { return true; } virtual bool visit(DeleteExpressionAST *) { return true; } virtual bool visit(DesignatedInitializerAST *) { return true; } @@ -258,6 +259,7 @@ public: virtual void endVisit(DeclarationStatementAST *) {} virtual void endVisit(DeclaratorAST *) {} virtual void endVisit(DeclaratorIdAST *) {} + virtual void endVisit(DecompositionDeclaratorAST *) {} virtual void endVisit(DecltypeSpecifierAST *) {} virtual void endVisit(DeleteExpressionAST *) {} virtual void endVisit(DesignatedInitializerAST *) {} diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h index fb6de59abd..4b31aaf590 100644 --- a/src/libs/3rdparty/cplusplus/ASTfwd.h +++ b/src/libs/3rdparty/cplusplus/ASTfwd.h @@ -66,6 +66,7 @@ class DeclarationAST; class DeclarationStatementAST; class DeclaratorAST; class DeclaratorIdAST; +class DecompositionDeclaratorAST; class DecltypeSpecifierAST; class DeleteExpressionAST; class DesignatedInitializerAST; diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 89ea441842..2f3f465c8e 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -35,6 +35,7 @@ #include <string> #include <memory> #include <sstream> +#include <utility> using namespace CPlusPlus; @@ -46,6 +47,7 @@ Bind::Bind(TranslationUnit *unit) _expression(nullptr), _name(nullptr), _declaratorId(nullptr), + _decompositionDeclarator(nullptr), _visibility(Symbol::Public), _objcVisibility(Symbol::Public), _methodKey(Function::NormalMethod), @@ -341,7 +343,9 @@ bool Bind::visit(DeclaratorAST *ast) return false; } -FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId) +FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType &init, + DeclaratorIdAST **declaratorId, + DecompositionDeclaratorAST **decompDeclarator) { FullySpecifiedType type = init; @@ -349,6 +353,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType return type; std::swap(_declaratorId, declaratorId); + std::swap(_decompositionDeclarator, decompDeclarator); bool isAuto = false; const bool cxx11Enabled = translationUnit()->languageFeatures().cxx11Enabled; if (cxx11Enabled) @@ -380,6 +385,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType } std::swap(_declaratorId, declaratorId); + std::swap(_decompositionDeclarator, decompDeclarator); return type; } @@ -1997,51 +2003,65 @@ bool Bind::visit(SimpleDeclarationAST *ast) for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) { DeclaratorIdAST *declaratorId = nullptr; - FullySpecifiedType declTy = this->declarator(it->value, type, &declaratorId); + DecompositionDeclaratorAST *decompDeclarator = nullptr; + FullySpecifiedType declTy = this->declarator(it->value, type, &declaratorId, + &decompDeclarator); - const Name *declName = nullptr; - int sourceLocation = location(it->value, ast->firstToken()); - if (declaratorId && declaratorId->name) - declName = declaratorId->name->name; + std::vector<std::pair<const Name *, int>> namesAndLocations; + if (declaratorId && declaratorId->name) { + namesAndLocations.push_back({declaratorId->name->name, + location(it->value, ast->firstToken())}); + } else if (decompDeclarator) { + for (auto it = decompDeclarator->identifiers->begin(); + it != decompDeclarator->identifiers->end(); ++it) { + if ((*it)->name) + namesAndLocations.push_back({(*it)->name, (*it)->firstToken()}); + } + } - Declaration *decl = control()->newDeclaration(sourceLocation, declName); - decl->setType(declTy); - setDeclSpecifiers(decl, type); + for (const auto &nameAndLoc : qAsConst(namesAndLocations)) { + const int sourceLocation = nameAndLoc.second; + Declaration *decl = control()->newDeclaration(sourceLocation, nameAndLoc.first); + decl->setType(declTy); + setDeclSpecifiers(decl, type); - if (Function *fun = decl->type()->asFunctionType()) { - fun->setEnclosingScope(_scope); - fun->setSourceLocation(sourceLocation, translationUnit()); + if (Function *fun = decl->type()->asFunctionType()) { + fun->setEnclosingScope(_scope); + fun->setSourceLocation(sourceLocation, translationUnit()); - setDeclSpecifiers(fun, type); - if (declaratorId && declaratorId->name) - fun->setName(declaratorId->name->name); // update the function name - } - else if (declTy.isAuto()) { - const ExpressionAST *initializer = it->value->initializer; - if (!initializer && declaratorId) - translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer"); - else if (initializer) - decl->setInitializer(asStringLiteral(initializer)); - } + setDeclSpecifiers(fun, type); + if (declaratorId && declaratorId->name) + fun->setName(declaratorId->name->name); // update the function name + } + else if (declTy.isAuto()) { + const ExpressionAST *initializer = it->value->initializer; + if (!initializer && declaratorId) { + translationUnit()->error(location(declaratorId->name, ast->firstToken()), + "auto-initialized variable must have an initializer"); + } else if (initializer) { + decl->setInitializer(asStringLiteral(initializer)); + } + } - if (_scope->asClass()) { - decl->setVisibility(_visibility); + if (_scope->asClass()) { + decl->setVisibility(_visibility); - if (Function *funTy = decl->type()->asFunctionType()) { - funTy->setMethodKey(methodKey); + if (Function *funTy = decl->type()->asFunctionType()) { + funTy->setMethodKey(methodKey); - bool pureVirtualInit = it->value->equal_token - && it->value->initializer - && it->value->initializer->asNumericLiteral(); - if (funTy->isVirtual() && pureVirtualInit) - funTy->setPureVirtual(true); + bool pureVirtualInit = it->value->equal_token + && it->value->initializer + && it->value->initializer->asNumericLiteral(); + if (funTy->isVirtual() && pureVirtualInit) + funTy->setPureVirtual(true); + } } - } - _scope->addMember(decl); + _scope->addMember(decl); - *symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl); - symbolTail = &(*symbolTail)->next; + *symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl); + symbolTail = &(*symbolTail)->next; + } } return false; } @@ -3319,6 +3339,14 @@ bool Bind::visit(DeclaratorIdAST *ast) return false; } +bool Bind::visit(DecompositionDeclaratorAST *ast) +{ + for (auto it = ast->identifiers->begin(); it != ast->identifiers->end(); ++it) + name(*it); + *_decompositionDeclarator = ast; + return false; +} + bool Bind::visit(NestedDeclaratorAST *ast) { _type = this->declarator(ast->declarator, _type, _declaratorId); diff --git a/src/libs/3rdparty/cplusplus/Bind.h b/src/libs/3rdparty/cplusplus/Bind.h index f009db8b6c..e5ee622881 100644 --- a/src/libs/3rdparty/cplusplus/Bind.h +++ b/src/libs/3rdparty/cplusplus/Bind.h @@ -77,7 +77,9 @@ protected: const Name *objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg); void attribute(GnuAttributeAST *ast); - FullySpecifiedType declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId); + FullySpecifiedType declarator(DeclaratorAST *ast, const FullySpecifiedType &init, + DeclaratorIdAST **declaratorId, + DecompositionDeclaratorAST **decompDeclarator = nullptr); void qtInterfaceName(QtInterfaceNameAST *ast); void baseSpecifier(BaseSpecifierAST *ast, int colon_token, Class *klass); void ctorInitializer(CtorInitializerAST *ast, Function *fun); @@ -275,6 +277,7 @@ protected: // CoreDeclaratorAST bool visit(DeclaratorIdAST *ast) override; + bool visit(DecompositionDeclaratorAST *ast) override; bool visit(NestedDeclaratorAST *ast) override; // PostfixDeclaratorAST @@ -291,6 +294,7 @@ private: const Name *_name; FullySpecifiedType _type; DeclaratorIdAST **_declaratorId; + DecompositionDeclaratorAST **_decompositionDeclarator; int _visibility; int _objcVisibility; int _methodKey; diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 7116f1abf4..9938fa9dde 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -1568,6 +1568,8 @@ bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, Specifier return parseAbstractDeclarator(node, decl_specifier_list); } + + bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *) { DEBUG_THIS_RULE(); @@ -1616,11 +1618,51 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp node = ast; return true; } + } else if (const auto decl = parseDecompositionDeclarator()) { + DeclaratorAST *ast = new (_pool) DeclaratorAST; + ast->attribute_list = attributes; + ast->ptr_operator_list = ptr_operators; + ast->core_declarator = decl; + node = ast; + return true; } rewind(start); return false; } +DecompositionDeclaratorAST *Parser::parseDecompositionDeclarator() +{ + if (LA() != T_LBRACKET) + return nullptr; + consumeToken(); + + const auto decl = new (_pool) DecompositionDeclaratorAST; + for (NameListAST **iter = &decl->identifiers; ; iter = &(*iter)->next) { + NameAST *name_ast = nullptr; + if (!parseName(name_ast)) { + error(cursor(), "expected an identifier"); + return nullptr; + } + *iter = new (_pool) NameListAST; + (*iter)->value = name_ast; + + if (LA() == T_RBRACKET) { + consumeToken(); + return decl; + } + + if (LA() == T_COMMA) { + consumeToken(); + continue; + } + + error(cursor(), "expected ',' or ']'"); + return nullptr; + } + + return nullptr; +} + static bool maybeCppInitializer(DeclaratorAST *declarator) { if (declarator->ptr_operator_list) diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index b8efe2765e..3a3b00fdf6 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -79,6 +79,7 @@ public: bool parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass = nullptr); bool parseDeclarationStatement(StatementAST *&node); bool parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass); + DecompositionDeclaratorAST *parseDecompositionDeclarator(); bool parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass = nullptr); bool parseDeleteExpression(ExpressionAST *&node); bool parseDoStatement(StatementAST *&node); |