diff options
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.h | 2 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTClone.cpp | 4 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.cpp | 10 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisit.cpp | 2 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Bind.cpp | 4 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 27 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Token.h | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/projectpart.cpp | 1 | ||||
-rw-r--r-- | tests/auto/cplusplus/cxx11/tst_cxx11.cpp | 23 |
9 files changed, 68 insertions, 6 deletions
diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index 0f40424464e..6a5da23306a 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -1779,6 +1779,8 @@ public: int if_token = 0; int constexpr_token = 0; int lparen_token = 0; + DeclarationAST *initDecl = nullptr; + StatementAST *initStmt = nullptr; ExpressionAST *condition = nullptr; int rparen_token = 0; StatementAST *statement = nullptr; diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index e494ad71ac6..57617bb1180 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -785,6 +785,10 @@ IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const ast->if_token = if_token; ast->constexpr_token = constexpr_token; ast->lparen_token = lparen_token; + if (initDecl) + ast->initDecl = initDecl->clone(pool); + if (initStmt) + ast->initStmt = initStmt->clone(pool); if (condition) ast->condition = condition->clone(pool); ast->rparen_token = rparen_token; diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index de6f6fc87c0..6f12efb8aca 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -1318,6 +1318,16 @@ bool ASTMatcher::match(IfStatementAST *node, IfStatementAST *pattern) pattern->lparen_token = node->lparen_token; + if (!pattern->initDecl) + pattern->initDecl = node->initDecl; + else if (!AST::match(node->initDecl, pattern->initDecl, this)) + return false; + + if (!pattern->initStmt) + pattern->initStmt = node->initStmt; + else if (!AST::match(node->initStmt, pattern->initStmt, this)) + return false; + if (! pattern->condition) pattern->condition = node->condition; else if (! AST::match(node->condition, pattern->condition, this)) diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index 17941d8122f..7e8f75f2334 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -563,6 +563,8 @@ void ForStatementAST::accept0(ASTVisitor *visitor) void IfStatementAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { + accept(initDecl, visitor); + accept(initStmt, visitor); accept(condition, visitor); accept(statement, visitor); accept(else_statement, visitor); diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 202c36a51fa..e3d38a09a84 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -1528,6 +1528,10 @@ bool Bind::visit(IfStatementAST *ast) ast->symbol = block; Scope *previousScope = switchScope(block); + if (ast->initDecl) + this->declaration(ast->initDecl); + else if (ast->initStmt) + this->statement(ast->initStmt); /*ExpressionTy condition =*/ this->expression(ast->condition); this->statement(ast->statement); this->statement(ast->else_statement); diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index f8c737c0978..31e290d1ad6 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -3511,12 +3511,14 @@ bool Parser::parseExpressionStatement(StatementAST *&node) ExpressionAST *expression = nullptr; if (parseExpression(expression)) { - ExpressionStatementAST *ast = new (previousPool) ExpressionStatementAST; - if (expression) - ast->expression = expression->clone(previousPool); - match(T_SEMICOLON, &ast->semicolon_token); - node = ast; - parsed = true; + if (LA() == T_SEMICOLON) { + ExpressionStatementAST *ast = new (previousPool) ExpressionStatementAST; + ast->semicolon_token = consumeToken(); + if (expression) + ast->expression = expression->clone(previousPool); + node = ast; + parsed = true; + } } _inExpressionStatement = wasInExpressionStatement; @@ -4072,6 +4074,19 @@ bool Parser::parseIfStatement(StatementAST *&node) ast->constexpr_token = consumeToken(); } match(T_LPAREN, &ast->lparen_token); + + // C++17: init-statement + if (_languageFeatures.cxx17Enabled) { + const int savedCursor = cursor(); + const bool savedBlockErrors = _translationUnit->blockErrors(true); + if (!parseSimpleDeclaration(ast->initDecl)) { + rewind(savedCursor); + if (!parseExpressionStatement(ast->initStmt)) + rewind(savedCursor); + } + _translationUnit->blockErrors(savedBlockErrors); + } + parseCondition(ast->condition); match(T_RPAREN, &ast->rparen_token); if (! parseStatement(ast->statement)) diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h index 204096893ad..f853d29c77f 100644 --- a/src/libs/3rdparty/cplusplus/Token.h +++ b/src/libs/3rdparty/cplusplus/Token.h @@ -455,6 +455,7 @@ struct LanguageFeatures unsigned int cxxEnabled : 1; unsigned int cxx11Enabled : 1; unsigned int cxx14Enabled : 1; + unsigned int cxx17Enabled : 1; unsigned int cxx20Enabled : 1; unsigned int objCEnabled : 1; unsigned int c99Enabled : 1; diff --git a/src/plugins/cppeditor/projectpart.cpp b/src/plugins/cppeditor/projectpart.cpp index 9cab9a6df2b..bea37f91ab4 100644 --- a/src/plugins/cppeditor/projectpart.cpp +++ b/src/plugins/cppeditor/projectpart.cpp @@ -163,6 +163,7 @@ CPlusPlus::LanguageFeatures ProjectPart::deriveLanguageFeatures() const CPlusPlus::LanguageFeatures features; features.cxx11Enabled = languageVersion >= Utils::LanguageVersion::CXX11; features.cxx14Enabled = languageVersion >= Utils::LanguageVersion::CXX14; + features.cxx17Enabled = languageVersion >= Utils::LanguageVersion::CXX17; features.cxx20Enabled = languageVersion >= Utils::LanguageVersion::CXX20; features.cxxEnabled = hasCxx; features.c99Enabled = languageVersion >= Utils::LanguageVersion::C99; diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp index 958aa631c68..d27ba601467 100644 --- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp +++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp @@ -150,6 +150,7 @@ private Q_SLOTS: void requiresClause(); void coroutines(); void genericLambdas(); + void ifStatementWithInitialization(); }; @@ -550,5 +551,27 @@ int main() QVERIFY(!hasErrors); } +void tst_cxx11::ifStatementWithInitialization() +{ + LanguageFeatures features; + features.cxxEnabled = true; + features.cxx11Enabled = features.cxx14Enabled = features.cxx17Enabled = true; + + const QString source = R"( +int main() +{ + if (bool b = true; b) + b = false; +} +)"; + QByteArray errors; + Document::Ptr doc = Document::create(FilePath::fromPathPart(u"testFile")); + processDocument(doc, source.toUtf8(), features, &errors); + const bool hasErrors = !errors.isEmpty(); + if (hasErrors) + qDebug().noquote() << errors; + QVERIFY(!hasErrors); +} + QTEST_APPLESS_MAIN(tst_cxx11) #include "tst_cxx11.moc" |