Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9177,9 +9177,11 @@ void Tokenizer::findGarbageCode() const
if (!Token::Match(tok->next(), "%name%|*|~") || (tok->next()->isKeyword() && !Token::Match(tok->next(), "new|delete|operator")))
syntaxError(tok);
if (Token::simpleMatch(tok->tokAt(-1), ")")) {
// NAME(...):: => NAME is most likely an unknown macro
// other cases are valid, e.g. (void)::f(), return (T)::x, new (p) ::T, decltype(x)::type
const Token* const prev = tok->linkAt(-1)->tokAt(-1);
if (!Token::Match(prev, "%name% (") || (!prev->isControlFlowKeyword() && prev->str() != "decltype")) {
if (prev && prev->isUpperCaseName())
if (Token::Match(prev, "%name% (") && !prev->isKeyword()) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI review take it with a grain of salt. Please feel free to reject it by clicking on Resolve button

Whether a token is a keyword depends on --std (TokenList::isKeyword() uses Keywords::getAll(standards.cpp)). With --std=c++03, decltype is a plain name, so this now gives a false syntaxError:

$ cppcheck --std=c++03 dt.cpp
dt.cpp:3:12: error: syntax error [syntaxError]
decltype(s)::type i;

The old code avoided this with prev->str() != "decltype". Maybe keep that, e.g. && !prev->isKeyword() && prev->str() != "decltype".

if (prev->isUpperCaseName())
unknownMacroError(prev);
else
syntaxError(tok);
Expand Down
16 changes: 16 additions & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8135,6 +8135,22 @@ class TestTokenizer : public TestFixture {
" *p = -*p;\n"
"}\n"));

ASSERT_NO_THROW(tokenizeAndStringify("void f(void* h) {\n" // cast before global scope operator

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI review take it with a grain of salt. Please feel free to reject it by clicking on Resolve button

In this project tests usually reference the ticket number, e.g. // #15079.

" (void)::CloseHandle(h);\n"
" int i = (int)::GetTickCount();\n"
" g((unsigned char)::toupper(i));\n"
"}\n"));
ASSERT_NO_THROW(tokenizeAndStringify("int f(int i) {\n"
" return (int)::abs(i);\n"
"}\n"));
ASSERT_NO_THROW(tokenizeAndStringify("namespace N { struct T {}; }\n"
"void f(void* p) {\n"
" new (p) ::N::T;\n"
"}\n"));
ASSERT_NO_THROW(tokenizeAndStringify("struct S { using type = int; };\n"
"S s;\n"
"decltype(s)::type i;\n"));

ignore_errout();

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