Token: Added flag for attribute noreturn (#6328)

This commit is contained in:
Daniel Marjamäki 2014-12-24 12:50:51 +01:00
parent 90bd38a972
commit fb3f5a159d
5 changed files with 47 additions and 9 deletions

View File

@ -1536,6 +1536,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
to->isAttributeDestructor(from->isAttributeDestructor()); to->isAttributeDestructor(from->isAttributeDestructor());
to->isAttributePure(from->isAttributePure()); to->isAttributePure(from->isAttributePure());
to->isAttributeConst(from->isAttributeConst()); to->isAttributeConst(from->isAttributeConst());
to->isAttributeNoreturn(from->isAttributeNoreturn());
to->isAttributeNothrow(from->isAttributeNothrow()); to->isAttributeNothrow(from->isAttributeNothrow());
to->isDeclspecNothrow(from->isDeclspecNothrow()); to->isDeclspecNothrow(from->isDeclspecNothrow());
break; break;
@ -2086,6 +2087,7 @@ void SymbolDatabase::printOut(const char *title) const
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl; std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
std::cout << " isAttributeConst: " << (func->isAttributeConst() ? "true" : "false") << std::endl; std::cout << " isAttributeConst: " << (func->isAttributeConst() ? "true" : "false") << std::endl;
std::cout << " isAttributePure: " << (func->isAttributePure() ? "true" : "false") << std::endl; std::cout << " isAttributePure: " << (func->isAttributePure() ? "true" : "false") << std::endl;
std::cout << " isAttributeNoreturn: " << (func->isAttributeNoreturn() ? "true" : "false") << std::endl;
std::cout << " isAttributeNothrow: " << (func->isAttributeNothrow() ? "true" : "false") << std::endl; std::cout << " isAttributeNothrow: " << (func->isAttributeNothrow() ? "true" : "false") << std::endl;
std::cout << " isDeclspecNothrow: " << (func->isDeclspecNothrow() ? "true" : "false") << std::endl; std::cout << " isDeclspecNothrow: " << (func->isDeclspecNothrow() ? "true" : "false") << std::endl;
std::cout << " noexceptArg: " << (func->noexceptArg ? func->noexceptArg->str() : "none") << std::endl; std::cout << " noexceptArg: " << (func->noexceptArg ? func->noexceptArg->str() : "none") << std::endl;

View File

@ -627,6 +627,9 @@ public:
bool isAttributeConst() const { bool isAttributeConst() const {
return tokenDef->isAttributeConst(); return tokenDef->isAttributeConst();
} }
bool isAttributeNoreturn() const {
return tokenDef->isAttributeNoreturn();
}
bool isAttributeNothrow() const { bool isAttributeNothrow() const {
return tokenDef->isAttributeNothrow(); return tokenDef->isAttributeNothrow();
} }

View File

@ -355,6 +355,12 @@ public:
void isAttributeConst(bool value) { void isAttributeConst(bool value) {
setFlag(fIsAttributeConst, value); setFlag(fIsAttributeConst, value);
} }
bool isAttributeNoreturn() const {
return getFlag(fIsAttributeNoreturn);
}
void isAttributeNoreturn(bool value) {
setFlag(fIsAttributeNoreturn, value);
}
bool isAttributeNothrow() const { bool isAttributeNothrow() const {
return getFlag(fIsAttributeNothrow); return getFlag(fIsAttributeNothrow);
} }
@ -765,9 +771,10 @@ private:
fIsAttributeUnused = (1 << 9), // __attribute__((unused)) fIsAttributeUnused = (1 << 9), // __attribute__((unused))
fIsAttributePure = (1 << 10), // __attribute__((pure)) fIsAttributePure = (1 << 10), // __attribute__((pure))
fIsAttributeConst = (1 << 11), // __attribute__((const)) fIsAttributeConst = (1 << 11), // __attribute__((const))
fIsAttributeNothrow = (1 << 12), // __attribute__((nothrow)) fIsAttributeNoreturn = (1 << 12), // __attribute__((noreturn)) __declspec(noreturn)
fIsDeclspecNothrow = (1 << 13), // __declspec(nothrow) fIsAttributeNothrow = (1 << 13), // __attribute__((nothrow))
fIsAttributeUsed = (1 << 14) // __attribute__((used)) fIsDeclspecNothrow = (1 << 14), // __declspec(nothrow)
fIsAttributeUsed = (1 << 15) // __attribute__((used))
}; };
unsigned int _flags; unsigned int _flags;

View File

