Skip to content

Commit 822bbd5

Browse files
authored
Fix #12813 (Tokenizer: handle alignas in C11 code) (#6534)
cherry picked from 7ab4ae7
1 parent 71dcef8 commit 822bbd5

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed

lib/tokenize.cpp

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9223,7 +9223,11 @@ void Tokenizer::simplifyCppcheckAttribute()
92239223

92249224
void Tokenizer::simplifyCPPAttribute()
92259225
{
9226-
if (!isCPP() || mSettings.standards.cpp < Standards::CPP11)
9226+
// According to cppreference alignas is a c21 feature however the macro is often available when compiling c11
9227+
const bool hasAlignas = ((isCPP() && mSettings.standards.cpp >= Standards::CPP11) || (isC() && mSettings.standards.c >= Standards::C11));
9228+
const bool hasCppAttribute = (isCPP() && mSettings.standards.cpp >= Standards::CPP11);
9229+
9230+
if (!hasAlignas && !hasCppAttribute)
92279231
return;
92289232

92299233
for (Token *tok = list.front(); tok;) {
@@ -9232,6 +9236,10 @@ void Tokenizer::simplifyCPPAttribute()
92329236
continue;
92339237
}
92349238
if (isCPPAttribute(tok)) {
9239+
if (!hasCppAttribute) {
9240+
tok = skipCPPOrAlignAttribute(tok)->next();
9241+
continue;
9242+
}
92359243
if (Token::findsimplematch(tok->tokAt(2), "noreturn", tok->link())) {
92369244
Token * head = skipCPPOrAlignAttribute(tok)->next();
92379245
while (isCPPAttribute(head) || isAlignAttribute(head))
@@ -9283,23 +9291,29 @@ void Tokenizer::simplifyCPPAttribute()
92839291
}
92849292
}
92859293
} else {
9286-
if (Token::simpleMatch(tok, "alignas (")) {
9287-
Token* atok = nullptr;
9288-
if (Token::Match(tok->previous(), "%name%"))
9289-
atok = tok->previous();
9290-
else {
9291-
atok = tok;
9292-
while (isCPPAttribute(atok) || isAlignAttribute(atok))
9293-
atok = skipCPPOrAlignAttribute(atok)->next();
9294-
}
9295-
if (atok) {
9296-
std::string a;
9297-
for (const Token* t = tok->tokAt(2); t && t->str() != ")"; t = t->next())
9298-
a += " " + t->str();
9299-
if (a.size() > 1)
9300-
atok->addAttributeAlignas(a.substr(1));
9301-
}
9302-
// alignment requirements could be checked here
9294+
// alignas(expr)
9295+
9296+
if (!hasAlignas) {
9297+
tok = skipCPPOrAlignAttribute(tok)->next();
9298+
continue;
9299+
}
9300+
9301+
// alignment requirements could be checked here
9302+
9303+
Token* atok = nullptr;
9304+
if (Token::Match(tok->previous(), "%name%"))
9305+
atok = tok->previous();
9306+
else {
9307+
atok = tok;
9308+
while (isCPPAttribute(atok) || isAlignAttribute(atok))
9309+
atok = skipCPPOrAlignAttribute(atok)->next();
9310+
}
9311+
if (atok) {
9312+
std::string a;
9313+
for (const Token* t = tok->tokAt(2); t && t->str() != ")"; t = t->next())
9314+
a += " " + t->str();
9315+
if (a.size() > 1)
9316+
atok->addAttributeAlignas(a.substr(1));
93039317
}
93049318
}
93059319
Token::eraseTokens(tok, skipCPPOrAlignAttribute(tok)->next());

test/testsymboldatabase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1715,7 +1715,7 @@ class TestSymbolDatabase : public TestFixture {
17151715
ASSERT(db);
17161716
ASSERT_EQUALS(2, db->scopeList.front().varlist.size());
17171717
const Variable *x1 = Token::findsimplematch(tokenizer.tokens(), "x")->variable();
1718-
ASSERT(x1 && Token::simpleMatch(x1->typeStartToken(), "alignas ( 16 ) int x ;"));
1718+
ASSERT(x1 && Token::simpleMatch(x1->typeStartToken(), "int x ;"));
17191719
}
17201720

17211721
void memberVar1() {

test/testtokenize.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ class TestTokenizer : public TestFixture {
438438

439439
TEST_CASE(removeAlignas1);
440440
TEST_CASE(removeAlignas2); // Do not remove alignof in the same way
441+
TEST_CASE(removeAlignas3); // remove alignas in C11 code
441442
TEST_CASE(dumpAlignas);
442443

443444
TEST_CASE(simplifyCoroutines);
@@ -7765,6 +7766,16 @@ class TestTokenizer : public TestFixture {
77657766
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
77667767
}
77677768

7769+
void removeAlignas3() {
7770+
const char code[] = "alignas(16) int x;";
7771+
const char expected[] = "int x ;";
7772+
// According to cppreference alignas() is a C23 macro; but it is often available when compiling C11.
7773+
// Misra C has C11 examples with alignas.
7774+
// Microsoft provides alignas in C11.
7775+
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Type::Native, false, Standards::CPP11));
7776+
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Platform::Type::Native, true, Standards::CPP11));
7777+
}
7778+
77687779
void dumpAlignas() {
77697780
Settings settings;
77707781
SimpleTokenizer tokenizer(settings, *this);

0 commit comments

Comments
 (0)