Skip to content

Commit fb3f5a1

Browse files
committed
Token: Added flag for attribute noreturn (danmar#6328)
1 parent 90bd38a commit fb3f5a1

File tree

5 files changed

+47
-9
lines changed

5 files changed

+47
-9
lines changed

lib/symboldatabase.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
15361536
to->isAttributeDestructor(from->isAttributeDestructor());
15371537
to->isAttributePure(from->isAttributePure());
15381538
to->isAttributeConst(from->isAttributeConst());
1539+
to->isAttributeNoreturn(from->isAttributeNoreturn());
15391540
to->isAttributeNothrow(from->isAttributeNothrow());
15401541
to->isDeclspecNothrow(from->isDeclspecNothrow());
15411542
break;
@@ -2086,6 +2087,7 @@ void SymbolDatabase::printOut(const char *title) const
20862087
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
20872088
std::cout << " isAttributeConst: " << (func->isAttributeConst() ? "true" : "false") << std::endl;
20882089
std::cout << " isAttributePure: " << (func->isAttributePure() ? "true" : "false") << std::endl;
2090+
std::cout << " isAttributeNoreturn: " << (func->isAttributeNoreturn() ? "true" : "false") << std::endl;
20892091
std::cout << " isAttributeNothrow: " << (func->isAttributeNothrow() ? "true" : "false") << std::endl;
20902092
std::cout << " isDeclspecNothrow: " << (func->isDeclspecNothrow() ? "true" : "false") << std::endl;
20912093
std::cout << " noexceptArg: " << (func->noexceptArg ? func->noexceptArg->str() : "none") << std::endl;

lib/symboldatabase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,9 @@ class CPPCHECKLIB Function {
627627
bool isAttributeConst() const {
628628
return tokenDef->isAttributeConst();
629629
}
630+
bool isAttributeNoreturn() const {
631+
return tokenDef->isAttributeNoreturn();
632+
}
630633
bool isAttributeNothrow() const {
631634
return tokenDef->isAttributeNothrow();
632635
}

lib/token.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,12 @@ class CPPCHECKLIB Token {
355355
void isAttributeConst(bool value) {
356356
setFlag(fIsAttributeConst, value);
357357
}
358+
bool isAttributeNoreturn() const {
359+
return getFlag(fIsAttributeNoreturn);
360+
}
361+
void isAttributeNoreturn(bool value) {
362+
setFlag(fIsAttributeNoreturn, value);
363+
}
358364
bool isAttributeNothrow() const {
359365
return getFlag(fIsAttributeNothrow);
360366
}
@@ -765,9 +771,10 @@ class CPPCHECKLIB Token {
765771
fIsAttributeUnused = (1 << 9), // __attribute__((unused))
766772
fIsAttributePure = (1 << 10), // __attribute__((pure))
767773
fIsAttributeConst = (1 << 11), // __attribute__((const))
768-
fIsAttributeNothrow = (1 << 12), // __attribute__((nothrow))
769-
fIsDeclspecNothrow = (1 << 13), // __declspec(nothrow)
770-
fIsAttributeUsed = (1 << 14) // __attribute__((used))
774+
fIsAttributeNoreturn = (1 << 12), // __attribute__((noreturn)) __declspec(noreturn)
775+
fIsAttributeNothrow = (1 << 13), // __attribute__((nothrow))
776+
fIsDeclspecNothrow = (1 << 14), // __declspec(nothrow)
777+
fIsAttributeUsed = (1 << 15) // __attribute__((used))
771778
};
772779

773780
unsigned int _flags;

lib/tokenize.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9235,13 +9235,16 @@ void Tokenizer::simplifyDeclspec()
92359235
{
92369236
for (Token *tok = list.front(); tok; tok = tok->next()) {
92379237
while (Token::simpleMatch(tok, "__declspec (") && tok->next()->link() && tok->next()->link()->next()) {
9238-
if (tok->strAt(2) == "nothrow") {
9238+
if (Token::Match(tok->tokAt(2), "noreturn|nothrow")) {
92399239
Token *tok1 = tok->next()->link()->next();
92409240
while (tok1 && !Token::Match(tok1, "%var%")) {
92419241
tok1 = tok1->next();
92429242
}
92439243
if (tok1) {
9244-
tok1->isDeclspecNothrow(true);
9244+
if (tok->strAt(2) == "noreturn")
9245+
tok1->isAttributeNoreturn(true);
9246+
else
9247+
tok1->isDeclspecNothrow(true);
92459248
}
92469249
} else if (tok->strAt(2) == "property")
92479250
tok->next()->link()->insertToken("__property");
@@ -9334,6 +9337,23 @@ void Tokenizer::simplifyAttribute()
93349337
tok->next()->link()->next()->isAttributeConst(true);
93359338
}
93369339

9340+
else if (Token::Match(tok->tokAt(2), "( noreturn|__noreturn__")) {
9341+
// type func(...) __attribute__((noreturn));
9342+
if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% ("))
9343+
tok->previous()->link()->previous()->isAttributeNoreturn(true);
9344+
9345+
// type __attribute__((noreturn)) func() { }
9346+
else if (Token::Match(tok->next()->link(), ") __attribute__|__attribute (") &&
9347+
Token::Match(tok->next()->link()->linkAt(2), ") __attribute__|__attribute (") &&
9348+
Token::Match(tok->next()->link()->linkAt(2)->linkAt(2), ") %var% ("))
9349+
tok->next()->link()->linkAt(2)->linkAt(2)->next()->isAttributeNoreturn(true);
9350+
else if (Token::Match(tok->next()->link(), ") __attribute__|__attribute (") &&
9351+
Token::Match(tok->next()->link()->linkAt(2), ") %var% ("))
9352+
tok->next()->link()->linkAt(2)->next()->isAttributeNoreturn(true);
9353+
else if (Token::Match(tok->next()->link(), ") %var% ("))
9354+
tok->next()->link()->next()->isAttributeNoreturn(true);
9355+
}
9356+
93379357
else if (Token::Match(tok->tokAt(2), "( nothrow|__nothrow__")) {
93389358
// type func(...) __attribute__((nothrow));
93399359
if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% ("))

test/testtokenize.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5121,8 +5121,9 @@ class TestTokenizer : public TestFixture {
51215121
const char code[] = "void __attribute__((pure)) __attribute__((nothrow)) __attribute__((const)) func1();\n"
51225122
"void __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__)) func2();\n"
51235123
"void __attribute__((nothrow)) __attribute__((pure)) __attribute__((const)) func3();\n"
5124-
"void __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__)) func4();";
5125-
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ;";
5124+
"void __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__)) func4();\n"
5125+
"void __attribute__((noreturn)) func5();";
5126+
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;";
51265127

51275128
errout.str("");
51285129

@@ -5140,19 +5141,22 @@ class TestTokenizer : public TestFixture {
51405141
const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2");
51415142
const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3");
51425143
const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4");
5144+
const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5");
51435145

51445146
ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst());
51455147
ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst());
51465148
ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst());
51475149
ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst());
5150+
ASSERT(func5 && func5->isAttributeNoreturn());
51485151
}
51495152

51505153
void functionAttributeAfter() {
51515154
const char code[] = "void func1() __attribute__((pure)) __attribute__((nothrow)) __attribute__((const));\n"
51525155
"void func2() __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__));\n"
51535156
"void func3() __attribute__((nothrow)) __attribute__((pure)) __attribute__((const));\n"
5154-
"void func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));";
5155-
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ;";
5157+
"void func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));"
5158+
"void func5() __attribute__((noreturn));";
5159+
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;";
51565160

51575161
errout.str("");
51585162

@@ -5170,11 +5174,13 @@ class TestTokenizer : public TestFixture {
51705174
const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2");
51715175
const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3");
51725176
const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4");
5177+
const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5");
51735178

51745179
ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst());
51755180
ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst());
51765181
ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst());
51775182
ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst());
5183+
ASSERT(func5 && func5->isAttributeNoreturn());
51785184
}
51795185

51805186
void cpp0xtemplate1() {

0 commit comments

Comments
 (0)