Token: Added flag for attribute noreturn (#6328)
This commit is contained in:
parent
90bd38a972
commit
fb3f5a159d
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
13
lib/token.h
13
lib/token.h
|
@ -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;
|
||||||
|
|
|
@ -9235,12 +9235,15 @@ 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) {
|
||||||
|
if (tok->strAt(2) == "noreturn")
|
||||||
|
tok1->isAttributeNoreturn(true);
|
||||||
|
else
|
||||||
tok1->isDeclspecNothrow(true);
|
tok1->isDeclspecNothrow(true);
|
||||||
}
|
}
|
||||||
} else if (tok->strAt(2) == "property")
|
} else if (tok->strAt(2) == "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% ("))
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue