From 2ebe4cc42a48d595250e225429f1ee09ccc0cf0d Mon Sep 17 00:00:00 2001 From: Leander Schulten Date: Wed, 15 Jul 2026 16:59:04 +0200 Subject: [PATCH] Fix #11538: Fix syntax error on C++23 'if consteval' / 'if !consteval' The tokenizer only recognized 'if constexpr (...)' and treated any other 'if ' without parentheses as a syntax error, so C++23's 'if consteval { ... }' and 'if !consteval { ... }' were rejected. Rewrite them to 'if ( __cppcheck_consteval__ ) { ... }' and 'if ( ! __cppcheck_consteval__ ) { ... }' respectively, using a synthetic unresolved symbol rather than a boolean literal so that valueflow can't treat the condition as always true/false. --- lib/tokenize.cpp | 17 ++++++++++++++++- test/testtokenize.cpp | 13 +++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 3dc83082e4e..10d702d2558 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5721,7 +5721,22 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) // if MACRO for (Token *tok = list.front(); tok; tok = tok->next()) { - if (Token::Match(tok, "if|for|while %name% (")) { + if (Token::simpleMatch(tok, "if consteval {")) { + // 'if consteval { ... }' -> 'if ( __cppcheck_consteval__ ) { ... }' + Token *parTok = tok->next(); + parTok->str("("); + Token *evalTok = parTok->insertToken("__cppcheck_consteval__"); + evalTok->originalName("consteval"); + evalTok->insertToken(")"); + } else if (Token::simpleMatch(tok, "if ! consteval {")) { + // 'if !consteval { ... }' -> 'if ( ! __cppcheck_consteval__ ) { ... }' + Token *notTok = tok->next(); + notTok->insertTokenBefore("("); + Token *evalTok = notTok->next(); + evalTok->str("__cppcheck_consteval__"); + evalTok->originalName("consteval"); + evalTok->insertToken(")"); + } else if (Token::Match(tok, "if|for|while %name% (")) { if (Token::simpleMatch(tok, "for each")) { // 'for each (x in y )' -> 'for (x : y)' if (Token* in = Token::findsimplematch(tok->tokAt(2), "in", tok->linkAt(2))) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f1a2a85e212..db72bcc33f3 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -104,6 +104,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(foreach); // #3690 TEST_CASE(ifconstexpr); + TEST_CASE(ifconsteval); TEST_CASE(combineOperators); @@ -1042,6 +1043,18 @@ class TestTokenizer : public TestFixture { filter_valueflow(errout_str())); } + void ifconsteval() { + ASSERT_EQUALS("void f ( ) { if ( __cppcheck_consteval__ ) { bar ( ) ; } }", tokenizeAndStringify("void f() { if consteval { bar(); } }")); + filter_valueflow(errout_str()); + + ASSERT_EQUALS("void f ( ) { if ( ! __cppcheck_consteval__ ) { bar ( ) ; } }", tokenizeAndStringify("void f() { if !consteval { bar(); } }")); + filter_valueflow(errout_str()); + + ASSERT_EQUALS("void f ( ) { if ( __cppcheck_consteval__ ) { bar ( ) ; } else { baz ( ) ; } }", + tokenizeAndStringify("void f() { if consteval { bar(); } else { baz(); } }")); + filter_valueflow(errout_str()); + } + void combineOperators() { ASSERT_EQUALS("; private: ;", tokenizeAndStringify(";private:;")); ASSERT_EQUALS("; protected: ;", tokenizeAndStringify(";protected:;"));