* Fix #8382 (Syntax error when scanning code with template and attribute) This commit only addresses #8382. There are issues concerning which versions of C++ should be supported and also generic C++ 14 attribute support which can be revisited later. * Remove all C++ style attributes. Remove all C++ style attributes when C++ version is 11 or greater. Rename simplify function to simplifyCPPAttributes. Handle more cases of roreturn function attribute.
This commit is contained in:
parent
79be1257ca
commit
fcde1d80e9
|
@ -3583,8 +3583,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
|||
if (_settings->terminated())
|
||||
return false;
|
||||
|
||||
// Remove [[deprecated]]
|
||||
simplifyDeprecated();
|
||||
// Remove [[attribute]]
|
||||
simplifyCPPAttribute();
|
||||
|
||||
// remove __attribute__((?))
|
||||
simplifyAttribute();
|
||||
|
@ -8430,7 +8430,8 @@ void Tokenizer::findGarbageCode() const
|
|||
tok = tok->next()->findClosingBracket();
|
||||
if (!tok)
|
||||
syntaxError(tok1);
|
||||
if (!Token::Match(tok, ">|>> ::| %name%"))
|
||||
if (!Token::Match(tok, ">|>> ::| %name%") &&
|
||||
!Token::Match(tok, ">|>> [ [ %name%"))
|
||||
syntaxError(tok->next() ? tok->next() : tok1);
|
||||
}
|
||||
}
|
||||
|
@ -8915,6 +8916,26 @@ void Tokenizer::simplifyAttribute()
|
|||
}
|
||||
}
|
||||
|
||||
void Tokenizer::simplifyCPPAttribute()
|
||||
{
|
||||
if (_settings->standards.cpp < Standards::CPP11 || isC())
|
||||
return;
|
||||
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (tok->link() && Token::Match(tok, "[ [ %name%")) {
|
||||
if (tok->strAt(2) == "noreturn") {
|
||||
const Token * head = tok->tokAt(5);
|
||||
while (Token::Match(head, "%name%|::|*|&"))
|
||||
head = head->next();
|
||||
if (head && isFunctionHead(head, "{|;"))
|
||||
head->previous()->isAttributeNoreturn(true);
|
||||
}
|
||||
Token::eraseTokens(tok, tok->link()->next());
|
||||
tok->deleteThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const std::set<std::string> keywords = make_container< std::set<std::string> >()
|
||||
<< "volatile"
|
||||
<< "inline"
|
||||
|
@ -9811,19 +9832,6 @@ void Tokenizer::removeUnnecessaryQualification()
|
|||
}
|
||||
}
|
||||
|
||||
void Tokenizer::simplifyDeprecated()
|
||||
{
|
||||
if (_settings->standards.cpp != Standards::CPP11 || isC())
|
||||
return; // It is actually a C++14 feature, however, there seems to be nothing dangerous about removing it for C++11 as well
|
||||
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (tok->link() && Token::simpleMatch(tok, "[ [ deprecated")) {
|
||||
Token::eraseTokens(tok, tok->link()->next());
|
||||
tok->deleteThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tokenizer::simplifyReturnStrncat()
|
||||
{
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
|
|
|
@ -671,9 +671,9 @@ private:
|
|||
void simplifyOperatorName();
|
||||
|
||||
/**
|
||||
* Remove [[deprecated]] (C++14) from TokenList
|
||||
* Remove [[attribute]] (C++11 and later) from TokenList
|
||||
*/
|
||||
void simplifyDeprecated();
|
||||
void simplifyCPPAttribute();
|
||||
|
||||
/**
|
||||
* Replace strlen(str)
|
||||
|
|
|
@ -316,6 +316,8 @@ private:
|
|||
TEST_CASE(nothrowAttributeFunction);
|
||||
TEST_CASE(nothrowDeclspecFunction);
|
||||
|
||||
TEST_CASE(noreturnAttributeFunction);
|
||||
|
||||
TEST_CASE(varTypesIntegral); // known integral
|
||||
TEST_CASE(varTypesFloating); // known floating
|
||||
TEST_CASE(varTypesOther); // (un)known
|
||||
|
@ -4115,6 +4117,35 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void noreturnAttributeFunction() {
|
||||
GET_SYMBOL_DB("[[noreturn]] void func1();\n"
|
||||
"void func1() { }\n"
|
||||
"[[noreturn]] void func2();\n"
|
||||
"[[noreturn]] void func3() { }\n"
|
||||
"template <class T> [[noreturn]] void func4() { }");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS(true, db != nullptr); // not null
|
||||
|
||||
if (db) {
|
||||
const Function *func = findFunctionByName("func1", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
if (func)
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
func = findFunctionByName("func2", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
if (func)
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
func = findFunctionByName("func3", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
if (func)
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
func = findFunctionByName("func4", &db->scopeList.front());
|
||||
ASSERT_EQUALS(true, func != nullptr);
|
||||
if (func)
|
||||
ASSERT_EQUALS(true, func->isAttributeNoreturn());
|
||||
}
|
||||
}
|
||||
|
||||
void varTypesIntegral() {
|
||||
GET_SYMBOL_DB("void f() { bool b; char c; unsigned char uc; short s; unsigned short us; int i; unsigned u; unsigned int ui; long l; unsigned long ul; long long ll; }");
|
||||
const Variable *b = db->getVariableFromVarId(1);
|
||||
|
|
|
@ -440,7 +440,7 @@ private:
|
|||
TEST_CASE(simplifyMathExpressions); //ticket #1620
|
||||
TEST_CASE(simplifyStaticConst);
|
||||
|
||||
TEST_CASE(simplifyDeprecated);
|
||||
TEST_CASE(simplifyCPPAttribute);
|
||||
|
||||
TEST_CASE(simplifyCaseRange);
|
||||
|
||||
|
@ -7972,7 +7972,7 @@ private:
|
|||
ASSERT_EQUALS(expected3, tokenizeAndStringify(code3, true));
|
||||
}
|
||||
|
||||
void simplifyDeprecated() {
|
||||
void simplifyCPPAttribute() {
|
||||
ASSERT_EQUALS("int f ( ) ;",
|
||||
tokenizeAndStringify("[[deprecated]] int f();", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
|
@ -7981,6 +7981,18 @@ private:
|
|||
|
||||
ASSERT_EQUALS("[ [ deprecated ] ] int f ( ) ;",
|
||||
tokenizeAndStringify("[[deprecated]] int f();", false, true, Settings::Native, "test.c", true));
|
||||
|
||||
ASSERT_EQUALS("template < class T > int f ( ) { }",
|
||||
tokenizeAndStringify("template <class T> [[noreturn]] int f(){}", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("template < class T > [ [ noreturn ] ] int f ( ) { }",
|
||||
tokenizeAndStringify("template <class T> [[noreturn]] int f(){}", false, true, Settings::Native, "test.cpp", false));
|
||||
ASSERT_EQUALS("int f ( int i ) ;",
|
||||
tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", false, true, Settings::Native, "test.cpp", true));
|
||||
|
||||
ASSERT_EQUALS("[ [ maybe_unused ] ] int f ( [ [ maybe_unused ] ] int i ) ;",
|
||||
tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", false, true, Settings::Native, "test.cpp", false));
|
||||
|
||||
}
|
||||
|
||||
void simplifyCaseRange() {
|
||||
|
|
Loading…
Reference in New Issue