diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a5eb147c6..bd6da5090 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -10903,6 +10903,8 @@ void Tokenizer::simplifyAttribute() prev = prev->previous(); if (Token::simpleMatch(prev, ")") && Token::Match(prev->link()->previous(), "%name% (")) functok = prev->link()->previous(); + else if ((!prev || Token::Match(prev, "[;{}*]")) && Token::Match(tok->previous(), "%name%")) + functok = tok->previous(); } for (Token *attr = tok->tokAt(2); attr->str() != ")"; attr = attr->next()) { diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 9e7581502..cadf8a6bb 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4151,9 +4151,9 @@ static void valueFlowForwardAssign(Token* const tok, } static std::list truncateValues(std::list values, - const ValueType* dst, - const ValueType* src, - const Settings* settings) + const ValueType* dst, + const ValueType* src, + const Settings* settings) { if (!dst || !dst->isIntegral()) return values; @@ -4238,7 +4238,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat continue; std::list values = truncateValues( - tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings); + tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings); // Remove known values std::set types; if (tok->astOperand1()->hasKnownValue()) { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index d070185ac..b7c96861e 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -255,7 +255,8 @@ private: TEST_CASE(removedeclspec); TEST_CASE(removeattribute); - TEST_CASE(functionAttributeBefore); + TEST_CASE(functionAttributeBefore1); + TEST_CASE(functionAttributeBefore2); TEST_CASE(functionAttributeAfter); TEST_CASE(functionAttributeListBefore); TEST_CASE(functionAttributeListAfter); @@ -3506,7 +3507,7 @@ private: ASSERT_EQUALS("struct Payload_IR_config { uint8_t tap [ 16 ] ; } ;", tokenizeAndStringify("struct __attribute__((packed, gcc_struct)) Payload_IR_config { uint8_t tap[16]; };")); } - void functionAttributeBefore() { + void functionAttributeBefore1() { 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" @@ -3537,6 +3538,22 @@ private: ASSERT(func5 && func5->isAttributeNoreturn()); } + void functionAttributeBefore2() { + const char code[] = "extern vas_f *VAS_Fail __attribute__((__noreturn__));"; + const char expected[] = "extern vas_f * VAS_Fail ;"; + + errout.str(""); + + // tokenize.. + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); + + const Token * VAS_Fail = Token::findsimplematch(tokenizer.tokens(), "VAS_Fail"); + ASSERT(VAS_Fail && VAS_Fail->isAttributeNoreturn()); + } + void functionAttributeAfter() { const char code[] = "void func1() __attribute__((pure)) __attribute__((nothrow)) __attribute__((const));\n" "void func2() __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__));\n"