Fix 10659: FP knownConditionTrueFalse - C++17 structured binding (#3662)

This commit is contained in:
Paul Fultz II 2022-01-02 01:14:50 -06:00 committed by GitHub
parent af289c8357
commit 71a44395c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 1 deletions

View File

@ -846,6 +846,16 @@ static bool hasUnknownVars(const Token* startTok)
return result; 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 /// 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 /// to the expression that the variable is assigned to. If its not valid to
/// make such substitution then it will return the original token. /// 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; return tok;
if (var->isArgument()) if (var->isArgument())
return tok; return tok;
if (isStructuredBindingVariable(var))
return tok;
const Token * lastTok = precedes(tok, end) ? end : 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 // 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; const Token * endToken = (isInLoopCondition(tok) || isInLoopCondition(varTok) || var->scope() != tok->scope()) ? var->scope()->bodyEnd : lastTok;
@ -931,7 +943,7 @@ std::vector<ReferenceToken> followAllReferences(const Token* tok,
return {{tok, std::move(errors)}}; return {{tok, std::move(errors)}};
const Variable *var = tok->variable(); const Variable *var = tok->variable();
if (var && var->declarationId() == tok->varId()) { if (var && var->declarationId() == tok->varId()) {
if (var->nameToken() == tok) { if (var->nameToken() == tok || isStructuredBindingVariable(var)) {
return {{tok, std::move(errors)}}; return {{tok, std::move(errors)}};
} else if (var->isReference() || var->isRValueReference()) { } else if (var->isReference() || var->isRValueReference()) {
if (!var->declEndToken()) if (!var->declEndToken())

View File

@ -3850,6 +3850,14 @@ private:
" while (is_running) {}\n" " while (is_running) {}\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #10659
check("auto func(const std::tuple<int, int>& 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() void alwaysTrueSymbolic()