Fixed #3471 (Unused functions: take __attribute__((constructor)) in to consideration)
This commit is contained in:
parent
fc435ae9aa
commit
4a1d1ce1a1
|
@ -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..
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
23
lib/token.h
23
lib/token.h
|
@ -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. */
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue