diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5e58e06c5..0856fb84d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1712,8 +1712,11 @@ void Tokenizer::simplifyTypedef() tok2 = tok2->linkAt(1); // skip over const/noexcept - while (Token::Match(tok2->next(), "const|noexcept")) + while (Token::Match(tok2->next(), "const|noexcept")) { tok2 = tok2->next(); + if (Token::Match(tok2->next(), "( true|false )")) + tok2 = tok2->tokAt(3); + } tok2->insertToken(")"); tok2 = tok2->next(); @@ -6431,11 +6434,15 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co tok2 = nullptr; } - // parenthesis, functions can't be declared like: - // int f1(a,b), f2(c,d); - // so if there is a comma assume this is a variable declaration - else if (Token::Match(varName, "%name% (") && Token::simpleMatch(varName->linkAt(1), ") ,")) { - tok2 = varName->linkAt(1)->next(); + // function declaration + else if (Token::Match(varName, "%name% (")) { + Token* commaTok = varName->linkAt(1)->next(); + while (Token::Match(commaTok, "const|noexcept|override|final")) { + commaTok = commaTok->next(); + if (Token::Match(commaTok, "( true|false )")) + commaTok = commaTok->link()->next(); + } + tok2 = Token::simpleMatch(commaTok, ",") ? commaTok : nullptr; } else @@ -8424,10 +8431,12 @@ void Tokenizer::simplifyKeyword() // noexcept -> noexcept(true) // 2) void f() noexcept; -> void f() noexcept(true); - else if (Token::Match(tok, ") noexcept :|{|;|const|override|final")) { + else if (Token::Match(tok, ") const|override|final| noexcept :|{|;|,|const|override|final")) { // Insertion is done in inverse order // The brackets are linked together accordingly afterwards - Token * tokNoExcept = tok->next(); + Token* tokNoExcept = tok->next(); + while (tokNoExcept->str() != "noexcept") + tokNoExcept = tokNoExcept->next(); tokNoExcept->insertToken(")"); Token * braceEnd = tokNoExcept->next(); tokNoExcept->insertToken("true"); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index c80ada3fc..55f6a5b4b 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -2622,7 +2622,7 @@ private: " constexpr const foo &c_str() const noexcept { return _a; }\n" "};"; - const char exp[] = "class c { char _a [ 4 ] ; const constexpr char ( & c_str ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const constexpr char ( & c_str ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2633,8 +2633,8 @@ private: " constexpr operator foo &() const noexcept { return _a; }\n" "};"; - const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; - const char exp[] = "class c { char _a [ 4 ] ; const operator char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorchar ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const operator char ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); } @@ -2645,8 +2645,8 @@ private: " constexpr operator const foo &() const noexcept { return _a; }\n" "};"; - const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorconstchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; - const char exp[] = "class c { char _a [ 4 ] ; const operator const char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorconstchar ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const operator const char ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); } } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 71645981b..e5c74d0d6 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -4370,7 +4370,7 @@ private: "struct Foo : Bar {\n" " virtual std::string get_endpoint_url() const noexcept override final;\n" "};"); - const Token *f = db ? Token::findsimplematch(tokenizer.tokens(), "get_endpoint_url ( ) const noexcept ;") : nullptr; + const Token *f = db ? Token::findsimplematch(tokenizer.tokens(), "get_endpoint_url ( ) const noexcept ( true ) ;") : nullptr; ASSERT(f != nullptr); ASSERT(f && f->function() && f->function()->token->linenr() == 2); ASSERT(f && f->function() && f->function()->hasVirtualSpecifier()); @@ -4378,7 +4378,7 @@ private: ASSERT(f && f->function() && !f->function()->hasFinalSpecifier()); ASSERT(f && f->function() && f->function()->isConst()); ASSERT(f && f->function() && f->function()->isNoExcept()); - f = db ? Token::findsimplematch(tokenizer.tokens(), "get_endpoint_url ( ) const noexcept override final ;") : nullptr; + f = db ? Token::findsimplematch(tokenizer.tokens(), "get_endpoint_url ( ) const noexcept ( true ) override final ;") : nullptr; ASSERT(f != nullptr); ASSERT(f && f->function() && f->function()->token->linenr() == 5); ASSERT(f && f->function() && f->function()->hasVirtualSpecifier()); @@ -6731,7 +6731,7 @@ private: " return nullptr;\n" "}"); ASSERT_EQUALS("", errout.str()); - const Token *functok = Token::findsimplematch(tokenizer.tokens(), "what ( ) const noexcept {"); + const Token *functok = Token::findsimplematch(tokenizer.tokens(), "what ( ) const noexcept ( true ) {"); ASSERT(functok); ASSERT(functok->function()); ASSERT(functok->function()->name() == "what"); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 2ad35e85f..42bc016d4 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -217,6 +217,7 @@ private: TEST_CASE(vardecl26); // #5907 - incorrect handling of extern declarations TEST_CASE(vardecl27); // #7850 - crash on valid C code TEST_CASE(vardecl28); + TEST_CASE(vardecl29); // #9282 TEST_CASE(vardecl_stl_1); TEST_CASE(vardecl_stl_2); TEST_CASE(vardecl_stl_3); @@ -2492,6 +2493,20 @@ private: tokenizeAndStringify(code, /*expand=*/ true, Settings::Native, "test.c")); } + void vardecl29() { // #9282 + const char* code = "double f1() noexcept, f2(double) noexcept;"; + ASSERT_EQUALS("double f1 ( ) noexcept ( true ) ; double f2 ( double ) noexcept ( true ) ;", + tokenizeAndStringify(code)); + + code = "class C {\n" + " double f1() const noexcept, f2 (double) const noexcept;\n" + "};\n"; + ASSERT_EQUALS("class C {\n" + "double f1 ( ) const noexcept ( true ) ; double f2 ( double ) const noexcept ( true ) ;\n" + "} ;", + tokenizeAndStringify(code)); + } + void volatile_variables() { { const char code[] = "volatile int a=0;\n" @@ -4931,7 +4946,7 @@ private: ASSERT_EQUALS(result3, tokenizeAndStringify(code3)); const char code4[] = "value_type * operator += (int) const noexcept ;"; - const char result4[] = "value_type * operator+= ( int ) const noexcept ;"; + const char result4[] = "value_type * operator+= ( int ) const noexcept ( true ) ;"; ASSERT_EQUALS(result4, tokenizeAndStringify(code4)); const char code5[] = "value_type * operator += (int) const noexcept ( true ) ;"; diff --git a/test/testunusedprivfunc.cpp b/test/testunusedprivfunc.cpp index 7176f1a2b..a3774b7e8 100644 --- a/test/testunusedprivfunc.cpp +++ b/test/testunusedprivfunc.cpp @@ -47,6 +47,7 @@ private: TEST_CASE(test4); TEST_CASE(test5); TEST_CASE(test6); // ticket #2602 + TEST_CASE(test7); // ticket #9282 // [ 2236547 ] False positive --style unused function, called via pointer TEST_CASE(func_pointer1); @@ -251,6 +252,16 @@ private: ASSERT_EQUALS("", errout.str()); } + void test7() { // ticket #9282 + check("class C {\n" + " double f1() const noexcept, f2(double) const noexcept;\n" + " void f3() const noexcept;\n" + "};\n" + "double C::f1() const noexcept { f3(); }\n" + "void C::f3() const noexcept {}\n"); + ASSERT_EQUALS("", errout.str()); + } +