aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/3rdparty/cplusplus/AST.h2
-rw-r--r--src/libs/3rdparty/cplusplus/ASTClone.cpp4
-rw-r--r--src/libs/3rdparty/cplusplus/ASTMatcher.cpp10
-rw-r--r--src/libs/3rdparty/cplusplus/ASTVisit.cpp2
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.cpp4
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.cpp27
-rw-r--r--src/libs/3rdparty/cplusplus/Token.h1
-rw-r--r--src/plugins/cppeditor/projectpart.cpp1
-rw-r--r--tests/auto/cplusplus/cxx11/tst_cxx11.cpp23
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"