@ -9235,13 +9235,16 @@ void Tokenizer::simplifyDeclspec()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
while (Token::simpleMatch(tok, "__declspec (") && tok->next()->link() && tok->next()->link()->next()) { while (Token::simpleMatch(tok, "__declspec (") && tok->next()->link() && tok->next()->link()->next()) {
if (tok->strAt(2) == "nothrow") { if (Token::Match(tok->tokAt(2), "noreturn|nothrow")) {
Token *tok1 = tok->next()->link()->next(); Token *tok1 = tok->next()->link()->next();
while (tok1 && !Token::Match(tok1, "%var%")) { while (tok1 && !Token::Match(tok1, "%var%")) {
tok1 = tok1->next(); tok1 = tok1->next();
} }
if (tok1) { if (tok1) {
tok1->isDeclspecNothrow(true); if (tok->strAt(2) == "noreturn")
tok1->isAttributeNoreturn(true);
else
tok1->isDeclspecNothrow(true);
} }
} else if (tok->strAt(2) == "property") } else if (tok->strAt(2) == "property")
tok->next()->link()->insertToken("__property"); tok->next()->link()->insertToken("__property");
@ -9334,6 +9337,23 @@ void Tokenizer::simplifyAttribute()
tok->next()->link()->next()->isAttributeConst(true); tok->next()->link()->next()->isAttributeConst(true);
} }
else if (Token::Match(tok->tokAt(2), "( noreturn|__noreturn__")) {
// type func(...) __attribute__((noreturn));
if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% ("))
tok->previous()->link()->previous()->isAttributeNoreturn(true);
// type __attribute__((noreturn)) func() { }
else if (Token::Match(tok->next()->link(), ") __attribute__|__attribute (") &&
Token::Match(tok->next()->link()->linkAt(2), ") __attribute__|__attribute (") &&
Token::Match(tok->next()->link()->linkAt(2)->linkAt(2), ") %var% ("))
tok->next()->link()->linkAt(2)->linkAt(2)->next()->isAttributeNoreturn(true);
else if (Token::Match(tok->next()->link(), ") __attribute__|__attribute (") &&
Token::Match(tok->next()->link()->linkAt(2), ") %var% ("))
tok->next()->link()->linkAt(2)->next()->isAttributeNoreturn(true);
else if (Token::Match(tok->next()->link(), ") %var% ("))
tok->next()->link()->next()->isAttributeNoreturn(true);
}
else if (Token::Match(tok->tokAt(2), "( nothrow|__nothrow__")) { else if (Token::Match(tok->tokAt(2), "( nothrow|__nothrow__")) {
// type func(...) __attribute__((nothrow)); // type func(...) __attribute__((nothrow));
if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% (")) if (tok->previous() && tok->previous()->link() && Token::Match(tok->previous()->link()->previous(), "%var% ("))

View File

@ -5121,8 +5121,9 @@ private:
const char code[] = "void __attribute__((pure)) __attribute__((nothrow)) __attribute__((const)) func1();\n" const char code[] = "void __attribute__((pure)) __attribute__((nothrow)) __attribute__((const)) func1();\n"
"void __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__)) func2();\n" "void __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__)) func2();\n"
"void __attribute__((nothrow)) __attribute__((pure)) __attribute__((const)) func3();\n" "void __attribute__((nothrow)) __attribute__((pure)) __attribute__((const)) func3();\n"
"void __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__)) func4();"; "void __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__)) func4();\n"
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ;"; "void __attribute__((noreturn)) func5();";
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;";
errout.str(""); errout.str("");
@ -5140,19 +5141,22 @@ private:
const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2"); const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2");
const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3"); const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3");
const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4"); const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4");
const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5");
ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst()); ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst());
ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst()); ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst());
ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst()); ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst());
ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst()); ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst());
ASSERT(func5 && func5->isAttributeNoreturn());
} }
void functionAttributeAfter() { void functionAttributeAfter() {
const char code[] = "void func1() __attribute__((pure)) __attribute__((nothrow)) __attribute__((const));\n" const char code[] = "void func1() __attribute__((pure)) __attribute__((nothrow)) __attribute__((const));\n"
"void func2() __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__));\n" "void func2() __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__));\n"
"void func3() __attribute__((nothrow)) __attribute__((pure)) __attribute__((const));\n" "void func3() __attribute__((nothrow)) __attribute__((pure)) __attribute__((const));\n"
"void func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));"; "void func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));"
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ;"; "void func5() __attribute__((noreturn));";
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;";
errout.str(""); errout.str("");
@ -5170,11 +5174,13 @@ private:
const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2"); const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2");
const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3"); const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3");
const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4"); const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4");
const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5");
ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst()); ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst());
ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst()); ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst());
ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst()); ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst());
ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst()); ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst());
ASSERT(func5 && func5->isAttributeNoreturn());
} }
void cpp0xtemplate1() { void cpp0xtemplate1() {