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())
|
if (mSettings->standards.cpp < Standards::CPP11 || isC())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok;) {
|
||||||
if (!isCPPAttribute(tok) && !isAlignAttribute(tok)) {
|
if (!isCPPAttribute(tok) && !isAlignAttribute(tok)) {
|
||||||
|
tok = tok->next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isCPPAttribute(tok)) {
|
if (isCPPAttribute(tok)) {
|
||||||
if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
|
if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
|
||||||
Token * head = skipCPPOrAlignAttribute(tok);
|
Token * head = skipCPPOrAlignAttribute(tok)->next();
|
||||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||||
head = skipCPPOrAlignAttribute(head);
|
head = skipCPPOrAlignAttribute(head)->next();
|
||||||
head = head->next();
|
|
||||||
while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type
|
while (Token::Match(head, "%name%|::|*|&|<|>|,")) // skip return type
|
||||||
head = head->next();
|
head = head->next();
|
||||||
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
||||||
head->previous()->isAttributeNoreturn(true);
|
head->previous()->isAttributeNoreturn(true);
|
||||||
}
|
}
|
||||||
} else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) {
|
} else if (Token::findsimplematch(tok->tokAt(2), "nodiscard", tok->link())) {
|
||||||
Token * head = skipCPPOrAlignAttribute(tok);
|
Token * head = skipCPPOrAlignAttribute(tok)->next();
|
||||||
while (isCPPAttribute(head) || isAlignAttribute(head))
|
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||||
head = skipCPPOrAlignAttribute(head);
|
head = skipCPPOrAlignAttribute(head)->next();
|
||||||
head = head->next();
|
|
||||||
while (Token::Match(head, "%name%|::|*|&|<|>|,"))
|
while (Token::Match(head, "%name%|::|*|&|<|>|,"))
|
||||||
head = head->next();
|
head = head->next();
|
||||||
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
if (head && head->str() == "(" && isFunctionHead(head, "{|;")) {
|
||||||
head->previous()->isAttributeNodiscard(true);
|
head->previous()->isAttributeNodiscard(true);
|
||||||
}
|
}
|
||||||
} else if (Token::findsimplematch(tok->tokAt(2), "maybe_unused", tok->link())) {
|
} 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))
|
while (isCPPAttribute(head) || isAlignAttribute(head))
|
||||||
head = skipCPPOrAlignAttribute(head);
|
head = skipCPPOrAlignAttribute(head)->next();
|
||||||
head->next()->isAttributeMaybeUnused(true);
|
head->isAttributeMaybeUnused(true);
|
||||||
} else if (Token::Match(tok->previous(), ") [ [ expects|ensures|assert default|audit|axiom| : %name% <|<=|>|>= %num% ] ]")) {
|
} else if (Token::Match(tok->previous(), ") [ [ expects|ensures|assert default|audit|axiom| : %name% <|<=|>|>= %num% ] ]")) {
|
||||||
const Token *vartok = tok->tokAt(4);
|
const Token *vartok = tok->tokAt(4);
|
||||||
if (vartok->str() == ":")
|
if (vartok->str() == ":")
|
||||||
|
@ -8884,14 +8883,7 @@ void Tokenizer::simplifyCPPAttribute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::eraseTokens(tok, skipCPPOrAlignAttribute(tok)->next());
|
Token::eraseTokens(tok, skipCPPOrAlignAttribute(tok)->next());
|
||||||
// fix iterator after removing
|
tok->deleteThis();
|
||||||
if (tok->previous()) {
|
|
||||||
tok = tok->previous();
|
|
||||||
tok->next()->deleteThis();
|
|
||||||
} else {
|
|
||||||
tok->deleteThis();
|
|
||||||
tok = list.front();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7408,7 +7408,10 @@ private:
|
||||||
"void func1() { }\n"
|
"void func1() { }\n"
|
||||||
"[[noreturn]] void func2();\n"
|
"[[noreturn]] void func2();\n"
|
||||||
"[[noreturn]] void func3() { }\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("", errout.str());
|
||||||
ASSERT_EQUALS(true, db != nullptr); // not null
|
ASSERT_EQUALS(true, db != nullptr); // not null
|
||||||
|
|
||||||
|
@ -7428,6 +7431,14 @@ private:
|
||||||
ASSERT_EQUALS(true, func != nullptr);
|
ASSERT_EQUALS(true, func != nullptr);
|
||||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
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() {
|
void nodiscardAttributeFunction() {
|
||||||
|
|
|
@ -5691,6 +5691,24 @@ private:
|
||||||
|
|
||||||
ASSERT_EQUALS("struct a ;",
|
ASSERT_EQUALS("struct a ;",
|
||||||
tokenizeAndStringify("struct [[deprecated,maybe_unused]] alignas(double) [[trivial_abi]] 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() {
|
void simplifyCaseRange() {
|
||||||
|
|
Loading…
Reference in New Issue