Implement support for __attribute__((used)) (#3408)

This commit is contained in:
PKEuS 2014-08-06 11:13:58 +02:00
parent 8da61ab71a
commit adcc8b1634
4 changed files with 34 additions and 14 deletions

View File

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

View File

@ -331,6 +331,12 @@ public:
void isAttributeUnused(bool unused) { void isAttributeUnused(bool unused) {
setFlag(fIsAttributeUnused, unused); setFlag(fIsAttributeUnused, unused);
} }
bool isAttributeUsed() const {
return getFlag(fIsAttributeUsed);
}
void isAttributeUsed(bool unused) {
setFlag(fIsAttributeUsed, unused);
}
bool isAttributePure() const { bool isAttributePure() const {
return getFlag(fIsAttributePure); return getFlag(fIsAttributePure);
} }
@ -743,7 +749,8 @@ private:
fIsAttributePure = (1 << 9), // __attribute__((pure)) fIsAttributePure = (1 << 9), // __attribute__((pure))
fIsAttributeConst = (1 << 10), // __attribute__((const)) fIsAttributeConst = (1 << 10), // __attribute__((const))
fIsAttributeNothrow = (1 << 11), // __attribute__((nothrow)) fIsAttributeNothrow = (1 << 11), // __attribute__((nothrow))
fIsDeclspecNothrow = (1 << 12) // __declspec(nothrow) fIsDeclspecNothrow = (1 << 12), // __declspec(nothrow)
fIsAttributeUsed = (1 << 13) // __attribute__((used))
}; };
unsigned int _flags; unsigned int _flags;

View File

@ -111,18 +111,7 @@ Token *Tokenizer::copyTokens(Token *dest, const Token *first, const Token *last,
tok2->fileIndex(commonFileIndex); tok2->fileIndex(commonFileIndex);
tok2->linenr(linenrs); tok2->linenr(linenrs);
tok2->type(tok->type()); tok2->type(tok->type());
tok2->isUnsigned(tok->isUnsigned()); tok2->flags(tok2->flags());
tok2->isSigned(tok->isSigned());
tok2->isPointerCompare(tok->isPointerCompare());
tok2->isLong(tok->isLong());
tok2->isExpandedMacro(tok->isExpandedMacro());
tok2->isAttributeConstructor(tok->isAttributeConstructor());
tok2->isAttributeDestructor(tok->isAttributeDestructor());
tok2->isAttributeUnused(tok->isAttributeUnused());
tok2->isAttributePure(tok->isAttributePure());
tok2->isAttributeConst(tok->isAttributeConst());
tok2->isAttributeNothrow(tok->isAttributeNothrow());
tok2->isDeclspecNothrow(tok->isDeclspecNothrow());
tok2->varId(tok->varId()); tok2->varId(tok->varId());
// Check for links and fix them up // Check for links and fix them up
@ -9248,6 +9237,18 @@ void Tokenizer::simplifyAttribute()
tok->next()->link()->next()->isAttributeUnused(true); tok->next()->link()->next()->isAttributeUnused(true);
} }
else if (Token::Match(tok->tokAt(2), "( used|__used__ )")) {
// check if after variable name
if (Token::Match(tok->next()->link()->next(), ";|=")) {
if (Token::Match(tok->previous(), "%type%"))
tok->previous()->isAttributeUsed(true);
}
// check if before variable name
else if (Token::Match(tok->next()->link()->next(), "%type%"))
tok->next()->link()->next()->isAttributeUsed(true);
}
else if (Token::Match(tok->tokAt(2), "( pure|__pure__ )")) { else if (Token::Match(tok->tokAt(2), "( pure|__pure__ )")) {
// type func(...) __attribute__((pure)); // type func(...) __attribute__((pure));
if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% (")) if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% ("))

View File

@ -3240,6 +3240,18 @@ private:
" bool __attribute__((unused)) test = true;\n" " bool __attribute__((unused)) test = true;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
functionVariableUsage("int foo()\n"
"{\n"
" bool test __attribute__((used));\n"
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("int foo()\n"
"{\n"
" bool __attribute__((used)) test;\n"
"}");
ASSERT_EQUALS("", errout.str());
} }
void localvarFunction() { void localvarFunction() {