forked from qt-creator/qt-creator
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>
This commit is contained in:
1
src/libs/3rdparty/cplusplus/AST.cpp
vendored
1
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -4634,4 +4634,3 @@ int NoExceptOperatorExpressionAST::lastToken() const
|
|||||||
return noexcept_token + 1;
|
return noexcept_token + 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/libs/3rdparty/cplusplus/AST.h
vendored
19
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -210,6 +210,7 @@ public:
|
|||||||
virtual DeclarationStatementAST *asDeclarationStatement() { return nullptr; }
|
virtual DeclarationStatementAST *asDeclarationStatement() { return nullptr; }
|
||||||
virtual DeclaratorAST *asDeclarator() { return nullptr; }
|
virtual DeclaratorAST *asDeclarator() { return nullptr; }
|
||||||
virtual DeclaratorIdAST *asDeclaratorId() { return nullptr; }
|
virtual DeclaratorIdAST *asDeclaratorId() { return nullptr; }
|
||||||
|
virtual DecompositionDeclaratorAST *asDecompositionDeclarator() { return nullptr; }
|
||||||
virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return nullptr; }
|
virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return nullptr; }
|
||||||
virtual DeleteExpressionAST *asDeleteExpression() { return nullptr; }
|
virtual DeleteExpressionAST *asDeleteExpression() { return nullptr; }
|
||||||
virtual DesignatedInitializerAST *asDesignatedInitializer() { return nullptr; }
|
virtual DesignatedInitializerAST *asDesignatedInitializer() { return nullptr; }
|
||||||
@@ -1277,6 +1278,24 @@ protected:
|
|||||||
bool match0(AST *, ASTMatcher *) override;
|
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
|
class CPLUSPLUS_EXPORT NestedDeclaratorAST: public CoreDeclaratorAST
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
8
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -1840,3 +1840,11 @@ DesignatedInitializerAST *DesignatedInitializerAST::clone(MemoryPool *pool) cons
|
|||||||
return ast;
|
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;
|
||||||
|
}
|
||||||
|
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -352,6 +352,14 @@ bool DeclaratorIdAST::match0(AST *pattern, ASTMatcher *matcher)
|
|||||||
return false;
|
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)
|
bool NestedDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||||
{
|
{
|
||||||
if (NestedDeclaratorAST *_other = pattern->asNestedDeclarator())
|
if (NestedDeclaratorAST *_other = pattern->asNestedDeclarator())
|
||||||
|
9
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
9
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -836,6 +836,15 @@ bool ASTMatcher::match(DeclaratorIdAST *node, DeclaratorIdAST *pattern)
|
|||||||
return true;
|
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)
|
bool ASTMatcher::match(NestedDeclaratorAST *node, NestedDeclaratorAST *pattern)
|
||||||
{
|
{
|
||||||
(void) node;
|
(void) node;
|
||||||
|
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -63,6 +63,7 @@ public:
|
|||||||
virtual bool match(DeclarationStatementAST *node, DeclarationStatementAST *pattern);
|
virtual bool match(DeclarationStatementAST *node, DeclarationStatementAST *pattern);
|
||||||
virtual bool match(DeclaratorAST *node, DeclaratorAST *pattern);
|
virtual bool match(DeclaratorAST *node, DeclaratorAST *pattern);
|
||||||
virtual bool match(DeclaratorIdAST *node, DeclaratorIdAST *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(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern);
|
||||||
virtual bool match(DeleteExpressionAST *node, DeleteExpressionAST *pattern);
|
virtual bool match(DeleteExpressionAST *node, DeleteExpressionAST *pattern);
|
||||||
virtual bool match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern);
|
virtual bool match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern);
|
||||||
|
@@ -339,6 +339,13 @@ public:
|
|||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DecompositionDeclaratorAST *DecompositionDeclarator(NameListAST *names = nullptr)
|
||||||
|
{
|
||||||
|
const auto ast = new (&pool) DecompositionDeclaratorAST;
|
||||||
|
ast->identifiers = names;
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
NestedDeclaratorAST *NestedDeclarator(DeclaratorAST *declarator = nullptr)
|
NestedDeclaratorAST *NestedDeclarator(DeclaratorAST *declarator = nullptr)
|
||||||
{
|
{
|
||||||
NestedDeclaratorAST *ast = new (&pool) NestedDeclaratorAST;
|
NestedDeclaratorAST *ast = new (&pool) NestedDeclaratorAST;
|
||||||
|
8
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -368,6 +368,14 @@ void DeclaratorIdAST::accept0(ASTVisitor *visitor)
|
|||||||
visitor->endVisit(this);
|
visitor->endVisit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecompositionDeclaratorAST::accept0(ASTVisitor *visitor)
|
||||||
|
{
|
||||||
|
if (visitor->visit(this)) {
|
||||||
|
accept(identifiers, visitor);
|
||||||
|
}
|
||||||
|
visitor->endVisit(this);
|
||||||
|
}
|
||||||
|
|
||||||
void NestedDeclaratorAST::accept0(ASTVisitor *visitor)
|
void NestedDeclaratorAST::accept0(ASTVisitor *visitor)
|
||||||
{
|
{
|
||||||
if (visitor->visit(this)) {
|
if (visitor->visit(this)) {
|
||||||
|
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -105,6 +105,7 @@ public:
|
|||||||
virtual bool visit(DeclarationStatementAST *) { return true; }
|
virtual bool visit(DeclarationStatementAST *) { return true; }
|
||||||
virtual bool visit(DeclaratorAST *) { return true; }
|
virtual bool visit(DeclaratorAST *) { return true; }
|
||||||
virtual bool visit(DeclaratorIdAST *) { return true; }
|
virtual bool visit(DeclaratorIdAST *) { return true; }
|
||||||
|
virtual bool visit(DecompositionDeclaratorAST *) { return true; }
|
||||||
virtual bool visit(DecltypeSpecifierAST *) { return true; }
|
virtual bool visit(DecltypeSpecifierAST *) { return true; }
|
||||||
virtual bool visit(DeleteExpressionAST *) { return true; }
|
virtual bool visit(DeleteExpressionAST *) { return true; }
|
||||||
virtual bool visit(DesignatedInitializerAST *) { return true; }
|
virtual bool visit(DesignatedInitializerAST *) { return true; }
|
||||||
@@ -258,6 +259,7 @@ public:
|
|||||||
virtual void endVisit(DeclarationStatementAST *) {}
|
virtual void endVisit(DeclarationStatementAST *) {}
|
||||||
virtual void endVisit(DeclaratorAST *) {}
|
virtual void endVisit(DeclaratorAST *) {}
|
||||||
virtual void endVisit(DeclaratorIdAST *) {}
|
virtual void endVisit(DeclaratorIdAST *) {}
|
||||||
|
virtual void endVisit(DecompositionDeclaratorAST *) {}
|
||||||
virtual void endVisit(DecltypeSpecifierAST *) {}
|
virtual void endVisit(DecltypeSpecifierAST *) {}
|
||||||
virtual void endVisit(DeleteExpressionAST *) {}
|
virtual void endVisit(DeleteExpressionAST *) {}
|
||||||
virtual void endVisit(DesignatedInitializerAST *) {}
|
virtual void endVisit(DesignatedInitializerAST *) {}
|
||||||
|
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -66,6 +66,7 @@ class DeclarationAST;
|
|||||||
class DeclarationStatementAST;
|
class DeclarationStatementAST;
|
||||||
class DeclaratorAST;
|
class DeclaratorAST;
|
||||||
class DeclaratorIdAST;
|
class DeclaratorIdAST;
|
||||||
|
class DecompositionDeclaratorAST;
|
||||||
class DecltypeSpecifierAST;
|
class DecltypeSpecifierAST;
|
||||||
class DeleteExpressionAST;
|
class DeleteExpressionAST;
|
||||||
class DesignatedInitializerAST;
|
class DesignatedInitializerAST;
|
||||||
|
48
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
48
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -35,6 +35,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ Bind::Bind(TranslationUnit *unit)
|
|||||||
_expression(nullptr),
|
_expression(nullptr),
|
||||||
_name(nullptr),
|
_name(nullptr),
|
||||||
_declaratorId(nullptr),
|
_declaratorId(nullptr),
|
||||||
|
_decompositionDeclarator(nullptr),
|
||||||
_visibility(Symbol::Public),
|
_visibility(Symbol::Public),
|
||||||
_objcVisibility(Symbol::Public),
|
_objcVisibility(Symbol::Public),
|
||||||
_methodKey(Function::NormalMethod),
|
_methodKey(Function::NormalMethod),
|
||||||
@@ -341,7 +343,9 @@ bool Bind::visit(DeclaratorAST *ast)
|
|||||||
return false;
|
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;
|
FullySpecifiedType type = init;
|
||||||
|
|
||||||
@@ -349,6 +353,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType
|
|||||||
return type;
|
return type;
|
||||||
|
|
||||||
std::swap(_declaratorId, declaratorId);
|
std::swap(_declaratorId, declaratorId);
|
||||||
|
std::swap(_decompositionDeclarator, decompDeclarator);
|
||||||
bool isAuto = false;
|
bool isAuto = false;
|
||||||
const bool cxx11Enabled = translationUnit()->languageFeatures().cxx11Enabled;
|
const bool cxx11Enabled = translationUnit()->languageFeatures().cxx11Enabled;
|
||||||
if (cxx11Enabled)
|
if (cxx11Enabled)
|
||||||
@@ -380,6 +385,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::swap(_declaratorId, declaratorId);
|
std::swap(_declaratorId, declaratorId);
|
||||||
|
std::swap(_decompositionDeclarator, decompDeclarator);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1997,14 +2003,25 @@ bool Bind::visit(SimpleDeclarationAST *ast)
|
|||||||
|
|
||||||
for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) {
|
for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) {
|
||||||
DeclaratorIdAST *declaratorId = nullptr;
|
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;
|
std::vector<std::pair<const Name *, int>> namesAndLocations;
|
||||||
int sourceLocation = location(it->value, ast->firstToken());
|
if (declaratorId && declaratorId->name) {
|
||||||
if (declaratorId && declaratorId->name)
|
namesAndLocations.push_back({declaratorId->name->name,
|
||||||
declName = 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);
|
for (const auto &nameAndLoc : qAsConst(namesAndLocations)) {
|
||||||
|
const int sourceLocation = nameAndLoc.second;
|
||||||
|
Declaration *decl = control()->newDeclaration(sourceLocation, nameAndLoc.first);
|
||||||
decl->setType(declTy);
|
decl->setType(declTy);
|
||||||
setDeclSpecifiers(decl, type);
|
setDeclSpecifiers(decl, type);
|
||||||
|
|
||||||
@@ -2018,11 +2035,13 @@ bool Bind::visit(SimpleDeclarationAST *ast)
|
|||||||
}
|
}
|
||||||
else if (declTy.isAuto()) {
|
else if (declTy.isAuto()) {
|
||||||
const ExpressionAST *initializer = it->value->initializer;
|
const ExpressionAST *initializer = it->value->initializer;
|
||||||
if (!initializer && declaratorId)
|
if (!initializer && declaratorId) {
|
||||||
translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer");
|
translationUnit()->error(location(declaratorId->name, ast->firstToken()),
|
||||||
else if (initializer)
|
"auto-initialized variable must have an initializer");
|
||||||
|
} else if (initializer) {
|
||||||
decl->setInitializer(asStringLiteral(initializer));
|
decl->setInitializer(asStringLiteral(initializer));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_scope->asClass()) {
|
if (_scope->asClass()) {
|
||||||
decl->setVisibility(_visibility);
|
decl->setVisibility(_visibility);
|
||||||
@@ -2043,6 +2062,7 @@ bool Bind::visit(SimpleDeclarationAST *ast)
|
|||||||
*symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl);
|
*symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl);
|
||||||
symbolTail = &(*symbolTail)->next;
|
symbolTail = &(*symbolTail)->next;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3319,6 +3339,14 @@ bool Bind::visit(DeclaratorIdAST *ast)
|
|||||||
return false;
|
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)
|
bool Bind::visit(NestedDeclaratorAST *ast)
|
||||||
{
|
{
|
||||||
_type = this->declarator(ast->declarator, _type, _declaratorId);
|
_type = this->declarator(ast->declarator, _type, _declaratorId);
|
||||||
|
6
src/libs/3rdparty/cplusplus/Bind.h
vendored
6
src/libs/3rdparty/cplusplus/Bind.h
vendored
@@ -77,7 +77,9 @@ protected:
|
|||||||
|
|
||||||
const Name *objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg);
|
const Name *objCSelectorArgument(ObjCSelectorArgumentAST *ast, bool *hasArg);
|
||||||
void attribute(GnuAttributeAST *ast);
|
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 qtInterfaceName(QtInterfaceNameAST *ast);
|
||||||
void baseSpecifier(BaseSpecifierAST *ast, int colon_token, Class *klass);
|
void baseSpecifier(BaseSpecifierAST *ast, int colon_token, Class *klass);
|
||||||
void ctorInitializer(CtorInitializerAST *ast, Function *fun);
|
void ctorInitializer(CtorInitializerAST *ast, Function *fun);
|
||||||
@@ -275,6 +277,7 @@ protected:
|
|||||||
|
|
||||||
// CoreDeclaratorAST
|
// CoreDeclaratorAST
|
||||||
bool visit(DeclaratorIdAST *ast) override;
|
bool visit(DeclaratorIdAST *ast) override;
|
||||||
|
bool visit(DecompositionDeclaratorAST *ast) override;
|
||||||
bool visit(NestedDeclaratorAST *ast) override;
|
bool visit(NestedDeclaratorAST *ast) override;
|
||||||
|
|
||||||
// PostfixDeclaratorAST
|
// PostfixDeclaratorAST
|
||||||
@@ -291,6 +294,7 @@ private:
|
|||||||
const Name *_name;
|
const Name *_name;
|
||||||
FullySpecifiedType _type;
|
FullySpecifiedType _type;
|
||||||
DeclaratorIdAST **_declaratorId;
|
DeclaratorIdAST **_declaratorId;
|
||||||
|
DecompositionDeclaratorAST **_decompositionDeclarator;
|
||||||
int _visibility;
|
int _visibility;
|
||||||
int _objcVisibility;
|
int _objcVisibility;
|
||||||
int _methodKey;
|
int _methodKey;
|
||||||
|
42
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
42
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -1568,6 +1568,8 @@ bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, Specifier
|
|||||||
return parseAbstractDeclarator(node, decl_specifier_list);
|
return parseAbstractDeclarator(node, decl_specifier_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *)
|
bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *)
|
||||||
{
|
{
|
||||||
DEBUG_THIS_RULE();
|
DEBUG_THIS_RULE();
|
||||||
@@ -1616,11 +1618,51 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp
|
|||||||
node = ast;
|
node = ast;
|
||||||
return true;
|
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);
|
rewind(start);
|
||||||
return false;
|
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)
|
static bool maybeCppInitializer(DeclaratorAST *declarator)
|
||||||
{
|
{
|
||||||
if (declarator->ptr_operator_list)
|
if (declarator->ptr_operator_list)
|
||||||
|
1
src/libs/3rdparty/cplusplus/Parser.h
vendored
1
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -79,6 +79,7 @@ public:
|
|||||||
bool parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass = nullptr);
|
bool parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass = nullptr);
|
||||||
bool parseDeclarationStatement(StatementAST *&node);
|
bool parseDeclarationStatement(StatementAST *&node);
|
||||||
bool parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass);
|
bool parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass);
|
||||||
|
DecompositionDeclaratorAST *parseDecompositionDeclarator();
|
||||||
bool parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass = nullptr);
|
bool parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass = nullptr);
|
||||||
bool parseDeleteExpression(ExpressionAST *&node);
|
bool parseDeleteExpression(ExpressionAST *&node);
|
||||||
bool parseDoStatement(StatementAST *&node);
|
bool parseDoStatement(StatementAST *&node);
|
||||||
|
@@ -2494,6 +2494,13 @@ bool FindUsages::visit(DeclaratorIdAST *ast)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FindUsages::visit(DecompositionDeclaratorAST *ast)
|
||||||
|
{
|
||||||
|
for (auto it = ast->identifiers->begin(); it != ast->identifiers->end(); ++it)
|
||||||
|
name(*it);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool FindUsages::visit(NestedDeclaratorAST *ast)
|
bool FindUsages::visit(NestedDeclaratorAST *ast)
|
||||||
{
|
{
|
||||||
// unsigned lparen_token = ast->lparen_token;
|
// unsigned lparen_token = ast->lparen_token;
|
||||||
|
@@ -282,6 +282,7 @@ protected:
|
|||||||
|
|
||||||
// CoreDeclaratorAST
|
// CoreDeclaratorAST
|
||||||
virtual bool visit(DeclaratorIdAST *ast);
|
virtual bool visit(DeclaratorIdAST *ast);
|
||||||
|
virtual bool visit(DecompositionDeclaratorAST *ast);
|
||||||
virtual bool visit(NestedDeclaratorAST *ast);
|
virtual bool visit(NestedDeclaratorAST *ast);
|
||||||
|
|
||||||
// PostfixDeclaratorAST
|
// PostfixDeclaratorAST
|
||||||
|
@@ -83,6 +83,7 @@ private Q_SLOTS:
|
|||||||
void shadowedNames_1();
|
void shadowedNames_1();
|
||||||
void shadowedNames_2();
|
void shadowedNames_2();
|
||||||
void staticVariables();
|
void staticVariables();
|
||||||
|
void structuredBinding();
|
||||||
|
|
||||||
void functionNameFoundInArguments();
|
void functionNameFoundInArguments();
|
||||||
void memberFunctionFalsePositives_QTCREATORBUG2176();
|
void memberFunctionFalsePositives_QTCREATORBUG2176();
|
||||||
@@ -374,6 +375,42 @@ void tst_FindUsages::staticVariables()
|
|||||||
QCOMPARE(findUsages.usages().at(4).type, Usage::Type::Write);
|
QCOMPARE(findUsages.usages().at(4).type, Usage::Type::Write);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::structuredBinding()
|
||||||
|
{
|
||||||
|
const QByteArray src = "\n"
|
||||||
|
"int array[] = {1, 2};\n"
|
||||||
|
"const auto &[e1, e2] = array;\n"
|
||||||
|
"const int i1 = e1;\n"
|
||||||
|
"const int i2 = e2;\n"
|
||||||
|
;
|
||||||
|
Document::Ptr doc = Document::create("structuredBinding");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QCOMPARE(doc->globalSymbolCount(), 5);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Declaration * const d1 = doc->globalSymbolAt(1)->asDeclaration();
|
||||||
|
QVERIFY(d1);
|
||||||
|
Declaration * const d2 = doc->globalSymbolAt(2)->asDeclaration();
|
||||||
|
QVERIFY(d2);
|
||||||
|
|
||||||
|
FindUsages findUsages(src, doc, snapshot, true);
|
||||||
|
findUsages(d1);
|
||||||
|
QCOMPARE(findUsages.usages().size(), 2);
|
||||||
|
QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Initialization);
|
||||||
|
QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read);
|
||||||
|
|
||||||
|
findUsages(d2);
|
||||||
|
QCOMPARE(findUsages.usages().size(), 2);
|
||||||
|
QCOMPARE(findUsages.usages().at(0).type, Usage::Type::Initialization);
|
||||||
|
QCOMPARE(findUsages.usages().at(1).type, Usage::Type::Read);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_FindUsages::functionNameFoundInArguments()
|
void tst_FindUsages::functionNameFoundInArguments()
|
||||||
{
|
{
|
||||||
const QByteArray src =
|
const QByteArray src =
|
||||||
|
Reference in New Issue
Block a user