Fixed #3471 (Unused functions: take __attribute__((constructor)) in to consideration)

This commit is contained in:
Daniel Marjamäki 2013-08-30 06:27:46 +02:00
parent fc435ae9aa
commit 4a1d1ce1a1
7 changed files with 49 additions and 23 deletions

View File

@ -64,6 +64,10 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer)
if (Token::Match(tok->previous(), ")|const") || funcname == 0)
continue;
// Don't warn about functions that are marked by __attribute__((constructor))
if (tok->isAttributeConstructor() || funcname->isAttributeConstructor())
continue;
tok = funcname->linkAt(1);
// Check that ") {" is found..

View File

@ -1079,7 +1079,7 @@ void CheckUnusedVar::checkFunctionVariableUsage()
const Variable* var = symbolDatabase->getVariableFromVarId(it->first);
// variable has been marked as unused so ignore it
if (usage._var->nameToken()->isUnused())
if (usage._var->nameToken()->isAttributeUnused())
continue;
// skip things that are only partially implemented to prevent false positives

View File

@ -45,9 +45,10 @@ Token::Token(Token **t) :
_isSigned(false),
_isPointerCompare(false),
_isLong(false),
_isUnused(false),
_isStandardType(false),
_isExpandedMacro(false),
_isAttributeConstructor(false),
_isAttributeUnused(false),
_astOperand1(NULL),
_astOperand2(NULL),
_astParent(NULL)
@ -192,9 +193,10 @@ void Token::deleteThis()
_isSigned = _next->_isSigned;
_isPointerCompare = _next->_isPointerCompare;
_isLong = _next->_isLong;
_isUnused = _next->_isUnused;
_isStandardType = _next->_isStandardType;
_isExpandedMacro = _next->_isExpandedMacro;
_isAttributeConstructor = _next->_isAttributeConstructor;
_isAttributeUnused = _next->_isAttributeUnused;
_varId = _next->_varId;
_fileIndex = _next->_fileIndex;
_linenr = _next->_linenr;
@ -213,9 +215,10 @@ void Token::deleteThis()
_isSigned = _previous->_isSigned;
_isPointerCompare = _previous->_isPointerCompare;
_isLong = _previous->_isLong;
_isUnused = _previous->_isUnused;
_isStandardType = _previous->_isStandardType;
_isExpandedMacro = _previous->_isExpandedMacro;
_isAttributeConstructor = _previous->_isAttributeConstructor;
_isAttributeUnused = _previous->_isAttributeUnused;
_varId = _previous->_varId;
_fileIndex = _previous->_fileIndex;
_linenr = _previous->_linenr;

View File

