diff --git a/lib/astutils.cpp b/lib/astutils.cpp index cdf5e9d26..f2f0f10d1 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -169,9 +169,9 @@ bool astHasToken(const Token* root, const Token * tok) { if (!root) return false; - if (root == tok) - return true; - return astHasToken(root->astOperand1(), tok) || astHasToken(root->astOperand2(), tok); + while (tok->astParent() && tok != root) + tok = tok->astParent(); + return root == tok; } bool astHasVar(const Token * tok, nonneg int varid) @@ -833,6 +833,8 @@ std::vector followAllReferences(const Token* tok, errors.emplace_back(var->declEndToken(), "Passed to reference."); return {{tok, std::move(errors)}}; } else if (Token::simpleMatch(var->declEndToken(), "=")) { + if (astHasToken(var->declEndToken(), tok)) + return std::vector{}; errors.emplace_back(var->declEndToken(), "Assigned to reference."); const Token *vartok = var->declEndToken()->astOperand2(); if (vartok == tok || (!temporary && isTemporary(true, vartok, nullptr, true) && diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index ed3e89f9a..7dde244b1 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -409,6 +409,7 @@ private: TEST_CASE(checkIfCppCast); TEST_CASE(checkRefQualifiers); TEST_CASE(checkConditionBlock); + TEST_CASE(checkUnknownCircularVar); // #9052 TEST_CASE(noCrash1); @@ -6845,6 +6846,14 @@ private: "}\n")); } + void checkUnknownCircularVar() + { + ASSERT_NO_THROW(tokenizeAndStringify("void execute() {\n" + " const auto &bias = GEMM_CTX_ARG_STORAGE(bias);\n" + " auto &c = GEMM_CTX_ARG_STORAGE(c);\n" + "}\n")); + } + void noCrash1() { ASSERT_NO_THROW(tokenizeAndStringify( "struct A {\n"