Implement support for __attribute__((used)) (#3408)
This commit is contained in:
parent
8da61ab71a
commit
adcc8b1634
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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% ("))
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue