Fix #12081 (Tokenizer::simplifyTypedef: Handle volatile structs better) (#5577)

This commit is contained in:
Daniel Marjamäki 2023-10-19 21:02:03 +02:00 committed by GitHub
parent 04ece4f65b
commit 17ea101e7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 10 deletions

View File

@ -410,17 +410,15 @@ namespace {
static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount) static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount)
{ {
std::string name; std::string name;
bool isConst = false; std::set<std::string> qualifiers;
Token *tok1 = tok->next();
// skip const if present while (Token::Match(tok->next(), "const|volatile")) {
if (tok1->str() == "const") { qualifiers.insert(tok->next()->str());
tok1->deleteThis(); tok->deleteNext();
isConst = true;
} }
// skip "class|struct|union|enum" // skip "class|struct|union|enum"
tok1 = tok1->next(); Token *tok1 = tok->tokAt(2);
const bool hasName = Token::Match(tok1, "%name%"); const bool hasName = Token::Match(tok1, "%name%");
@ -465,8 +463,8 @@ static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount)
tok1->insertToken("typedef"); tok1->insertToken("typedef");
tok1 = tok1->next(); tok1 = tok1->next();
Token * tok3 = tok1; Token * tok3 = tok1;
if (isConst) { for (const std::string &qualifier : qualifiers) {
tok1->insertToken("const"); tok1->insertToken(qualifier);
tok1 = tok1->next(); tok1 = tok1->next();
} }
tok1->insertToken(tok->next()->str()); // struct, union or enum tok1->insertToken(tok->next()->str()); // struct, union or enum
@ -1209,7 +1207,10 @@ void Tokenizer::simplifyTypedefCpp()
// pull struct, union, enum or class definition out of typedef // pull struct, union, enum or class definition out of typedef
// use typedef name for unnamed struct, union, enum or class // use typedef name for unnamed struct, union, enum or class
if (Token::Match(tok->next(), "const| struct|enum|union|class %type%| {|:")) { const Token* tokClass = tok->next();
while (Token::Match(tokClass, "const|volatile"))
tokClass = tokClass->next();
if (Token::Match(tokClass, "struct|enum|union|class %type%| {|:")) {
Token *tok1 = splitDefinitionFromTypedef(tok, &mUnnamedCount); Token *tok1 = splitDefinitionFromTypedef(tok, &mUnnamedCount);
if (!tok1) if (!tok1)
continue; continue;

View File

@ -222,6 +222,8 @@ private:
TEST_CASE(simplifyTypedefFunction9); TEST_CASE(simplifyTypedefFunction9);
TEST_CASE(simplifyTypedefFunction10); // #5191 TEST_CASE(simplifyTypedefFunction10); // #5191
TEST_CASE(simplifyTypedefStruct); // #12081 - volatile struct
TEST_CASE(simplifyTypedefShadow); // #4445 - shadow variable TEST_CASE(simplifyTypedefShadow); // #4445 - shadow variable
TEST_CASE(simplifyTypedefMacro); TEST_CASE(simplifyTypedefMacro);
@ -4002,6 +4004,20 @@ private:
tok(code,false)); tok(code,false));
} }
void simplifyTypedefStruct() {
const char code1[] = "typedef struct S { int x; } xyz;\n"
"xyz var;";
ASSERT_EQUALS("struct S { int x ; } ; struct S var ;", tok(code1,false));
const char code2[] = "typedef const struct S { int x; } xyz;\n"
"xyz var;";
ASSERT_EQUALS("struct S { int x ; } ; const struct S var ;", tok(code2,false));
const char code3[] = "typedef volatile struct S { int x; } xyz;\n"
"xyz var;";
ASSERT_EQUALS("struct S { int x ; } ; volatile struct S var ;", tok(code3,false));
}
void simplifyTypedefShadow() { // shadow variable (#4445) void simplifyTypedefShadow() { // shadow variable (#4445)
const char code[] = "typedef struct { int x; } xyz;;\n" const char code[] = "typedef struct { int x; } xyz;;\n"
"void f(){\n" "void f(){\n"