diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 62a616ee6..fecf31711 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2254,7 +2254,7 @@ static T* getTokenArgumentFunctionImpl(T* tok, int& argn) parent = parent->astParent(); // passing variable to subfunction? - if (Token::Match(parent, "[*[(,{]") || Token::Match(parent, "%oror%|&&")) + if (Token::Match(parent, "[*[(,{.]") || Token::Match(parent, "%oror%|&&")) ; else if (Token::simpleMatch(parent, ":")) { while (Token::Match(parent, "[?:]")) @@ -3310,8 +3310,13 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings, const Token* op = parent->astParent(); while (Token::simpleMatch(op, ".")) op = op->astParent(); - if (Token::Match(op, "%assign%|++|--") && op->str() != "=") - return ExprUsage::Used; + if (Token::Match(op, "%assign%|++|--")) { + if (op->str() == "=") { + if (precedes(tok, op)) + return ExprUsage::NotUsed; + } else + return ExprUsage::Used; + } } if (Token::simpleMatch(parent, "=") && astIsRHS(tok)) { const Token* const lhs = parent->astOperand1(); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index e89031a81..d13373309 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -5089,6 +5089,11 @@ private: " return fwrite(s.c_str(), 1, s.length(), fp) == s.length();\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("void f(const std::string& s) {\n" // #9148 + " if (s.empty() || s.size() < 1) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 's.size()<1' is always false\n", errout.str()); } void alwaysTrueLoop() diff --git a/test/testother.cpp b/test/testother.cpp index a97f52b8d..75977e4dd 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3395,6 +3395,29 @@ private: " std::transform(v1.begin(), v1.end(), v2.begin(), [](auto& x) { return &x; });\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("class T;\n" // #11869 + "class E {\n" + "public:\n" + " class F {\n" + " public:\n" + " explicit F(const T* t);\n" + " };\n" + "};\n" + "void f(T& t) {\n" + " std::list c(1, E::F(&t));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9]: (style) Parameter 't' can be declared as reference to const\n", errout.str()); + + check("struct T;\n" + "struct U {\n" + " struct V { explicit V(const T* p); };\n" + "};\n" + "void g(U::V v);\n" + "void f(T& t) {\n" + " g(U::V(&t));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (style) Parameter 't' can be declared as reference to const\n", errout.str()); } void constParameterCallback() { @@ -3910,6 +3933,13 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'p' can be declared as pointer to const\n", errout.str()); + + check("struct S { const T* t; };\n" // #12206 + "void f(S* s) {\n" + " if (s->t.i) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 's' can be declared as pointer to const\n", + errout.str()); } void switchRedundantAssignmentTest() {