Skip to content

Commit 663d816

Browse files
autoantwortclaude
andcommitted
Fix #15079 FP syntaxError for C-style cast before scope operator
The check added in a294079 (#15060) reports every `)` followed by `::` unless the `(` belongs to a control flow keyword or decltype. That also rejects valid code like `(HWND)::SendMessage(...)` or placement new `new (p) ::N::T`, so whole translation units are skipped. Only report when the parenthesis follows a non-keyword name, which is the unknown macro case the check was added for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent fa6c1f1 commit 663d816

2 files changed

Lines changed: 20 additions & 2 deletions

File tree

‎lib/tokenize.cpp‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9177,9 +9177,11 @@ void Tokenizer::findGarbageCode() const
91779177
if (!Token::Match(tok->next(), "%name%|*|~") || (tok->next()->isKeyword() && !Token::Match(tok->next(), "new|delete|operator")))
91789178
syntaxError(tok);
91799179
if (Token::simpleMatch(tok->tokAt(-1), ")")) {
9180+
// NAME(...):: => NAME is most likely an unknown macro
9181+
// other cases are valid, e.g. (void)::f(), return (T)::x, new (p) ::T, decltype(x)::type
91809182
const Token* const prev = tok->linkAt(-1)->tokAt(-1);
9181-
if (!Token::Match(prev, "%name% (") || (!prev->isControlFlowKeyword() && prev->str() != "decltype")) {
9182-
if (prev && prev->isUpperCaseName())
9183+
if (Token::Match(prev, "%name% (") && !prev->isKeyword()) {
9184+
if (prev->isUpperCaseName())
91839185
unknownMacroError(prev);
91849186
else
91859187
syntaxError(tok);

‎test/testtokenize.cpp‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8135,6 +8135,22 @@ class TestTokenizer : public TestFixture {
81358135
" *p = -*p;\n"
81368136
"}\n"));
81378137

8138+
ASSERT_NO_THROW(tokenizeAndStringify("void f(void* h) {\n" // cast before global scope operator
8139+
" (void)::CloseHandle(h);\n"
8140+
" int i = (int)::GetTickCount();\n"
8141+
" g((unsigned char)::toupper(i));\n"
8142+
"}\n"));
8143+
ASSERT_NO_THROW(tokenizeAndStringify("int f(int i) {\n"
8144+
" return (int)::abs(i);\n"
8145+
"}\n"));
8146+
ASSERT_NO_THROW(tokenizeAndStringify("namespace N { struct T {}; }\n"
8147+
"void f(void* p) {\n"
8148+
" new (p) ::N::T;\n"
8149+
"}\n"));
8150+
ASSERT_NO_THROW(tokenizeAndStringify("struct S { using type = int; };\n"
8151+
"S s;\n"
8152+
"decltype(s)::type i;\n"));
8153+
81388154
ignore_errout();
81398155

81408156
ASSERT_EQUALS(";", tokenizeAndStringify("typedef std::size_t size_t;\n")); // #14809

0 commit comments

Comments
 (0)