Skip to content

Commit

Permalink
Fix #12813 (Tokenizer: handle alignas in C11 code) (#6487)
Browse files Browse the repository at this point in the history
  • Loading branch information
danmar committed Jun 17, 2024
1 parent 7b31255 commit 6b218fc
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 18 deletions.
50 changes: 32 additions & 18 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9223,7 +9223,11 @@ void Tokenizer::simplifyCppcheckAttribute()

void Tokenizer::simplifyCPPAttribute()
{
if (!isCPP() || mSettings.standards.cpp < Standards::CPP11)
// According to cppreference alignas is a c21 feature however the macro is often available when compiling c11
const bool hasAlignas = ((isCPP() && mSettings.standards.cpp >= Standards::CPP11) || (isC() && mSettings.standards.c >= Standards::C11));
const bool hasCppAttribute = (isCPP() && mSettings.standards.cpp >= Standards::CPP11);

if (!hasAlignas && !hasCppAttribute)
return;

for (Token *tok = list.front(); tok;) {
Expand All @@ -9232,6 +9236,10 @@ void Tokenizer::simplifyCPPAttribute()
continue;
}
if (isCPPAttribute(tok)) {
if (!hasCppAttribute) {
tok = skipCPPOrAlignAttribute(tok)->next();
continue;
}
if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
Token * head = skipCPPOrAlignAttribute(tok)->next();
while (isCPPAttribute(head) || isAlignAttribute(head))
Expand Down Expand Up @@ -9283,23 +9291,29 @@ void Tokenizer::simplifyCPPAttribute()
}
}
} else {
if (Token::simpleMatch(tok, "alignas (")) {
Token* atok = nullptr;
if (Token::Match(tok->previous(), "%name%"))
atok = tok->previous();
else {
atok = tok;
while (isCPPAttribute(atok) || isAlignAttribute(atok))
atok = skipCPPOrAlignAttribute(atok)->next();
}
if (atok) {
std::string a;
for (const Token* t = tok->tokAt(2); t && t->str() != ")"; t = t->next())
a += " " + t->str();
if (a.size() > 1)
atok->addAttributeAlignas(a.substr(1));
}
// alignment requirements could be checked here
// alignas(expr)

if (!hasAlignas) {
tok = skipCPPOrAlignAttribute(tok)->next();
continue;
}

// alignment requirements could be checked here

Token* atok = nullptr;
if (Token::Match(tok->previous(), "%name%"))
atok = tok->previous();
else {
atok = tok;
while (isCPPAttribute(atok) || isAlignAttribute(atok))
atok = skipCPPOrAlignAttribute(atok)->next();
}
if (atok) {
std::string a;
for (const Token* t = tok->tokAt(2); t && t->str() != ")"; t = t->next())
a += " " + t->str();
if (a.size() > 1)
atok->addAttributeAlignas(a.substr(1));
}
}
Token::eraseTokens(tok, skipCPPOrAlignAttribute(tok)->next());
Expand Down
11 changes: 11 additions & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ class TestTokenizer : public TestFixture {

TEST_CASE(removeAlignas1);
TEST_CASE(removeAlignas2); // Do not remove alignof in the same way
TEST_CASE(removeAlignas3); // remove alignas in C11 code
TEST_CASE(dumpAlignas);

TEST_CASE(simplifyCoroutines);
Expand Down Expand Up @@ -7765,6 +7766,16 @@ class TestTokenizer : public TestFixture {
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
}

void removeAlignas3() {
const char code[] = "alignas(16) int x;";
const char expected[] = "int x ;";
// According to cppreference alignas() is a C23 macro; but it is often available when compiling C11.
// Misra C has C11 examples with alignas.
// Microsoft provides alignas in C11.
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Type::Native, false, Standards::CPP11));
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Type::Native, true, Standards::CPP11));
}

void dumpAlignas() {
Settings settings;
SimpleTokenizer tokenizer(settings, *this);
Expand Down

0 comments on commit 6b218fc

Please sign in to comment.