diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 13ee9de8b..7dfcc78b8 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9254,8 +9254,15 @@ static const Token *findUnmatchedTernaryOp(const Token * const begin, const Toke return ternaryOp.empty() ? nullptr : ternaryOp.top(); } +static bool isCPPAttribute(const Token * tok) +{ + return Token::simpleMatch(tok, "[ [") && tok->link() && tok->link()->previous() == tok->linkAt(1); +} + void Tokenizer::findGarbageCode() const { + const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11; + // initialization: = { for (const Token *tok = tokens(); tok; tok = tok->next()) { if (!Token::simpleMatch(tok, "= {")) @@ -9409,6 +9416,11 @@ void Tokenizer::findGarbageCode() const if (Token::Match(tok, "> %cop%")) continue; } + // skip C++ attributes [[...]] + if (isCPP11 && isCPPAttribute(tok)) { + tok = tok->link(); + continue; + } { bool match1 = Token::Match(tok, "%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|++|--|::|sizeof"); bool match2 = Token::Match(tok->next(), "{|if|else|while|do|for|return|switch|break"); @@ -10031,7 +10043,7 @@ void Tokenizer::simplifyCPPAttribute() return; for (Token *tok = list.front(); tok; tok = tok->next()) { - if (!tok->link() || !Token::Match(tok, "[ [ %name%")) + if (!isCPPAttribute(tok)) continue; if (Token::Match(tok->tokAt(2), "noreturn|nodiscard")) { const Token * head = tok->link()->next(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 9e60849bc..a9821eb1f 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -7291,6 +7291,26 @@ private: ASSERT_EQUALS("[ [ maybe_unused ] ] int f ( [ [ maybe_unused ] ] int i ) ;", tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", false, true, Settings::Native, "test.cpp", false)); + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[]] a;", false, true, Settings::Native, "test.cpp", true)); + + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[,]] a;", false, true, Settings::Native, "test.cpp", true)); + + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[deprecated,]] a;", false, true, Settings::Native, "test.cpp", true)); + + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[,,]] a;", false, true, Settings::Native, "test.cpp", true)); + + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[deprecated,,]] a;", false, true, Settings::Native, "test.cpp", true)); + + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[deprecated,maybe_unused,]] a;", false, true, Settings::Native, "test.cpp", true)); + + ASSERT_EQUALS("struct a ;", + tokenizeAndStringify("struct [[,,,]] a;", false, true, Settings::Native, "test.cpp", true)); } void simplifyCaseRange() {