Skip to content

Commit e052321

Browse files
authored
Fix issue with anonymous enums (#599)
* Fix issue with anonymous enums
1 parent ad1c9b3 commit e052321

File tree

11 files changed

+109
-2
lines changed

11 files changed

+109
-2
lines changed

server/src/clang-utils/SourceToHeaderMatchCallback.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ void SourceToHeaderMatchCallback::generateInternal(const FunctionDecl *decl) con
196196
auto policy = getDefaultPrintingPolicy(decl, true);
197197
policy.TerseOutput = 1;
198198
policy.PolishForDeclaration = 1;
199+
policy.AnonymousTagLocations = 0;
199200

200201
std::string name = decl->getNameAsString();
201202
std::string decoratedName = decorate(name);
@@ -208,6 +209,13 @@ void SourceToHeaderMatchCallback::generateInternal(const FunctionDecl *decl) con
208209
curDecl = getOldStyleDeclarationAsString(decl, decoratedName);
209210
wrapperDecl = getOldStyleDeclarationAsString(decl, wrapperName);
210211
}
212+
TagDecl *tagDecl = decl->getReturnType()->getAsTagDecl();
213+
if (isAnonymousEnumDecl(tagDecl)) {
214+
std::string enumReturnTypeName = PrinterUtils::getEnumReturnMangledTypeName(name);
215+
replaceAnonymousEnumTypeName(wrapperDecl, enumReturnTypeName);
216+
replaceAnonymousEnumTypeName(curDecl, enumReturnTypeName);
217+
renameAnonymousReturnTypeDecl(tagDecl, name);
218+
}
211219

212220
*internalStream << "extern \"C\" " << wrapperDecl << ";\n";
213221
*internalStream << "static " << curDecl << " {\n";
@@ -251,6 +259,7 @@ void SourceToHeaderMatchCallback::generateWrapper(const FunctionDecl *decl) cons
251259
auto policy = getDefaultPrintingPolicy(decl, false);
252260
policy.TerseOutput = 1;
253261
policy.PolishForDeclaration = 1;
262+
policy.AnonymousTagLocations = 0;
254263

