diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 36945fcec..6b8f91b1a 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1301,14 +1301,18 @@ void CheckOther::checkPassByReference() bool inconclusive = false; - if (var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && !var->valueType()->container->view) {} else if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class. - // Ensure that it is a large object. - if (!var->type()->classScope) - inconclusive = true; - else if (estimateSize(var->type(), mSettings, symbolDatabase) <= 2 * mSettings->sizeof_pointer) + const bool isContainer = var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && var->valueType()->container && !var->valueType()->container->view; + if (!isContainer) { + if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class. + // Ensure that it is a large object. + if (!var->type()->classScope) + inconclusive = true; + else if (estimateSize(var->type(), mSettings, symbolDatabase) <= 2 * mSettings->sizeof_pointer) + continue; + } + else continue; - } else - continue; + } if (inconclusive && !mSettings->certainty.isEnabled(Certainty::inconclusive)) continue; diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 151010ff5..a532bfdfa 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -402,6 +402,8 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok) if (closing->str() == ">>") return numberOfParameters; tok = closing->next(); + if (!tok) + syntaxError(tok); if (Token::Match(tok, ">|>>|>>=")) return numberOfParameters; else if (tok->str() == ",") { diff --git a/lib/token.cpp b/lib/token.cpp index 4920c92bd..fea57dfa1 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2244,6 +2244,7 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok) return nullptr; if (typeTok != nullptr) *typeTok = tok; + const Token* lhsVarTok{}; if (Token::simpleMatch(tok, "return")) { const Scope *scope = tok->scope(); if (!scope) @@ -2266,8 +2267,8 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok) return function->retType; } else if (Token::Match(tok->previous(), "%type%|= (|{")) { return typeOf(tok->previous(), typeTok); - } else if (Token::simpleMatch(tok, "=")) { - return Token::typeOf(getLHSVariableToken(tok), typeTok); + } else if (Token::simpleMatch(tok, "=") && (lhsVarTok = getLHSVariableToken(tok)) != tok->next()) { + return Token::typeOf(lhsVarTok, typeTok); } else if (Token::simpleMatch(tok, ".")) { return Token::typeOf(tok->astOperand2(), typeTok); } else if (Token::simpleMatch(tok, "[")) { diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 8e42829ea..787e69115 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -251,6 +251,7 @@ private: TEST_CASE(garbageCode219); // #10101 TEST_CASE(garbageCode220); // #6832 TEST_CASE(garbageCode221); + TEST_CASE(garbageCode222); // #10763 TEST_CASE(garbageCodeFuzzerClientMode1); // test cases created with the fuzzer client, mode 1 @@ -1708,6 +1709,9 @@ private: void garbageCode221() { ASSERT_THROW(checkCode("struct A<0<;\n"), InternalError); // don't crash } + void garbageCode222() { // #10763 + ASSERT_THROW(checkCode("template\n"), InternalError); // don't crash + } void syntaxErrorFirstToken() { ASSERT_THROW(checkCode("&operator(){[]};"), InternalError); // #7818 diff --git a/test/testother.cpp b/test/testother.cpp index 027d89599..8609ee72d 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -8520,6 +8520,10 @@ private: " A a2;" "};", nullptr, false, false, true); ASSERT_EQUALS("[test.cpp:8]: (performance) Function parameter 'a2' should be passed by const reference.\n", errout.str()); + + check("std::map m;\n" // #10817 + "void f(const decltype(m)::const_iterator i) {}"); + ASSERT_EQUALS("", errout.str()); } void checkComparisonFunctionIsAlwaysTrueOrFalse() { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 5778e40c6..3dfced215 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -687,6 +687,18 @@ private: lifetimes = lifetimeValues(code, "( void * )"); ASSERT_EQUALS(true, lifetimes.size() == 1); ASSERT_EQUALS(true, lifetimes.front() == "i"); + + code = "struct T {\n" // #10810 + " static int g() { return 0; }\n" + "};\n" + "T t;\n" + "struct S { int i; };\n" + "S f() {\n" + " S s = { decltype(t)::g() };\n" + " return s;\n" + "};\n"; + lifetimes = lifetimeValues(code, "="); + ASSERT_EQUALS(true, lifetimes.empty()); } void valueFlowArrayElement() {