fix skipping of cpp attributes. (#4971)
* fix skipping of cpp attributes. * fix simplifyCPPAttribute loop. When the first token was the start of a c++ attribute on a function, so that tok->previous() was nullptr at the bottom of the loop, an extra token would be skipped. This could result in the corresponding function being omitted from the symbol table. * fix alignas test failure, enhance cpp attr test. * uncrustify. * fix redundantNextPrevious * delete redundant code. * add some tokenizer tests for simplifyCPPAttribute. * enhance noreturn symbol test. The order of a noreturn attribute and another attribute used to matter. Test both orders.
This commit is contained in:
parent
c3002f1230
commit
4183336dc1
|
@ -8825,36 +8825,35 @@ void Tokenizer::simplifyCPPAttribute()
|
|||
if (mSettings->standards.cpp < Standards::CPP11 || isC())
|
||||
return;
|
||||
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
for (Token *tok = list.front(); tok;) {
|
||||
if (!isCPPAttribute(tok) && !isAlignAttribute(tok)) {
|
||||
tok = tok->next();
|
||||
continue;
|
||||
}
|
||||
if (isCPPAttribute(tok)) {
|
||||
if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
|
||||
Token * head = skipCPPOrAlignAttribute(tok);
|
||||
Token * head = skipCPPOrAlignAttribute(tok)->next();
|
||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||
head = skipCPPOrAlignAttribute(head);
|
||||
head = head->next();
|
||||
head = skipCPPOrAlignAttribute(head)->next();
|
||||
while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type
|
||||
head = head->next();
|
||||
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
||||
head->previous()->isAttributeNoreturn(true);
|
||||
}
|
||||
} else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) {
|
||||
Token * head = skipCPPOrAlignAttribute(tok);
|
||||
Token * head = skipCPPOrAlignAttribute(tok)->next();
|
||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||
head = skipCPPOrAlignAttribute(head);
|
||||
head = head->next();
|
||||
head = skipCPPOrAlignAttribute(head)->next();
|
||||
while (Token::Match(head, "%name%|::|*|&|<|>|,"))
|
||||
head = head->next();
|
||||
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
||||
head->previous()->isAttributeNodiscard(true);
|
||||
}
|
||||
} else if (Token::findsimplematch(tok->tokAt(2), "maybe_unused", tok->link())) {
|
||||
Token* head = skipCPPOrAlignAttribute(tok);
|
||||
Token* head = skipCPPOrAlignAttribute(tok)->next();
|
||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||
head = skipCPPOrAlignAttribute(head);
|
||||
head->next()->isAttributeMaybeUnused(true);
|
||||
head = skipCPPOrAlignAttribute(head)->next();
|
||||
head->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() == ":")
|
||||
|
@ -8884,14 +8883,7 @@ void Tokenizer::simplifyCPPAttribute()
|
|||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
tok->deleteThis();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7408,7 +7408,10 @@ private:
|
|||
"void func1() { }\n"
|
||||
"[[noreturn]] void func2();\n"
|
||||
"[[noreturn]] void func3() { }\n"
|
||||
"template <class T> [[noreturn]] void func4() { }");
|
||||
"template <class T> [[noreturn]] void func4() { }\n"
|
||||
"[[noreturn]] [[gnu::format(printf, 1, 2)]] void func5(const char*, ...);\n"
|
||||
"[[gnu::format(printf, 1, 2)]] [[noreturn]] void func6(const char*, ...);\n"
|
||||
);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS(true, db != nullptr); // not null
|
||||
|
||||
|
@ -7428,6 +7431,14 @@ private:
|
|||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
|
||||
func = findFunctionByName("func5", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
|
||||
func = findFunctionByName("func6", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
|
||||
}
|
||||
|
||||
void nodiscardAttributeFunction() {
|
||||
|
|
|
@ -5691,6 +5691,24 @@ private:
|
|||
|
||||
ASSERT_EQUALS("struct a ;",
|
||||
tokenizeAndStringify("struct [[deprecated,maybe_unused]] alignas(double) [[trivial_abi]] a;"));
|
||||
|
||||
ASSERT_EQUALS("void func5 ( const char * , ... ) ;",
|
||||
tokenizeAndStringify("[[noreturn]] void func5(const char*, ...);"));
|
||||
|
||||
ASSERT_EQUALS("void func5 ( const char * , ... ) ;",
|
||||
tokenizeAndStringify("[[noreturn]] [[gnu::format(printf, 1, 2)]] void func5(const char*, ...);"));
|
||||
|
||||
ASSERT_EQUALS("void func5 ( const char * , ... ) ;",
|
||||
tokenizeAndStringify("[[gnu::format(printf, 1, 2)]] [[noreturn]] void func5(const char*, ...);"));
|
||||
|
||||
ASSERT_EQUALS("int func1 ( ) ;",
|
||||
tokenizeAndStringify("[[nodiscard]] int func1();"));
|
||||
|
||||
ASSERT_EQUALS("int func1 ( ) ;",
|
||||
tokenizeAndStringify("[[nodiscard]] [[clang::optnone]] int func1();"));
|
||||
|
||||
ASSERT_EQUALS("int func1 ( ) ;",
|
||||
tokenizeAndStringify("[[clang::optnone]] [[nodiscard]] int func1();"));
|
||||
}
|
||||
|
||||
void simplifyCaseRange() {
|
||||
|
|
Loading…
Reference in New Issue