aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/cplusplus
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2022-08-17 18:10:53 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2022-08-23 13:52:11 +0000
commitca00b874a75d8cd64f9768d21959a530b928c6dc (patch)
tree8292188e0ac3952854cd653bfa573c1cf94772de /src/libs/3rdparty/cplusplus
parent5fab54d95aadaf28c4f7d10e601cc12feb682429 (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.cpp1
-rw-r--r--src/libs/3rdparty/cplusplus/AST.h19
-rw-r--r--src/libs/3rdparty/cplusplus/ASTClone.cpp8
-rw-r--r--src/libs/3rdparty/cplusplus/ASTMatch0.cpp8
-rw-r--r--src/libs/3rdparty/cplusplus/ASTMatcher.cpp9
-rw-r--r--src/libs/3rdparty/cplusplus/ASTMatcher.h1
-rw-r--r--src/libs/3rdparty/cplusplus/ASTPatternBuilder.h7
-rw-r--r--src/libs/3rdparty/cplusplus/ASTVisit.cpp8
-rw-r--r--src/libs/3rdparty/cplusplus/ASTVisitor.h2
-rw-r--r--src/libs/3rdparty/cplusplus/ASTfwd.h1
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.cpp100
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.h6
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.cpp42
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.h1
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);