@ -261,21 +261,27 @@ public:
void isLong(bool size) {
_isLong = size;
}
bool isUnused() const {
return _isUnused;
}
void isUnused(bool used) {
_isUnused = used;
}
bool isStandardType() const {
return _isStandardType;
}
bool isExpandedMacro() const {
return _isExpandedMacro;
}
void setExpandedMacro(bool m) {
void isExpandedMacro(bool m) {
_isExpandedMacro = m;
}
bool isAttributeConstructor() const {
return _isAttributeConstructor;
}
void isAttributeConstructor(bool ac) {
_isAttributeConstructor = ac;
}
bool isAttributeUnused() const {
return _isAttributeUnused;
}
void isAttributeUnused(bool unused) {
_isAttributeUnused = unused;
}
static const Token *findsimplematch(const Token *tok, const char pattern[]);
static const Token *findsimplematch(const Token *tok, const char pattern[], const Token *end);
@ -608,9 +614,10 @@ private:
bool _isSigned;
bool _isPointerCompare;
bool _isLong;
bool _isUnused;
bool _isStandardType;
bool _isExpandedMacro;
bool _isAttributeConstructor; // __attribute__((constructor))
bool _isAttributeUnused; // __attribute__((unused))
/** Updates internal property cache like _isName or _isBoolean.
Called after any _str() modification. */

View File

@ -108,8 +108,9 @@ Token *Tokenizer::copyTokens(Token *dest, const Token *first, const Token *last,
tok2->isSigned(tok->isSigned());
tok2->isPointerCompare(tok->isPointerCompare());
tok2->isLong(tok->isLong());
tok2->isUnused(tok->isUnused());
tok2->setExpandedMacro(tok->isExpandedMacro());
tok2->isExpandedMacro(tok->isExpandedMacro());
tok2->isAttributeConstructor(tok->isAttributeConstructor());
tok2->isAttributeUnused(tok->isAttributeUnused());
tok2->varId(tok->varId());
// Check for links and fix them up
@ -8860,16 +8861,20 @@ void Tokenizer::simplifyAttribute()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
while (Token::simpleMatch(tok, "__attribute__ (") && tok->next()->link() && tok->next()->link()->next()) {
if (Token::simpleMatch(tok->tokAt(2), "( constructor )")) {
tok->next()->link()->next()->isAttributeConstructor(true);
}
if (Token::simpleMatch(tok->tokAt(2), "( unused )")) {
// check if after variable name
if (Token::Match(tok->next()->link()->next(), ";|=")) {
if (Token::Match(tok->previous(), "%type%"))
tok->previous()->isUnused(true);
tok->previous()->isAttributeUnused(true);
}
// check if before variable name
else if (Token::Match(tok->next()->link()->next(), "%type%"))
tok->next()->link()->next()->isUnused(true);
tok->next()->link()->next()->isAttributeUnused(true);
}
Token::eraseTokens(tok, tok->next()->link()->next());

View File

@ -128,7 +128,7 @@ void TokenList::addtoken(const Token * tok, const unsigned int lineno, const uns
_back->isUnsigned(tok->isUnsigned());
_back->isSigned(tok->isSigned());
_back->isLong(tok->isLong());
_back->isUnused(tok->isUnused());
_back->isAttributeUnused(tok->isAttributeUnused());
}
//---------------------------------------------------------------------------
// InsertTokens - Copy and insert tokens
@ -158,7 +158,7 @@ void TokenList::insertTokens(Token *dest, const Token *src, unsigned int n)
dest->isSigned(src->isSigned());
dest->isPointerCompare(src->isPointerCompare());
dest->isLong(src->isLong());
dest->isUnused(src->isUnused());
dest->isAttributeUnused(src->isAttributeUnused());
src = src->next();
--n;
}
@ -256,12 +256,12 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0)
// Add previous token
addtoken(CurrentToken.c_str(), lineno, FileIndex);
if (!CurrentToken.empty())
_back->setExpandedMacro(expandedMacro);
_back->isExpandedMacro(expandedMacro);
// Add content of the string
addtoken(line.c_str(), lineno, FileIndex);
if (!line.empty())
_back->setExpandedMacro(expandedMacro);
_back->isExpandedMacro(expandedMacro);
}
CurrentToken.clear();
@ -317,7 +317,7 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0)
addtoken(CurrentToken.c_str(), lineno, FileIndex, true);
if (!CurrentToken.empty())
_back->setExpandedMacro(expandedMacro);
_back->isExpandedMacro(expandedMacro);
CurrentToken.clear();
@ -336,7 +336,7 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0)
if (std::strchr("+-<>=:&|", ch) && (code.peek() == ch))
CurrentToken += (char)code.get();
addtoken(CurrentToken.c_str(), lineno, FileIndex);
_back->setExpandedMacro(expandedMacro);
_back->isExpandedMacro(expandedMacro);
CurrentToken.clear();
continue;
}
@ -345,7 +345,7 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0)
}
addtoken(CurrentToken.c_str(), lineno, FileIndex, true);
if (!CurrentToken.empty())
_back->setExpandedMacro(expandedMacro);
_back->isExpandedMacro(expandedMacro);
_front->assignProgressValues();
for (unsigned int i = 1; i < _files.size(); i++)

View File

@ -48,6 +48,7 @@ private:
TEST_CASE(initializationIsNotAFunction);
TEST_CASE(operator1); // #3195
TEST_CASE(returnRef);
TEST_CASE(attribute); // #3471 - FP __attribute__(constructor)
TEST_CASE(multipleFiles); // same function name in multiple files
@ -234,6 +235,12 @@ private:
ASSERT_EQUALS("[test.cpp:1]: (style) The function 'foo' is never used.\n", errout.str());
}
void attribute() { // #3471 - FP __attribute__((constructor))
check("void __attribute__((constructor)) f() {}");
ASSERT_EQUALS("", errout.str());
}
void multipleFiles() {
CheckUnusedFunctions c;