From fb3f5a159dd386db26e2a50a5618f948ad5d2b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 24 Dec 2014 12:50:51 +0100 Subject: [PATCH] Token: Added flag for attribute noreturn (#6328) --- lib/symboldatabase.cpp | 2 ++ lib/symboldatabase.h | 3 +++ lib/token.h | 13 ++++++++++--- lib/tokenize.cpp | 24 ++++++++++++++++++++++-- test/testtokenize.cpp | 14 ++++++++++---- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 2b52fa3c2..fc33cb190 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index c04e66946..0d5ed41f5 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -627,6 +627,9 @@ public: bool isAttributeConst() const { return tokenDef->isAttributeConst(); } + bool isAttributeNoreturn() const { + return tokenDef->isAttributeNoreturn(); + } bool isAttributeNothrow() const { return tokenDef->isAttributeNothrow(); } diff --git a/lib/token.h b/lib/token.h index 089a043b4..e4a512aaa 100644 --- a/lib/token.h +++ b/lib/token.h @@ -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; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6420410cf..f5ea5b587 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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% (")) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3ea94d15a..a5d6653d1 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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() {