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->isAttributePure(from->isAttributePure());
to->isAttributeConst(from->isAttributeConst());
to->isAttributeNoreturn(from->isAttributeNoreturn());
to->isAttributeNothrow(from->isAttributeNothrow());
to->isDeclspecNothrow(from->isDeclspecNothrow());
break;
@ -2086,6 +2087,7 @@ void SymbolDatabase::printOut(const char *title) const
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
std::cout << " isAttributeConst: " << (func->isAttributeConst() ? "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 << " isDeclspecNothrow: " << (func->isDeclspecNothrow() ? "true" : "false") << std::endl;
std::cout << " noexceptArg: " << (func->noexceptArg ? func->noexceptArg->str() : "none") << std::endl;

View File

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

View File

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

View File

@ -9235,13 +9235,16 @@ void Tokenizer::simplifyDeclspec()
{
for (Token *tok = list.front(); tok; tok = tok->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();
while (tok1 && !Token::Match(tok1, "%var%")) {
tok1 = tok1->next();
}
if (tok1) {
tok1->isDeclspecNothrow(true);
if (tok->strAt(2) == "noreturn")
tok1->isAttributeNoreturn(true);
else
tok1->isDeclspecNothrow(true);
}
} else if (tok->strAt(2) == "property")
tok->next()->link()->insertToken("__property");
@ -9334,6 +9337,23 @@ void Tokenizer::simplifyAttribute()
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__")) {
// type func(...) __attribute__((nothrow));
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"
"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__)) func4();";
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ;";
"void __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__)) func4();\n"
"void __attribute__((noreturn)) func5();";
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;";
errout.str("");
@ -5140,19 +5141,22 @@ private:
const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2");
const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3");
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(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst());
ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst());
ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst());
ASSERT(func5 && func5->isAttributeNoreturn());
}
void functionAttributeAfter() {
const char code[] = "void func1() __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 func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));";
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ;";
"void func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));"
"void func5() __attribute__((noreturn));";
const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;";
errout.str("");
@ -5170,11 +5174,13 @@ private:
const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2");
const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3");
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(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst());
ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst());
ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst());
ASSERT(func5 && func5->isAttributeNoreturn());
}
void cpp0xtemplate1() {