diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 5ff8c9c78..dfcbecaaa 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -169,7 +169,9 @@ void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() // parse this statement and see if the '<' and '>' are matching unsigned int level = 0; - for (const Token *tok2 = tok; tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->next()) { + for (const Token *tok2 = tok; tok2 && !Token::simpleMatch(tok2, ";"); tok2 = tok2->next()) { + if(Token::simpleMatch(tok2, "{") && (!Token::Match(tok2->previous(), ">|%type%") || Token::simpleMatch(tok2->link(), "} ;"))) + break; if (tok2->str() == "(") tok2 = tok2->link(); else if (tok2->str() == "<") { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 9fbfb4b6c..836acfb20 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -476,6 +476,7 @@ private: // Make sure the Tokenizer::findGarbageCode() does not have false positives // The TestGarbage ensures that there are true positives TEST_CASE(findGarbageCode); + TEST_CASE(checkEnableIf); // --check-config TEST_CASE(checkConfiguration); @@ -8648,6 +8649,38 @@ private: } + void checkEnableIf() { + ASSERT_NO_THROW(tokenizeAndStringify( + "template<\n" + " typename U,\n" + " typename std::enable_if<\n" + " std::is_convertible{}>::type* = nullptr>\n" + "void foo(U x);\n")) + + ASSERT_NO_THROW(tokenizeAndStringify( + "template\n" + "T f(const T a, const T b) {\n" + " return a < b ? b : a;\n" + "}\n")) + + ASSERT_NO_THROW(tokenizeAndStringify( + "template\n" + "struct A {\n" + " T f(const T a, const T b) {\n" + " return a < b ? b : a;\n" + " }\n" + "};\n")) + + ASSERT_NO_THROW(tokenizeAndStringify( + "const int a = 1;\n" + "const int b = 2;\n" + "template\n" + "struct A {\n" + " int x = a < b ? b : a;" + "};\n")) + + } + void checkConfig(const char code[]) { errout.str("");