diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 682ab3940..fe3040ef9 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -846,6 +846,16 @@ static bool hasUnknownVars(const Token* startTok) return result; } +static bool isStructuredBindingVariable(const Variable* var) +{ + if (!var) + return false; + const Token* tok = var->nameToken(); + while (Token::Match(tok->astParent(), "[|,")) + tok = tok->astParent(); + return Token::simpleMatch(tok, "["); +} + /// This takes a token that refers to a variable and it will return the token /// to the expression that the variable is assigned to. If its not valid to /// make such substitution then it will return the original token. @@ -879,6 +889,8 @@ static const Token * followVariableExpression(const Token * tok, bool cpp, const return tok; if (var->isArgument()) return tok; + if (isStructuredBindingVariable(var)) + return tok; const Token * lastTok = precedes(tok, end) ? end : tok; // If this is in a loop then check if variables are modified in the entire scope const Token * endToken = (isInLoopCondition(tok) || isInLoopCondition(varTok) || var->scope() != tok->scope()) ? var->scope()->bodyEnd : lastTok; @@ -931,7 +943,7 @@ std::vector followAllReferences(const Token* tok, return {{tok, std::move(errors)}}; const Variable *var = tok->variable(); if (var && var->declarationId() == tok->varId()) { - if (var->nameToken() == tok) { + if (var->nameToken() == tok || isStructuredBindingVariable(var)) { return {{tok, std::move(errors)}}; } else if (var->isReference() || var->isRValueReference()) { if (!var->declEndToken()) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 6ae692f96..4a11c83b3 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -3850,6 +3850,14 @@ private: " while (is_running) {}\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // #10659 + check("auto func(const std::tuple& t) {\n" + " auto& [foo, bar] = t;\n" + " std::cout << foo << bar << std::endl;\n" + " return foo < bar;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void alwaysTrueSymbolic()