255264
/*
256265
* fun_wrapper {
@@ -263,6 +272,10 @@ void SourceToHeaderMatchCallback::generateWrapper(const FunctionDecl *decl) cons
263272
if (IsOldStyleDefinition(wrapperDecl)){
264273
wrapperDecl = getOldStyleDeclarationAsString(decl, wrapperName);
265274
}
275+
TagDecl *tagDecl = decl->getReturnType()->getAsTagDecl();
276+
if (isAnonymousEnumDecl(tagDecl)) {
277+
replaceAnonymousEnumTypeName(wrapperDecl, "int");
278+
}
266279

267280
*wrapperStream << wrapperDecl << " {\n";
268281
printReturn(decl, name, wrapperStream);
@@ -373,6 +386,23 @@ void SourceToHeaderMatchCallback::renameDecl(const NamedDecl *decl, const std::s
373386
const_cast<NamedDecl *>(decl)->setDeclName(wrapperDeclarationName);
374387
}
375388

389+
void SourceToHeaderMatchCallback::renameAnonymousReturnTypeDecl(const TagDecl *tagDecl,
390+
const std::string &methodName) const {
391+
auto enumDecl = llvm::dyn_cast<clang::EnumDecl>(tagDecl);
392+
std::string declTypeName = PrinterUtils::getReturnMangledTypeName(methodName);
393+
renameDecl(enumDecl, declTypeName);
394+
print(enumDecl);
395+
}
396+
397+
void SourceToHeaderMatchCallback::replaceAnonymousEnumTypeName(std::string &strDecl,
398+
const std::string &typeName) const {
399+
StringUtils::replaceFirst(strDecl, "enum (anonymous)", typeName);
400+
}
401+
402+
bool SourceToHeaderMatchCallback::isAnonymousEnumDecl(const clang::TagDecl *tagDecl) const {
403+
return tagDecl && tagDecl->isEnum() && !tagDecl->hasNameForLinkage();
404+
}
405+
376406
std::string SourceToHeaderMatchCallback::getOldStyleDeclarationAsString(const FunctionDecl *decl, std::string const &name) const{
377407
std::string result;
378408
llvm::raw_string_ostream resultStream{ result };

server/src/clang-utils/SourceToHeaderMatchCallback.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,15 @@ class SourceToHeaderMatchCallback : public clang::ast_matchers::MatchFinder::Mat
8686

8787
void renameDecl(const clang::NamedDecl *decl, const std::string &name) const;
8888

89+
void renameAnonymousReturnTypeDecl(const clang::TagDecl *tagDecl, const std::string &methodName) const;
90+
8991
std::string decorate(std::string_view name) const;
9092

93+
void replaceAnonymousEnumTypeName(std::string &strDecl,
94+
const std::string &typeName) const;
95+
96+
bool isAnonymousEnumDecl(const clang::TagDecl *tagDecl) const;
97+
9198
std::string getOldStyleDeclarationAsString(const clang::FunctionDecl *decl, std::string const &name) const;
9299

93100
bool IsOldStyleDefinition(std::string const &definition) const;

server/src/fetchers/FunctionDeclsMatchCallback.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) {
3333
}
3434

3535
std::string methodName = FS->getQualifiedNameAsString();
36+
std::string enumReturnTypeName = PrinterUtils::getEnumReturnMangledTypeName(methodName);
3637
methodDescription.name = methodName;
3738
methodDescription.callName = ClangUtils::getCallName(FS);
3839
methodDescription.sourceFilePath = sourceFilePath;
@@ -42,6 +43,7 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) {
4243
}
4344
clang::QualType realReturnType = ClangUtils::getReturnType(FS, Result);
4445
methodDescription.returnType = ParamsHandler::getType(realReturnType, realReturnType, sourceManager);
46+
methodDescription.returnType.replaceTypeNameIfUnnamed(enumReturnTypeName);
4547
methodDescription.accessSpecifier = types::AS_pubic;
4648
if (onlyReturnTypes) {
4749
addMethod(sourceFilePath, methodDescription);
@@ -72,6 +74,7 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) {
7274
methodDescription.accessSpecifier = getAcessSpecifier(FS);
7375
}
7476
methodDescription.returnType = ParamsHandler::getType(realReturnType, realReturnType, sourceManager);
77+
methodDescription.returnType.replaceTypeNameIfUnnamed(enumReturnTypeName);
7578
methodDescription.hasIncompleteReturnType = ClangUtils::isIncomplete(realReturnType);
7679
if (toResolveReturnTypes) {
7780
typesResolver.resolve(realReturnType);

server/src/printers/KleePrinter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,10 @@ void KleePrinter::genReturnDeclaration(const Tests::MethodDescription &testMetho
471471
: testMethod.returnType;
472472
bool maybeArray = returnType.maybeReturnArray();
473473
bool isPointer = testMethod.returnType.isObjectPointer();
474-
strDeclareVar(returnType.baseType(), KleeUtils::RESULT_VARIABLE_NAME, std::nullopt, std::nullopt, false);
474+
std::string type = typesHandler->isAnonymousEnum(returnType)
475+
? "int"
476+
: returnType.baseType();
477+
strDeclareVar(type, KleeUtils::RESULT_VARIABLE_NAME, std::nullopt, std::nullopt, false);
475478
makeBracketsForStrPredicate(predicateInfo);
476479
if (maybeArray) {
477480
size_t size = types::TypesHandler::getElementsNumberInPointerOneDim(PointerUsage::RETURN);

server/src/types/Types.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,13 @@ void types::Type::replaceUsedType(const types::TypeName &newUsedType) {
390390
mUsedType = newUsedType;
391391
}
392392

393+
void types::Type::replaceTypeNameIfUnnamed(const TypeName &newTypeName) {
394+
if (isUnnamed()) {
395+
mBaseType = newTypeName;
396+
mUsedType = newTypeName;
397+
}
398+
}
399+
393400
/*
394401
* Integer types
395402
*/
@@ -504,6 +511,10 @@ bool types::TypesHandler::isEnum(const types::Type &type) const {
504511
return type.isSimple() && isEnum(type.getId());
505512
}
506513

514+
bool types::TypesHandler::isAnonymousEnum(const types::Type& type) const {
515+
return type.isUnnamed() && isEnum(type);
516+
}
517+
507518
bool types::TypesHandler::isEnum(uint64_t id) const {
508519
return typeIsInMap(id, typeMaps.enums);
509520
}

