Unused Var: Fix FP when initialization is made in macro
This commit is contained in:
parent
ad6c5d80ff
commit
e8e00d8fdf
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue