From cf97819682efe4d91588a4440110573b6c2f427e Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 14:52:28 +0100 Subject: [PATCH 01/12] Fix FP initalizerList --- lib/checkclass.cpp | 6 ------ test/testclass.cpp | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index ec3a9521b10..5d6ea385326 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2669,12 +2669,6 @@ void CheckClass::initializerListOrder() if (var) vars.emplace_back(var, tok); - if (Token::Match(tok->tokAt(2), "%name% =")) { - var = scope->getVariable(tok->strAt(2)); - - if (var) - vars.emplace_back(var, tok->tokAt(2)); - } tok = tok->next()->link()->next(); } else tok = tok->next(); diff --git a/test/testclass.cpp b/test/testclass.cpp index 52818894722..3372d70de27 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -7571,6 +7571,12 @@ class TestClass : public TestFixture { "};"); ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::b' is in the wrong place in the initializer list.\n" "[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Member variable 'Fred::a' is in the wrong place in the initializer list.\n", errout.str()); + + checkInitializerListOrder("struct S {\n" + " S() : b(a = 1) {}\n" + " int a, b;\n" + "};"); + ASSERT_EQUALS("", errout.str()); } #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__) From da2cdcd44817103cab432ffeffcecb1003aedb41 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 15:10:30 +0100 Subject: [PATCH 02/12] Fix #12322 detect usage of partially-initialized object in constructor (i.e. wrong init order) --- lib/checkclass.cpp | 49 +++++++++++++++++++++++++++++++--------------- lib/checkclass.h | 2 +- test/testclass.cpp | 13 ++++++++++++ 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 5d6ea385326..d83b677160e 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2628,11 +2628,12 @@ void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const st namespace { // avoid one-definition-rule violation struct VarInfo { - VarInfo(const Variable *_var, const Token *_tok) + VarInfo(const Variable* _var, const Token* _tok) : var(_var), tok(_tok) {} - const Variable *var; - const Token *tok; + const Variable* var; + const Token* tok; + std::vector> initArgs; }; } @@ -2650,13 +2651,13 @@ void CheckClass::initializerListOrder() logChecker("CheckClass::initializerListOrder"); // style,inconclusive - for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { + for (const Scope* scope : mSymbolDatabase->classAndStructScopes) { // iterate through all member functions looking for constructors for (std::list::const_iterator func = scope->functionList.cbegin(); func != scope->functionList.cend(); ++func) { if (func->isConstructor() && func->hasBody()) { // check for initializer list - const Token *tok = func->arg->link()->next(); + const Token* tok = func->arg->link()->next(); if (tok->str() == ":") { std::vector vars; @@ -2665,20 +2666,33 @@ void CheckClass::initializerListOrder() // find all variable initializations in list while (tok && tok != func->functionScope->bodyStart) { if (Token::Match(tok, "%name% (|{")) { - const Variable *var = scope->getVariable(tok->str()); + const Variable* var = scope->getVariable(tok->str()); if (var) vars.emplace_back(var, tok); - tok = tok->next()->link()->next(); - } else + const Token* const end = tok->next()->link(); + for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { + if (auto var2 = tok2->variable()) + vars.back().initArgs.emplace_back(var2, tok2); + } + tok = end->next(); + } + else tok = tok->next(); } - // need at least 2 members to have out of order initialization - for (int j = 1; j < vars.size(); j++) { + for (int j = 0; j < vars.size(); j++) { + // check for use of uninitialized arguments + for (const auto& arg : vars[j].initArgs) + if (vars[j].var->index() < arg.first->index()) + initializerListError(vars[j].tok, vars[j].var->nameToken(), scope->className, vars[j].var->name(), /*isArgument*/ true); + + // need at least 2 members to have out of order initialization + if (j == 0) + continue; // check for out of order initialization if (vars[j].var->index() < vars[j - 1].var->index()) - initializerListError(vars[j].tok,vars[j].var->nameToken(), scope->className, vars[j].var->name()); + initializerListError(vars[j].tok, vars[j].var->nameToken(), scope->className, vars[j].var->name()); } } } @@ -2686,15 +2700,18 @@ void CheckClass::initializerListOrder() } } -void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname) +void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname, bool isArgument) { std::list toks = { tok1, tok2 }; + const std::string msg = isArgument ? + "Member variable '$symbol' uses an uninitialized argument due to the order of declarations." : + "Member variable '$symbol' is in the wrong place in the initializer list."; reportError(toks, Severity::style, "initializerList", - "$symbol:" + classname + "::" + varname +"\n" - "Member variable '$symbol' is in the wrong place in the initializer list.\n" - "Member variable '$symbol' is in the wrong place in the initializer list. " + "$symbol:" + classname + "::" + varname + '\n' + + msg + '\n' + + msg + ' ' + "Members are initialized in the order they are declared, not in the " - "order they are in the initializer list. Keeping the initializer list " + "order they are in the initializer list. Keeping the initializer list " "in the same order that the members were declared prevents order dependent " "initialization errors.", CWE398, Certainty::inconclusive); } diff --git a/lib/checkclass.h b/lib/checkclass.h index bac9f6dd1d5..79258491b90 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -199,7 +199,7 @@ class CPPCHECKLIB CheckClass : public Check { void operatorEqToSelfError(const Token *tok); void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic); void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic); - void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname); + void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname, bool isArgument = false); void suggestInitializationList(const Token *tok, const std::string& varname); void selfInitializationError(const Token* tok, const std::string& varname); void pureVirtualFunctionCallInConstructorError(const Function * scopeFunction, const std::list & tokStack, const std::string &purefuncname); diff --git a/test/testclass.cpp b/test/testclass.cpp index 3372d70de27..efe3b206689 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -215,6 +215,7 @@ class TestClass : public TestFixture { TEST_CASE(qualifiedNameMember); // #10872 TEST_CASE(initializerListOrder); + TEST_CASE(initializerListArgument); TEST_CASE(initializerListUsage); TEST_CASE(selfInitialization); @@ -7579,6 +7580,18 @@ class TestClass : public TestFixture { ASSERT_EQUALS("", errout.str()); } + void initializerListArgument() { + checkInitializerListOrder("struct A { A(); };\n" // #12322 + "struct B { explicit B(const A* a); };\n" + "struct C {\n" + " C() : b(&a) {}\n" + " B b;\n" + " const A a;\n" + "};"); + ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style, inconclusive) Member variable 'C::b' uses an uninitialized argument due to the order of declarations.\n", + errout.str()); + } + #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__) void checkInitializationListUsage_(const char code[], const char* file, int line) { // Clear the error log From 5f10624fd41aadbca1e6f1ab45124209acf70ec0 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 15:14:31 +0100 Subject: [PATCH 03/12] Format --- lib/checkclass.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index d83b677160e..70a50a389ca 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2628,11 +2628,11 @@ void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const st namespace { // avoid one-definition-rule violation struct VarInfo { - VarInfo(const Variable* _var, const Token* _tok) + VarInfo(const Variable *_var, const Token *_tok) : var(_var), tok(_tok) {} - const Variable* var; - const Token* tok; + const Variable *var; + const Token *tok; std::vector> initArgs; }; } @@ -2651,13 +2651,13 @@ void CheckClass::initializerListOrder() logChecker("CheckClass::initializerListOrder"); // style,inconclusive - for (const Scope* scope : mSymbolDatabase->classAndStructScopes) { + for (const Scope *scope : mSymbolDatabase->classAndStructScopes) { // iterate through all member functions looking for constructors for (std::list::const_iterator func = scope->functionList.cbegin(); func != scope->functionList.cend(); ++func) { if (func->isConstructor() && func->hasBody()) { // check for initializer list - const Token* tok = func->arg->link()->next(); + const Token *tok = func->arg->link()->next(); if (tok->str() == ":") { std::vector vars; @@ -2666,7 +2666,7 @@ void CheckClass::initializerListOrder() // find all variable initializations in list while (tok && tok != func->functionScope->bodyStart) { if (Token::Match(tok, "%name% (|{")) { - const Variable* var = scope->getVariable(tok->str()); + const Variable *var = scope->getVariable(tok->str()); if (var) vars.emplace_back(var, tok); @@ -2676,8 +2676,7 @@ void CheckClass::initializerListOrder() vars.back().initArgs.emplace_back(var2, tok2); } tok = end->next(); - } - else + } else tok = tok->next(); } @@ -2692,7 +2691,7 @@ void CheckClass::initializerListOrder() continue; // check for out of order initialization if (vars[j].var->index() < vars[j - 1].var->index()) - initializerListError(vars[j].tok, vars[j].var->nameToken(), scope->className, vars[j].var->name()); + initializerListError(vars[j].tok,vars[j].var->nameToken(), scope->className, vars[j].var->name()); } } } From 5423cf71598103de87bc660e265ab1dc57bc9c07 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 15:17:06 +0100 Subject: [PATCH 04/12] Format --- lib/checkclass.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 70a50a389ca..8d276585787 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2651,7 +2651,7 @@ void CheckClass::initializerListOrder() logChecker("CheckClass::initializerListOrder"); // style,inconclusive - for (const Scope *scope : mSymbolDatabase->classAndStructScopes) { + for (const Scope * scope : mSymbolDatabase->classAndStructScopes) { // iterate through all member functions looking for constructors for (std::list::const_iterator func = scope->functionList.cbegin(); func != scope->functionList.cend(); ++func) { @@ -2703,8 +2703,8 @@ void CheckClass::initializerListError(const Token *tok1, const Token *tok2, cons { std::list toks = { tok1, tok2 }; const std::string msg = isArgument ? - "Member variable '$symbol' uses an uninitialized argument due to the order of declarations." : - "Member variable '$symbol' is in the wrong place in the initializer list."; + "Member variable '$symbol' uses an uninitialized argument due to the order of declarations." : + "Member variable '$symbol' is in the wrong place in the initializer list."; reportError(toks, Severity::style, "initializerList", "$symbol:" + classname + "::" + varname + '\n' + msg + '\n' + From 453dcee945041c5c91a6ebed3d24f92e29ccb5b6 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 15:27:45 +0100 Subject: [PATCH 05/12] Fix --- lib/checkclass.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 8d276585787..d64a7cc17d4 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2633,7 +2633,7 @@ namespace { // avoid one-definition-rule violation const Variable *var; const Token *tok; - std::vector> initArgs; + std::vector initArgs; }; } @@ -2669,11 +2669,13 @@ void CheckClass::initializerListOrder() const Variable *var = scope->getVariable(tok->str()); if (var) vars.emplace_back(var, tok); + else + continue; const Token* const end = tok->next()->link(); for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { if (auto var2 = tok2->variable()) - vars.back().initArgs.emplace_back(var2, tok2); + vars.back().initArgs.emplace_back(var2); } tok = end->next(); } else @@ -2683,7 +2685,7 @@ void CheckClass::initializerListOrder() for (int j = 0; j < vars.size(); j++) { // check for use of uninitialized arguments for (const auto& arg : vars[j].initArgs) - if (vars[j].var->index() < arg.first->index()) + if (vars[j].var->index() < arg->index()) initializerListError(vars[j].tok, vars[j].var->nameToken(), scope->className, vars[j].var->name(), /*isArgument*/ true); // need at least 2 members to have out of order initialization From af29efbb05f3f4d588623b5f6ea3b64fb48db000 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 15:30:54 +0100 Subject: [PATCH 06/12] Fix loop --- lib/checkclass.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index d64a7cc17d4..d1519d47d18 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2664,7 +2664,7 @@ void CheckClass::initializerListOrder() tok = tok->next(); // find all variable initializations in list - while (tok && tok != func->functionScope->bodyStart) { + for (; tok && tok != func->functionScope->bodyStart; tok = tok->next()) { if (Token::Match(tok, "%name% (|{")) { const Variable *var = scope->getVariable(tok->str()); if (var) @@ -2677,9 +2677,8 @@ void CheckClass::initializerListOrder() if (auto var2 = tok2->variable()) vars.back().initArgs.emplace_back(var2); } - tok = end->next(); - } else - tok = tok->next(); + tok = end; + } } for (int j = 0; j < vars.size(); j++) { From a2c99bcc4a5ee917c3f4605f99f2acbd2d471898 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 15:47:43 +0100 Subject: [PATCH 07/12] clang-tidy --- lib/checkclass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index d1519d47d18..1ad6cfb4aed 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2674,7 +2674,7 @@ void CheckClass::initializerListOrder() const Token* const end = tok->next()->link(); for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { - if (auto var2 = tok2->variable()) + if (const Variable* var2 = tok2->variable()) vars.back().initArgs.emplace_back(var2); } tok = end; From 9cd89c76dcf34979004a5f98aab5a8fcc8dd9583 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 16:09:28 +0100 Subject: [PATCH 08/12] Fix FP --- lib/checkclass.cpp | 2 +- test/testclass.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 1ad6cfb4aed..7f5e7e289d5 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2674,7 +2674,7 @@ void CheckClass::initializerListOrder() const Token* const end = tok->next()->link(); for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { - if (const Variable* var2 = tok2->variable()) + if (const Variable* var2 = scope->getVariable(tok2->str())) vars.back().initArgs.emplace_back(var2); } tok = end; diff --git a/test/testclass.cpp b/test/testclass.cpp index efe3b206689..e13e7c40aeb 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -7590,6 +7590,12 @@ class TestClass : public TestFixture { "};"); ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (style, inconclusive) Member variable 'C::b' uses an uninitialized argument due to the order of declarations.\n", errout.str()); + + checkInitializerListOrder("struct S {\n" + " S(const std::string& f, std::string i, int b, int c) : a(0), b(b), c(c) {}\n" + " int a, b, c;\n" + "};"); + ASSERT_EQUALS("", errout.str()); } #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__) From e62c28200841da3b2d49effc8e17f3d5bd3ec01e Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 6 Jan 2024 18:27:47 +0100 Subject: [PATCH 09/12] Fix FP --- lib/checkclass.cpp | 5 ++++- test/testclass.cpp | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 7f5e7e289d5..088f1557dd7 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2674,8 +2674,11 @@ void CheckClass::initializerListOrder() const Token* const end = tok->next()->link(); for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { - if (const Variable* var2 = scope->getVariable(tok2->str())) + if (const Variable* var2 = scope->getVariable(tok2->str())) { + if (var->isPointer() && var2->isArray()) + continue; vars.back().initArgs.emplace_back(var2); + } } tok = end; } diff --git a/test/testclass.cpp b/test/testclass.cpp index e13e7c40aeb..495c400a20c 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -7596,6 +7596,13 @@ class TestClass : public TestFixture { " int a, b, c;\n" "};"); ASSERT_EQUALS("", errout.str()); + + checkInitializerListOrder("struct S {\n" + " S() : p(a) {}\n" + " int* p;\n" + " int a[1];\n" + "};"); + ASSERT_EQUALS("", errout.str()); } #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__) From 54a246fa8dca340f962cd4a6b37d33a770d82f71 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 7 Jan 2024 11:06:23 +0100 Subject: [PATCH 10/12] Fix FP --- lib/checkclass.cpp | 2 +- test/testclass.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 088f1557dd7..2a901bcf48d 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2675,7 +2675,7 @@ void CheckClass::initializerListOrder() const Token* const end = tok->next()->link(); for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { if (const Variable* var2 = scope->getVariable(tok2->str())) { - if (var->isPointer() && var2->isArray()) + if (var->isPointer() && (var2->isArray() || Token::simpleMatch(tok2->astParent(), "&"))) continue; vars.back().initArgs.emplace_back(var2); } diff --git a/test/testclass.cpp b/test/testclass.cpp index 495c400a20c..a5927062978 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -7603,6 +7603,13 @@ class TestClass : public TestFixture { " int a[1];\n" "};"); ASSERT_EQUALS("", errout.str()); + + checkInitializerListOrder("struct S {\n" + " S() : p(&i) {}\n" + " int* p;\n" + " int i;\n" + "};"); + ASSERT_EQUALS("", errout.str()); } #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__) From 941dfd027f92306890fc419f22dc66552d53a3c2 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 7 Jan 2024 20:42:24 +0100 Subject: [PATCH 11/12] Fix FP, simplify loop --- lib/checkclass.cpp | 11 ++++++----- test/testclass.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2a901bcf48d..2295808cd9a 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2673,14 +2673,15 @@ void CheckClass::initializerListOrder() continue; const Token* const end = tok->next()->link(); - for (const Token* tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) { - if (const Variable* var2 = scope->getVariable(tok2->str())) { - if (var->isPointer() && (var2->isArray() || Token::simpleMatch(tok2->astParent(), "&"))) + for (; tok != end; tok = tok->next()) { + if (const Variable* argVar = scope->getVariable(tok->str())) { + if (var->isPointer() && (argVar->isArray() || Token::simpleMatch(tok->astParent(), "&"))) continue; - vars.back().initArgs.emplace_back(var2); + if (Token::simpleMatch(tok->astParent(), "=")) + continue; + vars.back().initArgs.emplace_back(argVar); } } - tok = end; } } diff --git a/test/testclass.cpp b/test/testclass.cpp index a5927062978..fdf1b222624 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -7610,6 +7610,12 @@ class TestClass : public TestFixture { " int i;\n" "};"); ASSERT_EQUALS("", errout.str()); + + checkInitializerListOrder("struct S {\n" + " S() : a(b = 1) {}\n" + " int a, b;\n" + "};"); + ASSERT_EQUALS("", errout.str()); } #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__) From c1ee3cb3d8d10662c63a7564d77417e01cdbd2e9 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Tue, 9 Jan 2024 00:04:44 +0100 Subject: [PATCH 12/12] Fix FP --- lib/checkclass.cpp | 2 ++ test/testclass.cpp | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2295808cd9a..5934dcd8556 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2677,6 +2677,8 @@ void CheckClass::initializerListOrder() if (const Variable* argVar = scope->getVariable(tok->str())) { if (var->isPointer() && (argVar->isArray() || Token::simpleMatch(tok->astParent(), "&"))) continue; + if (var->isReference()) + continue; if (Token::simpleMatch(tok->astParent(), "=")) continue; vars.back().initArgs.emplace_back(argVar); diff --git a/test/testclass.cpp b/test/testclass.cpp index fdf1b222624..f6dddcdce36 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -7616,6 +7616,13 @@ class TestClass : public TestFixture { " int a, b;\n" "};"); ASSERT_EQUALS("", errout.str()); + + checkInitializerListOrder("struct S {\n" + " S() : r(i) {}\n" + " int& r;\n" + " int i{};\n" + "};"); + ASSERT_EQUALS("", errout.str()); } #define checkInitializationListUsage(code) checkInitializationListUsage_(code, __FILE__, __LINE__)