simplifyCPPAttribute tokenizer strips alignas (#3171)
This commit is contained in:
parent
ab33bf1da8
commit
9b7f1f6280
|
@ -4816,7 +4816,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
|||
// simplify namespace aliases
|
||||
simplifyNamespaceAliases();
|
||||
|
||||
// Remove [[attribute]]
|
||||
// Remove [[attribute]] and alignas(?)
|
||||
simplifyCPPAttribute();
|
||||
|
||||
// remove __attribute__((?))
|
||||
|
@ -9919,6 +9919,21 @@ static bool isCPPAttribute(const Token * tok)
|
|||
return Token::simpleMatch(tok, "[ [") && tok->link() && tok->link()->previous() == tok->linkAt(1);
|
||||
}
|
||||
|
||||
static bool isAlignAttribute(const Token * tok)
|
||||
{
|
||||
return Token::simpleMatch(tok, "alignas (") && tok->next()->link();
|
||||
}
|
||||
|
||||
static const Token* skipCPPOrAlignAttribute(const Token * tok)
|
||||
{
|
||||
if(isCPPAttribute(tok)) {
|
||||
return tok->link();
|
||||
}else if(isAlignAttribute(tok)) {
|
||||
return tok->next()->link();
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
void Tokenizer::reportUnknownMacros() const
|
||||
{
|
||||
// Report unknown macros used in expressions "%name% %num%"
|
||||
|
@ -10182,8 +10197,8 @@ void Tokenizer::findGarbageCode() const
|
|||
continue;
|
||||
}
|
||||
// skip C++ attributes [[...]]
|
||||
if (isCPP11 && isCPPAttribute(tok)) {
|
||||
tok = tok->link();
|
||||
if (isCPP11 && (isCPPAttribute(tok) || isAlignAttribute(tok)) ) {
|
||||
tok = skipCPPOrAlignAttribute(tok);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
|
@ -10825,23 +10840,35 @@ void Tokenizer::simplifyCPPAttribute()
|
|||
return;
|
||||
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (!isCPPAttribute(tok))
|
||||
if (!isCPPAttribute(tok) && !isAlignAttribute(tok)){
|
||||
continue;
|
||||
if (Token::Match(tok->tokAt(2), "noreturn|nodiscard")) {
|
||||
const Token * head = tok->link()->next();
|
||||
while (Token::Match(head, "%name%|::|*|&"))
|
||||
}
|
||||
if(isCPPAttribute(tok)){
|
||||
if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
|
||||
const Token * head = skipCPPOrAlignAttribute(tok);
|
||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||
head = skipCPPOrAlignAttribute(head);
|
||||
head = head->next();
|
||||
while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type
|
||||
head = head->next();
|
||||
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
||||
if (tok->strAt(2) == "noreturn")
|
||||
head->previous()->isAttributeNoreturn(true);
|
||||
else
|
||||
}
|
||||
} else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) {
|
||||
const Token * head = skipCPPOrAlignAttribute(tok);
|
||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||
head = skipCPPOrAlignAttribute(head);
|
||||
head = head->next();
|
||||
while (Token::Match(head, "%name%|::|*|&|<|>|,"))
|
||||
head = head->next();
|
||||
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
||||
head->previous()->isAttributeNodiscard(true);
|
||||
}
|
||||
} else if (Token::simpleMatch(tok->tokAt(2), "maybe_unused")) {
|
||||
Token* head = tok->tokAt(5);
|
||||
while (isCPPAttribute(head))
|
||||
head = head->tokAt(5);
|
||||
head->isAttributeMaybeUnused(true);
|
||||
} else if (Token::findsimplematch(tok->tokAt(2), "maybe_unused", tok->link())) {
|
||||
const Token* head = skipCPPOrAlignAttribute(tok);
|
||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||
head = skipCPPOrAlignAttribute(head);
|
||||
head->next()->isAttributeMaybeUnused(true);
|
||||
} else if (Token::Match(tok->previous(), ") [ [ expects|ensures|assert default|audit|axiom| : %name% <|<=|>|>= %num% ] ]")) {
|
||||
const Token *vartok = tok->tokAt(4);
|
||||
if (vartok->str() == ":")
|
||||
|
@ -10865,8 +10892,20 @@ void Tokenizer::simplifyCPPAttribute()
|
|||
argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, MathLib::toLongNumber(vartok->strAt(2))-1);
|
||||
}
|
||||
}
|
||||
Token::eraseTokens(tok, tok->link()->next());
|
||||
} else {
|
||||
if (Token::simpleMatch(tok, "alignas (")) {
|
||||
// alignment requirements could be checked here
|
||||
}
|
||||
}
|
||||
Token::eraseTokens(tok, skipCPPOrAlignAttribute(tok)->next());
|
||||
// fix iterator after removing
|
||||
if(tok->previous()){
|
||||
tok = tok->previous();
|
||||
tok->next()->deleteThis();
|
||||
}else{
|
||||
tok->deleteThis();
|
||||
tok = list.front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -345,6 +345,7 @@ private:
|
|||
TEST_CASE(symboldatabase90);
|
||||
TEST_CASE(symboldatabase91);
|
||||
TEST_CASE(symboldatabase92); // daca crash
|
||||
TEST_CASE(symboldatabase93); // alignas attribute
|
||||
|
||||
TEST_CASE(createSymbolDatabaseFindAllScopes1);
|
||||
|
||||
|
@ -426,6 +427,7 @@ private:
|
|||
TEST_CASE(nothrowDeclspecFunction);
|
||||
|
||||
TEST_CASE(noreturnAttributeFunction);
|
||||
TEST_CASE(nodiscardAttributeFunction);
|
||||
|
||||
TEST_CASE(varTypesIntegral); // known integral
|
||||
TEST_CASE(varTypesFloating); // known floating
|
||||
|
@ -4689,6 +4691,15 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void symboldatabase93() { // alignas attribute
|
||||
GET_SYMBOL_DB("struct alignas(int) A{\n"
|
||||
"};\n"
|
||||
);
|
||||
ASSERT(db != nullptr);
|
||||
const Scope* scope = db->findScopeByName("A");
|
||||
ASSERT(scope);
|
||||
}
|
||||
|
||||
void createSymbolDatabaseFindAllScopes1() {
|
||||
GET_SYMBOL_DB("void f() { union {int x; char *p;} a={0}; }");
|
||||
ASSERT(db->scopeList.size() == 3);
|
||||
|
@ -6647,6 +6658,44 @@ private:
|
|||
func = findFunctionByName("func4", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
|
||||
}
|
||||
|
||||
void nodiscardAttributeFunction() {
|
||||
GET_SYMBOL_DB("[[nodiscard]] int func1();\n"
|
||||
"int func1() { }\n"
|
||||
"[[nodiscard]] int func2();\n"
|
||||
"[[nodiscard]] int func3() { }\n"
|
||||
"template <class T> [[nodiscard]] int func4() { }"
|
||||
"std::pair<bool, char> [[nodiscard]] func5();\n"
|
||||
"[[nodiscard]] std::pair<bool, char> func6();\n"
|
||||
);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS(true, db != nullptr); // not null
|
||||
|
||||
const Function *func = findFunctionByName("func1", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNodiscard());
|
||||
|
||||
func = findFunctionByName("func2", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNodiscard());
|
||||
|
||||
func = findFunctionByName("func3", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNodiscard());
|
||||
|
||||
func = findFunctionByName("func4", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNodiscard());
|
||||
|
||||
func = findFunctionByName("func5", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNodiscard());
|
||||
|
||||
func = findFunctionByName("func6", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNodiscard());
|
||||
}
|
||||
|
||||
void varTypesIntegral() {
|
||||
|
|
|
@ -5690,6 +5690,21 @@ private:
|
|||
|
||||
ASSERT_EQUALS("struct a ;",
|
||||
tokenizeAndStringify("struct [[,,,]] a;", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("struct a ;",
|
||||
tokenizeAndStringify("struct alignas(int) a;", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("struct a ;",
|
||||
tokenizeAndStringify("struct alignas ( alignof ( float ) ) a;", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("char a [ 256 ] ;",
|
||||
tokenizeAndStringify("alignas(256) char a[256];", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("struct a ;",
|
||||
tokenizeAndStringify("struct alignas(float) [[deprecated(reason)]] a;", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("struct a ;",
|
||||
tokenizeAndStringify("struct [[deprecated,maybe_unused]] alignas(double) [[trivial_abi]] a;", false, true, Settings::Native, "test.cpp", true));
|
||||
}
|
||||
|
||||
void simplifyCaseRange() {
|
||||
|
|
Loading…
Reference in New Issue