diff --git a/lib/astutils.cpp b/lib/astutils.cpp index a762d500505..30b26a79254 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2550,7 +2550,7 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti } if (const Variable* var = tok->variable()) { - if (tok == var->nameToken() && (!var->isReference() || var->isConst()) && (!var->isClass() || (var->valueType() && var->valueType()->container))) // const ref or passed to (copy) ctor + if (tok == var->nameToken() && (!var->isReference() || (var->isConst() && var->type() == tok1->type())) && (!var->isClass() || (var->valueType() && var->valueType()->container))) // const ref or passed to (copy) ctor return false; } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b2694508624..1b0913f2cf0 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2378,7 +2378,7 @@ void Variable::evaluate(const Settings& settings) std::string strtype = mTypeStartToken->str(); for (const Token *typeToken = mTypeStartToken; Token::Match(typeToken, "%type% :: %type%"); typeToken = typeToken->tokAt(2)) strtype += "::" + typeToken->strAt(2); - setFlag(fIsClass, !lib.podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && strtype != "..."); + setFlag(fIsClass, !lib.podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && !isReference() && strtype != "..."); setFlag(fIsStlType, Token::simpleMatch(mTypeStartToken, "std ::")); setFlag(fIsStlString, ::isStlStringType(mTypeStartToken)); setFlag(fIsSmartPointer, mTypeStartToken->isCpp() && lib.isSmartPointer(mTypeStartToken)); diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 62bd960da0a..226e4e502da 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -75,6 +75,7 @@ class TestConstructors : public TestFixture { TEST_CASE(simple15); // #8942 multiple arguments, decltype TEST_CASE(simple16); // copy members with c++11 init TEST_CASE(simple17); // #10360 + TEST_CASE(simple18); TEST_CASE(noConstructor1); TEST_CASE(noConstructor2); @@ -510,6 +511,23 @@ class TestConstructors : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void simple15() { // #8942 + check("class A\n" + "{\n" + "public:\n" + " int member;\n" + "};\n" + "class B\n" + "{\n" + "public:\n" + " B(const decltype(A::member)& x, const decltype(A::member)& y) : x(x), y(y) {}\n" + "private:\n" + " const decltype(A::member)& x;\n" + " const decltype(A::member)& y;\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + } + void simple16() { check("struct S {\n" " int i{};\n" @@ -554,21 +572,13 @@ class TestConstructors : public TestFixture { ASSERT_EQUALS("", errout_str()); } - void simple15() { // #8942 - check("class A\n" - "{\n" - "public:\n" - " int member;\n" - "};\n" - "class B\n" - "{\n" - "public:\n" - " B(const decltype(A::member)& x, const decltype(A::member)& y) : x(x), y(y) {}\n" - "private:\n" - " const decltype(A::member)& x;\n" - " const decltype(A::member)& y;\n" - "};\n"); - ASSERT_EQUALS("", errout_str()); + void simple18() { // #13302 + check("struct S {};\n" + "class C1 { S& r; };\n" + "class C2 { S* p; };\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) The class 'C1' does not declare a constructor although it has private member variables which likely require initialization.\n" + "[test.cpp:3]: (style) The class 'C2' does not declare a constructor although it has private member variables which likely require initialization.\n", + errout_str()); } void noConstructor1() {