server/src/types/Types.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ namespace types {
217217
*/
218218
void replaceUsedType(const TypeName &newUsedType);
219219

220+
/**
221+
* Replace current baseType and usedType with a new one if unnamed.
222+
* @param newTypeName - name of type
223+
* @return
224+
*/
225+
void replaceTypeNameIfUnnamed(const TypeName &newTypeName);
226+
220227
/**
221228
* Creates type from its name. Created type satisfies following:
222229
* typeName() == "const " + type && baseType() == type && usedType() == typeName();
@@ -462,6 +469,12 @@ namespace types {
462469
*/
463470
bool isEnum(const Type&) const;
464471

472+
/**
473+
* Returns true if given type is an anonymous enum, otherwise false.
474+
* @return whether given type is an anonymous enum
475+
*/
476+
bool isAnonymousEnum(const Type&) const;
477+
465478

466479
/**
467480
* Returns true if given type is void, otherwise false.

server/src/utils/PrinterUtils.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ namespace PrinterUtils {
9797
return methodName + "_return";
9898
}
9999

100+
std::string getReturnMangledTypeName(const std::string& methodName) {
101+
return methodName + "_return_type";
102+
}
103+
104+
std::string getEnumReturnMangledTypeName(const std::string& methodName) {
105+
return "enum " + getReturnMangledTypeName(methodName);
106+
}
107+
100108
std::string getEqualString(const std::string& lhs, const std::string& rhs) {
101109
return StringUtils::stringFormat("%s == %s", lhs, rhs);
102110
}

server/src/utils/PrinterUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ namespace PrinterUtils {
7878

7979
std::string getParamMangledName(const std::string &paramName, const std::string &methodName);
8080
std::string getReturnMangledName(const std::string &methodName);
81+
std::string getReturnMangledTypeName(const std::string& methodName);
82+
std::string getEnumReturnMangledTypeName(const std::string& methodName);
8183

8284
std::string getEqualString(const std::string &lhs, const std::string &rhs);
8385
std::string getDereferencePointer(const std::string &name, const size_t depth);

server/src/visitors/KleeAssumeReturnValueVisitor.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ namespace visitor {
1717
functionCall = printer->constrFunctionCall(methodDescription, 0, "", false);
1818
additionalPointersCount = methodDescription.returnType.countReturnPointers();
1919
auto returnType = methodDescription.returnType.baseTypeObj();
20-
printer->strDeclareVar(getActualTmpVarType(returnType).baseType(),
20+
std::string type = typesHandler->isAnonymousEnum(returnType)
21+
? "int"
22+
: getActualTmpVarType(returnType).baseType();
23+
printer->strDeclareVar(type,
2124
KleeUtils::TEMP_VARIABLE_NAME, functionCall,
2225
std::nullopt, true, additionalPointersCount);
2326
checkNotNullBefore();

server/test/framework/Syntax_Tests.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,26 @@ namespace {
722722
);
723723
}
724724

725+
TEST_F(Syntax_Test, Anonymous_Enum_As_Return_Test) {
726+
auto [testGen, status] = createTestForFunction(enums_c, 79);
727+
728+
ASSERT_TRUE(status.ok()) << status.error_message();
729+
730+
checkTestCasePredicates(
731+
testGen.tests.at(enums_c).methods.begin().value().testCases,
732+
std::vector<TestCasePredicate>(
733+
{[](const tests::Tests::MethodTestCase& testCase) {
734+
return testCase.returnValue.view->getEntryValue(nullptr) == "EVEN" && stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) % 2 == 0;
735+
},
736+
[](const tests::Tests::MethodTestCase& testCase) {
737+
return testCase.returnValue.view->getEntryValue(nullptr) == "ODD" && stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) % 2 == 1;
738+
}
739+
}
740+
),
741+
"intToParity"
742+
);
743+
}
744+
725745
TEST_F(Syntax_Test, Typedef_Struct_Test) {
726746
auto [testGen, status] = createTestForFunction(typedefs_1_c, 15);
727747

server/test/suites/syntax/enums.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,10 @@ static int enumWithinRecord(struct EnumWithinRecord record) {
7373
return 0;
7474
}
7575
}
76+
77+
enum {EVEN, ODD} intToParity(int a) {
78+
if (a % 2 == 0) {
79+
return EVEN;
80+
}
81+
return ODD;
82+
}

0 commit comments

Comments
 (0)