Unused Var: Fix FP when initialization is made in macro

This commit is contained in:
Daniel Marjamäki 2023-03-05 15:31:53 +01:00
parent ad6c5d80ff
commit e8e00d8fdf
3 changed files with 48 additions and 0 deletions

View File

@ -1237,6 +1237,10 @@ void CheckUnusedVar::checkFunctionVariableUsage()
while (Token::Match(op1tok, ".|[|*"))
op1tok = op1tok->astOperand1();
// Assignment in macro => do not warn
if (isAssignment && tok->isExpandedMacro() && op1tok && op1tok->isExpandedMacro())
continue;
const Variable *op1Var = op1tok ? op1tok->variable() : nullptr;
if (!op1Var && Token::Match(tok, "(|{") && tok->previous() && tok->previous()->variable())
op1Var = tok->previous()->variable();
@ -1353,6 +1357,13 @@ void CheckUnusedVar::checkFunctionVariableUsage()
bool error = false;
if (vnt->next()->isSplittedVarDeclEq()) {
const Token* nextStmt = vnt->tokAt(2);
if (nextStmt->isExpandedMacro()) {
const Token* parent = nextStmt;
while (parent->astParent() && parent == parent->astParent()->astOperand1())
parent = parent->astParent();
if (parent->isAssignmentOp() && parent->isExpandedMacro())
continue;
}
while (nextStmt && nextStmt->str() != ";")
nextStmt = nextStmt->next();
error = precedes(usage._lastAccess, nextStmt);

View File

@ -6435,6 +6435,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
endDecl = endDecl->next();
endDecl->next()->isSplittedVarDeclEq(true);
endDecl->insertToken(varName->str());
endDecl->next()->isExpandedMacro(varName->isExpandedMacro());
continue;
}
//non-VLA case

View File

@ -136,6 +136,7 @@ private:
TEST_CASE(localvar65); // #9876, #10006
TEST_CASE(localvar66); // #11143
TEST_CASE(localvar67); // #9946
TEST_CASE(localvar68);
TEST_CASE(localvarloops); // loops
TEST_CASE(localvaralias1);
TEST_CASE(localvaralias2); // ticket #1637
@ -265,6 +266,31 @@ private:
(checkUnusedVar.checkStructMemberUsage)();
}
void checkFunctionVariableUsageP(const char code[], const char* filename = "test.cpp") {
// Raw tokens..
std::vector<std::string> files(1, filename);
std::istringstream istr(code);
const simplecpp::TokenList tokens1(istr, files, files[0]);
// Preprocess..
simplecpp::TokenList tokens2(files);
std::map<std::string, simplecpp::TokenList*> filedata;
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
Preprocessor preprocessor(settings, nullptr);
preprocessor.setDirectives(tokens1);
// Tokenizer..
Tokenizer tokenizer(&settings, this, &preprocessor);
tokenizer.createTokens(std::move(tokens2));
tokenizer.simplifyTokens1("");
// Check for unused variables..
CheckUnusedVar checkUnusedVar(&tokenizer, &settings, this);
(checkUnusedVar.checkFunctionVariableUsage)();
}
void isRecordTypeWithoutSideEffects() {
functionVariableUsage(
"class A {};\n"
@ -3639,6 +3665,16 @@ private:
ASSERT_EQUALS("", errout.str());
}
void localvar68() {
checkFunctionVariableUsageP("#define X0 int x = 0\n"
"void f() { X0; }\n");
ASSERT_EQUALS("", errout.str());
checkFunctionVariableUsageP("#define X0 int (*x)(int) = 0\n"
"void f() { X0; }\n");
ASSERT_EQUALS("", errout.str());
}
void localvarloops() {
// loops
functionVariableUsage("void fun(int c) {\n"