From e69733bf2beab97b192e8c02cfb404b3ee78e2c6 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Tue, 25 Aug 2026 20:35:56 +0200 Subject: [PATCH 1/2] Partial fix for #14982 internalAstError for function with std::enable_if --- lib/tokenize.cpp | 2 ++ test/testtokenize.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index b22658db28c..3aa1360e27f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5647,6 +5647,8 @@ void Tokenizer::createLinks2() const Token* end = type.top()->findClosingBracket(); if (Token::Match(end, "> %comp%|;|.|=|{|}|(|)|::")) break; + if (Token::Match(end, "> %name% (")) + break; // Variable declaration if (Token::Match(end, "> %var% ;") && (type.top()->tokAt(-2) == nullptr || Token::Match(type.top()->tokAt(-2), ";|}|{"))) break; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 600d457e944..a00b0492981 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -3933,6 +3933,16 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); } + + { + const char code[] = "std::enable_if_t<0 || 1, void> f() {}\n"; // #14982 + SimpleTokenizer tokenizer(settingsDefault, *this); + ASSERT(tokenizer.tokenize(code)); + const Token* tok1 = Token::findsimplematch(tokenizer.tokens(), "< 0"); + const Token* tok2 = Token::findsimplematch(tok1, "> f"); + ASSERT_EQUALS(true, tok1->link() == tok2); + ASSERT_EQUALS(true, tok2->link() == tok1); + } } void simplifyString() { From 3cf97d0fed6b93abe836fbad4b51426dace016cc Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Tue, 25 Aug 2026 22:40:02 +0200 Subject: [PATCH 2/2] Handle scoped function --- lib/tokenize.cpp | 2 +- test/testtokenize.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 3aa1360e27f..19970e19a4b 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5647,7 +5647,7 @@ void Tokenizer::createLinks2() const Token* end = type.top()->findClosingBracket(); if (Token::Match(end, "> %comp%|;|.|=|{|}|(|)|::")) break; - if (Token::Match(end, "> %name% (")) + if (Token::Match(end, "> %name% (|::")) break; // Variable declaration if (Token::Match(end, "> %var% ;") && (type.top()->tokAt(-2) == nullptr || Token::Match(type.top()->tokAt(-2), ";|}|{"))) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a00b0492981..95f2ac8e8a4 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -3935,13 +3935,18 @@ class TestTokenizer : public TestFixture { } { - const char code[] = "std::enable_if_t<0 || 1, void> f() {}\n"; // #14982 + const char code[] = "std::enable_if_t<0 || 1, void> f() {}\n" // #14982 + "std::enable_if_t<0 || 1, void> S::g() {}\n"; SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT(tokenizer.tokenize(code)); const Token* tok1 = Token::findsimplematch(tokenizer.tokens(), "< 0"); const Token* tok2 = Token::findsimplematch(tok1, "> f"); ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); + const Token* tok3 = Token::findsimplematch(tok2, "< 0"); + const Token* tok4 = Token::findsimplematch(tok3, "> S"); + ASSERT_EQUALS(true, tok3->link() == tok4); + ASSERT_EQUALS(true, tok4->link() == tok3); } }