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, ".|[|*"))
|
while (Token::Match(op1tok, ".|[|*"))
|
||||||
op1tok = op1tok->astOperand1();
|
op1tok = op1tok->astOperand1();
|
||||||
|
|
||||||
|
// Assignment in macro => do not warn
|
||||||
|
if (isAssignment && tok->isExpandedMacro() && op1tok && op1tok->isExpandedMacro())
|
||||||
|
continue;
|
||||||
|
|
||||||
const Variable *op1Var = op1tok ? op1tok->variable() : nullptr;
|
const Variable *op1Var = op1tok ? op1tok->variable() : nullptr;
|
||||||
if (!op1Var && Token::Match(tok, "(|{") && tok->previous() && tok->previous()->variable())
|
if (!op1Var && Token::Match(tok, "(|{") && tok->previous() && tok->previous()->variable())
|
||||||
op1Var = tok->previous()->variable();
|
op1Var = tok->previous()->variable();
|
||||||
|
@ -1353,6 +1357,13 @@ void CheckUnusedVar::checkFunctionVariableUsage()
|
||||||
bool error = false;
|
bool error = false;
|
||||||
if (vnt->next()->isSplittedVarDeclEq()) {
|
if (vnt->next()->isSplittedVarDeclEq()) {
|
||||||
const Token* nextStmt = vnt->tokAt(2);
|
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() != ";")
|
while (nextStmt && nextStmt->str() != ";")
|
||||||
nextStmt = nextStmt->next();
|
nextStmt = nextStmt->next();
|
||||||
error = precedes(usage._lastAccess, nextStmt);
|
error = precedes(usage._lastAccess, nextStmt);
|
||||||
|
|
|
@ -6435,6 +6435,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
|
||||||
endDecl = endDecl->next();
|
endDecl = endDecl->next();
|
||||||
endDecl->next()->isSplittedVarDeclEq(true);
|
endDecl->next()->isSplittedVarDeclEq(true);
|
||||||
endDecl->insertToken(varName->str());
|
endDecl->insertToken(varName->str());
|
||||||
|
endDecl->next()->isExpandedMacro(varName->isExpandedMacro());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//non-VLA case
|
//non-VLA case
|
||||||
|
|
|
@ -136,6 +136,7 @@ private:
|
||||||
TEST_CASE(localvar65); // #9876, #10006
|
TEST_CASE(localvar65); // #9876, #10006
|
||||||
TEST_CASE(localvar66); // #11143
|
TEST_CASE(localvar66); // #11143
|
||||||
TEST_CASE(localvar67); // #9946
|
TEST_CASE(localvar67); // #9946
|
||||||
|
TEST_CASE(localvar68);
|
||||||
TEST_CASE(localvarloops); // loops
|
TEST_CASE(localvarloops); // loops
|
||||||
TEST_CASE(localvaralias1);
|
TEST_CASE(localvaralias1);
|
||||||
TEST_CASE(localvaralias2); // ticket #1637
|
TEST_CASE(localvaralias2); // ticket #1637
|
||||||
|
@ -265,6 +266,31 @@ private:
|
||||||
(checkUnusedVar.checkStructMemberUsage)();
|
(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() {
|
void isRecordTypeWithoutSideEffects() {
|
||||||
functionVariableUsage(
|
functionVariableUsage(
|
||||||
"class A {};\n"
|
"class A {};\n"
|
||||||
|
@ -3639,6 +3665,16 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void localvarloops() {
|
||||||
// loops
|
// loops
|
||||||
functionVariableUsage("void fun(int c) {\n"
|
functionVariableUsage("void fun(int c) {\n"
|
||||||
|
|
Loading…
Reference in New Issue