diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2022-08-24 16:23:33 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2022-08-25 08:09:23 +0000 |
commit | fa13f48c2b37f91690ba12e8f1b3162db7c3cb5c (patch) | |
tree | 4f5215123738e46c2f66c32b024db0615da2657b /src/libs/3rdparty/cplusplus | |
parent | 3172bba63c1234497fed360ba52d1c2588fc2132 (diff) |
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>
Diffstat (limited to 'src/libs/3rdparty/cplusplus')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Bind.cpp | 3 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 43 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.h | 4 |
3 files changed, 30 insertions, 20 deletions
diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 2f3f465c8e..64af5b893a 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -3343,7 +3343,8 @@ bool Bind::visit(DecompositionDeclaratorAST *ast) { for (auto it = ast->identifiers->begin(); it != ast->identifiers->end(); ++it) name(*it); - *_decompositionDeclarator = ast; + if (_decompositionDeclarator) + *_decompositionDeclarator = ast; return false; } diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 9938fa9dde..024573b918 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -1618,7 +1618,7 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp node = ast; return true; } - } else if (const auto decl = parseDecompositionDeclarator()) { + } else if (const auto decl = parseDecompositionDeclarator(decl_specifier_list)) { DeclaratorAST *ast = new (_pool) DeclaratorAST; ast->attribute_list = attributes; ast->ptr_operator_list = ptr_operators; @@ -1630,19 +1630,21 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp 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; consumeToken(); const auto decl = new (_pool) DecompositionDeclaratorAST; for (NameListAST **iter = &decl->identifiers; ; iter = &(*iter)->next) { - NameAST *name_ast = nullptr; - if (!parseName(name_ast)) { + if (LA() != T_IDENTIFIER) { error(cursor(), "expected an identifier"); return nullptr; } + SimpleNameAST * const name_ast = new (_pool) SimpleNameAST; + name_ast->identifier_token = consumeToken(); *iter = new (_pool) NameListAST; (*iter)->value = name_ast; @@ -1681,6 +1683,18 @@ static bool maybeCppInitializer(DeclaratorAST *declarator) 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) { DEBUG_THIS_RULE(); @@ -1753,19 +1767,9 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specif parseRefQualifier(ast->ref_qualifier_token); parseExceptionSpecification(ast->exception_specification); - if (_languageFeatures.cxx11Enabled && ! node->ptr_operator_list && LA() == T_ARROW) { - // only allow if there is 1 type spec, which has to be 'auto' - bool hasAuto = false; - 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); + if (_languageFeatures.cxx11Enabled && ! node->ptr_operator_list && LA() == T_ARROW + && hasAuto(decl_specifier_list)) { + parseTrailingReturnType(ast->trailing_return_type); } 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))) { 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; } diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index 3a3b00fdf6..499a854490 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -79,7 +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(); + DecompositionDeclaratorAST *parseDecompositionDeclarator(SpecifierListAST *decl_specifier_list); bool parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, ClassSpecifierAST *declaringClass = nullptr); bool parseDeleteExpression(ExpressionAST *&node); bool parseDoStatement(StatementAST *&node); @@ -317,6 +317,8 @@ public: void clearTemplateArgumentList() { _templateArgumentList.clear(); } private: + bool hasAuto(SpecifierListAST *decl_specifier_list) const; + TranslationUnit *_translationUnit; Control *_control; MemoryPool *_pool; |