Skip to content

Commit

Permalink
Honor attribute cleanup in unusedFunction
Browse files Browse the repository at this point in the history
Gets rid of FPs when a static function is only used with the attribute cleanup.
  • Loading branch information
mptre committed Aug 6, 2024
1 parent ef487ad commit a0b583d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/checkunusedfunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting
}
}

if (tok->hasAttributeCleanup()) {
const std::string& funcname = tok->getAttributeCleanup();
mFunctions[funcname].usedOtherFile = true;
mFunctionCalls.insert(funcname);
continue;
}

const Token *funcname = nullptr;

if (doMarkup)
Expand Down
11 changes: 11 additions & 0 deletions lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ struct TokenImpl {
mAttributeAlignas->push_back(a);
}

std::string mAttributeCleanup;

// For memoization, to speed up parsing of huge arrays #8897
enum class Cpp11init : std::uint8_t { UNKNOWN, CPP11INIT, NOINIT } mCpp11init = Cpp11init::UNKNOWN;

Expand Down Expand Up @@ -565,6 +567,15 @@ class CPPCHECKLIB Token {
void addAttributeAlignas(const std::string& a) {
mImpl->addAttributeAlignas(a);
}
void addAttributeCleanup(const std::string& funcname) {
mImpl->mAttributeCleanup = funcname;
}
const std::string& getAttributeCleanup() const {
return mImpl->mAttributeCleanup;
}
bool hasAttributeCleanup() const {
return !mImpl->mAttributeCleanup.empty();
}
void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) {
mImpl->setCppcheckAttribute(type, value);
}
Expand Down
28 changes: 28 additions & 0 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9146,6 +9146,26 @@ static Token* getTokenAfterAttributes(Token* tok, bool gccattr) {
return after;
}

static Token* getVariableTokenAfterAttributes(Token* tok) {
Token *vartok = nullptr;
Token *after = getTokenAfterAttributes(tok, true);

// check if after variable name
if (Token::Match(after, ";|=")) {
Token *prev = tok->previous();
while (Token::simpleMatch(prev, "]"))
prev = prev->link()->previous();
if (Token::Match(prev, "%type%"))
vartok = prev;
}

// check if before variable name
else if (Token::Match(after, "%type%"))
vartok = after;

return vartok;
}

Token* Tokenizer::getAttributeFuncTok(Token* tok, bool gccattr) const {
if (!Token::Match(tok, "%name% ("))
return nullptr;
Expand Down Expand Up @@ -9284,6 +9304,14 @@ void Tokenizer::simplifyAttribute()

else if (functok && Token::simpleMatch(attr, "( __visibility__ ( \"default\" ) )"))
functok->isAttributeExport(true);

else if (Token::Match(attr, "[(,] cleanup ( %name% )")) {
Token *vartok = getVariableTokenAfterAttributes(tok);
if (vartok) {
const std::string& funcname = attr->strAt(3);
vartok->addAttributeCleanup(funcname);
}
}
}

Token::eraseTokens(tok, tok->linkAt(1)->next());
Expand Down
10 changes: 10 additions & 0 deletions test/testunusedfunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class TestUnusedFunctions : public TestFixture {
TEST_CASE(virtualFunc);
TEST_CASE(parensInit);
TEST_CASE(typeInCast);
TEST_CASE(attributeCleanup);
}

#define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
Expand Down Expand Up @@ -769,6 +770,15 @@ class TestUnusedFunctions : public TestFixture {
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (style) The function 'Type' is never used.\n", errout_str());
}

void attributeCleanup()
{
check("void clean(void *ptr) {}\n"
"int main() {\n"
" void * __attribute__((cleanup(clean))) p;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
}
};

REGISTER_TEST(TestUnusedFunctions)

0 comments on commit a0b583d

Please sign in to comment.