forked from qt-creator/qt-creator
CPlusPlus: Fix mis-parsing array-related constructs
... as structured bindings.
Also add a safety check to Bind that might be needed for invalid code.
Amends ca00b874a7
.
Change-Id: I7b174b80ad97ed7424f1e369b876c99acf7e95d2
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
3
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
3
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -3343,7 +3343,8 @@ bool Bind::visit(DecompositionDeclaratorAST *ast)
|
|||||||
{
|
{
|
||||||
for (auto it = ast->identifiers->begin(); it != ast->identifiers->end(); ++it)
|
for (auto it = ast->identifiers->begin(); it != ast->identifiers->end(); ++it)
|
||||||
name(*it);
|
name(*it);
|
||||||
*_decompositionDeclarator = ast;
|
if (_decompositionDeclarator)
|
||||||
|
*_decompositionDeclarator = ast;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
43
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -1618,7 +1618,7 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp
|
|||||||
node = ast;
|
node = ast;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (const auto decl = parseDecompositionDeclarator()) {
|
} else if (const auto decl = parseDecompositionDeclarator(decl_specifier_list)) {
|
||||||
DeclaratorAST *ast = new (_pool) DeclaratorAST;
|
DeclaratorAST *ast = new (_pool) DeclaratorAST;
|
||||||
ast->attribute_list = attributes;
|
ast->attribute_list = attributes;
|
||||||
ast->ptr_operator_list = ptr_operators;
|
ast->ptr_operator_list = ptr_operators;
|
||||||
@@ -1630,19 +1630,21 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecompositionDeclaratorAST *Parser::parseDecompositionDeclarator()
|
DecompositionDeclaratorAST *Parser::parseDecompositionDeclarator(
|
||||||
|
SpecifierListAST *decl_specifier_list)
|
||||||
{
|
{
|
||||||
if (LA() != T_LBRACKET)
|
if (!_languageFeatures.cxx11Enabled || LA() != T_LBRACKET || !hasAuto(decl_specifier_list))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
consumeToken();
|
consumeToken();
|
||||||
|
|
||||||
const auto decl = new (_pool) DecompositionDeclaratorAST;
|
const auto decl = new (_pool) DecompositionDeclaratorAST;
|
||||||
for (NameListAST **iter = &decl->identifiers; ; iter = &(*iter)->next) {
|
for (NameListAST **iter = &decl->identifiers; ; iter = &(*iter)->next) {
|
||||||
NameAST *name_ast = nullptr;
|
if (LA() != T_IDENTIFIER) {
|
||||||
if (!parseName(name_ast)) {
|
|
||||||
error(cursor(), "expected an identifier");
|
error(cursor(), "expected an identifier");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
SimpleNameAST * const name_ast = new (_pool) SimpleNameAST;
|
||||||
|
name_ast->identifier_token = consumeToken();
|
||||||
*iter = new (_pool) NameListAST;
|
*iter = new (_pool) NameListAST;
|
||||||
(*iter)->value = name_ast;
|
(*iter)->value = name_ast;
|
||||||
|
|
||||||
@@ -1681,6 +1683,18 @@ static bool maybeCppInitializer(DeclaratorAST *declarator)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::hasAuto(SpecifierListAST *decl_specifier_list) const
|
||||||
|
{
|
||||||
|
for (SpecifierListAST *iter = decl_specifier_list; iter; iter = iter->next) {
|
||||||
|
SpecifierAST *spec = iter->value;
|
||||||
|
if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) {
|
||||||
|
if (_translationUnit->tokenKind(simpleSpec->specifier_token) == T_AUTO)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass)
|
bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass)
|
||||||
{
|
{
|
||||||
DEBUG_THIS_RULE();
|
DEBUG_THIS_RULE();
|
||||||
@@ -1753,19 +1767,9 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specif
|
|||||||
parseRefQualifier(ast->ref_qualifier_token);
|
parseRefQualifier(ast->ref_qualifier_token);
|
||||||
parseExceptionSpecification(ast->exception_specification);
|
parseExceptionSpecification(ast->exception_specification);
|
||||||
|
|
||||||
if (_languageFeatures.cxx11Enabled && ! node->ptr_operator_list && LA() == T_ARROW) {
|
if (_languageFeatures.cxx11Enabled && ! node->ptr_operator_list && LA() == T_ARROW
|
||||||
// only allow if there is 1 type spec, which has to be 'auto'
|
&& hasAuto(decl_specifier_list)) {
|
||||||
bool hasAuto = false;
|
parseTrailingReturnType(ast->trailing_return_type);
|
||||||
for (SpecifierListAST *iter = decl_specifier_list; !hasAuto && iter; iter = iter->next) {
|
|
||||||
SpecifierAST *spec = iter->value;
|
|
||||||
if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) {
|
|
||||||
if (_translationUnit->tokenKind(simpleSpec->specifier_token) == T_AUTO)
|
|
||||||
hasAuto = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasAuto)
|
|
||||||
parseTrailingReturnType(ast->trailing_return_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parseOverrideFinalQualifiers(ast->cv_qualifier_list);
|
parseOverrideFinalQualifiers(ast->cv_qualifier_list);
|
||||||
@@ -2809,6 +2813,9 @@ bool Parser::parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp
|
|||||||
}
|
}
|
||||||
} else if (node->core_declarator && (LA() == T_EQUAL || (_languageFeatures.cxx11Enabled && !isFunctionDeclarator && LA() == T_LBRACE) || (! declaringClass && LA() == T_LPAREN))) {
|
} else if (node->core_declarator && (LA() == T_EQUAL || (_languageFeatures.cxx11Enabled && !isFunctionDeclarator && LA() == T_LBRACE) || (! declaringClass && LA() == T_LPAREN))) {
|
||||||
parseInitializer(node->initializer, &node->equal_token);
|
parseInitializer(node->initializer, &node->equal_token);
|
||||||
|
} else if (node->core_declarator && node->core_declarator->asDecompositionDeclarator()) {
|
||||||
|
error(cursor(), "structured binding needs initializer");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
4
src/libs/3rdparty/cplusplus/Parser.h
vendored
4
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -79,7 +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();
|
DecompositionDeclaratorAST *parseDecompositionDeclarator(SpecifierListAST *decl_specifier_list);
|
||||||
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);
|
||||||
@@ -317,6 +317,8 @@ public:
|
|||||||
void clearTemplateArgumentList() { _templateArgumentList.clear(); }
|
void clearTemplateArgumentList() { _templateArgumentList.clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool hasAuto(SpecifierListAST *decl_specifier_list) const;
|
||||||
|
|
||||||
TranslationUnit *_translationUnit;
|
TranslationUnit *_translationUnit;
|
||||||
Control *_control;
|
Control *_control;
|
||||||
MemoryPool *_pool;
|
MemoryPool *_pool;
|
||||||
|
Reference in New Issue
Block a user