Skip to content

Commit e698e7f

Browse files
committed
Fix detection of cyclic structs and unions
Break cycle only in one place. Support breaking cycles on complex types. Remove `avoid` parameter in TypeTranslator methods.
1 parent 7f1ebd4 commit e698e7f

31 files changed

+921
-248
lines changed

bindgen/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ add_executable(bindgen
3636
defines/DefineFinderActionFactory.h
3737
TypeTranslator.h
3838
TypeTranslator.cpp
39-
CycleDetection.h
4039
Utils.h
4140
ir/IR.h
4241
ir/IR.cpp

bindgen/CycleDetection.h

Lines changed: 0 additions & 61 deletions
This file was deleted.

bindgen/TypeTranslator.cpp

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,17 @@ TypeTranslator::TypeTranslator(clang::ASTContext *ctx_, IR &ir)
3434
}
3535

3636
std::shared_ptr<Type>
37-
TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
38-
const std::string *avoid) {
37+
TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe) {
3938
const auto *ptr = qtpe.getTypePtr()->getAs<clang::PointerType>();
4039
const clang::QualType &inner = ptr->getPointeeType();
4140

4241
if (inner->isFunctionProtoType()) {
4342
const auto *fc = inner->getAs<clang::FunctionProtoType>();
44-
std::shared_ptr<Type> returnType =
45-
translate(fc->getReturnType(), avoid);
43+
std::shared_ptr<Type> returnType = translate(fc->getReturnType());
4644
std::vector<std::shared_ptr<const Type>> parametersTypes;
4745

4846
for (const clang::QualType &param : fc->param_types()) {
49-
parametersTypes.push_back(translate(param, avoid));
47+
parametersTypes.push_back(translate(param));
5048
}
5149

5250
return std::make_shared<FunctionPointerType>(
@@ -61,8 +59,7 @@ TypeTranslator::translateFunctionPointer(const clang::QualType &qtpe,
6159
}
6260

6361
std::shared_ptr<Type>
64-
TypeTranslator::translatePointer(const clang::QualType &pte,
65-
const std::string *avoid) {
62+
TypeTranslator::translatePointer(const clang::QualType &pte) {
6663

6764
if (pte->isBuiltinType()) {
6865
const clang::BuiltinType *as = pte->getAs<clang::BuiltinType>();
@@ -81,7 +78,7 @@ TypeTranslator::translatePointer(const clang::QualType &pte,
8178
}
8279
}
8380

84-
return std::make_shared<PointerType>(translate(pte, avoid));
81+
return std::make_shared<PointerType>(translate(pte));
8582
}
8683

8784
std::shared_ptr<Type>
@@ -120,10 +117,9 @@ TypeTranslator::translateStructOrUnion(const clang::QualType &qtpe) {
120117
}
121118

122119
std::shared_ptr<Type>
123-
TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
124-
const std::string *avoid) {
120+
TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar) {
125121
const uint64_t size = ar->getSize().getZExtValue();
126-
std::shared_ptr<Type> elementType = translate(ar->getElementType(), avoid);
122+
std::shared_ptr<Type> elementType = translate(ar->getElementType());
127123
if (elementType == nullptr) {
128124
llvm::errs() << "Failed to translate array type "
129125
<< ar->getElementType().getAsString() << "\n";
@@ -133,30 +129,20 @@ TypeTranslator::translateConstantArray(const clang::ConstantArrayType *ar,
133129
return std::make_shared<ArrayType>(elementType, size);
134130
}
135131

136-
std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
137-
const std::string *avoid) {
132+
std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe) {
138133

139134
const clang::Type *tpe = qtpe.getTypePtr();
140135

141-
if (typeEquals(tpe, avoid)) {
142-
// This is a type that we want to avoid the usage.
143-
// Êxample: A struct that has a pointer to itself
144-
uint64_t sizeInBits = ctx->getTypeSize(tpe);
145-
assert(sizeInBits % 8 == 0);
146-
return std::make_shared<ArrayType>(
147-
std::make_shared<PrimitiveType>("Byte"), sizeInBits / 8);
148-
}
149-
150136
if (tpe->isFunctionType()) {
151137
return nullptr;
152138
}
153139

154140
if (tpe->isFunctionPointerType()) {
155-
return translateFunctionPointer(qtpe, avoid);
141+
return translateFunctionPointer(qtpe);
156142

157143
} else if (tpe->isPointerType()) {
158144
return translatePointer(
159-
tpe->getAs<clang::PointerType>()->getPointeeType(), avoid);
145+
tpe->getAs<clang::PointerType>()->getPointeeType());
160146

161147
} else if (qtpe->isStructureType()) {
162148
return translateStructOrUnion(qtpe);
@@ -168,10 +154,9 @@ std::shared_ptr<Type> TypeTranslator::translate(const clang::QualType &qtpe,
168154
return translateStructOrUnionOrEnum(qtpe);
169155

170156
} else if (qtpe->isConstantArrayType()) {
171-
return translateConstantArray(ctx->getAsConstantArrayType(qtpe), avoid);
157+
return translateConstantArray(ctx->getAsConstantArrayType(qtpe));
172158
} else if (qtpe->isArrayType()) {
173-
return translatePointer(ctx->getAsArrayType(qtpe)->getElementType(),
174-
avoid);
159+
return translatePointer(ctx->getAsArrayType(qtpe)->getElementType());
175160
} else {
176161

177162
auto found = typeMap.find(qtpe.getUnqualifiedType().getAsString());

bindgen/TypeTranslator.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,9 @@ class TypeTranslator {
1010
/**
1111
* @brief Translate the qualified type from c to a scala type
1212
* @param tpe The type to translate
13-
* @param avoid A type to avoid, useful to avoid cyclic definitions inside
14-
* structs, unions, ...
1513
* @return the type translated or nullptr if type is function type.
1614
*/
17-
std::shared_ptr<Type> translate(const clang::QualType &tpe,
18-
const std::string *avoid = nullptr);
15+
std::shared_ptr<Type> translate(const clang::QualType &tpe);
1916

2017
std::string getTypeFromTypeMap(std::string cType);
2118

@@ -33,13 +30,10 @@ class TypeTranslator {
3330

3431
std::shared_ptr<Type> translateStructOrUnion(const clang::QualType &qtpe);
3532

36-
std::shared_ptr<Type> translateFunctionPointer(const clang::QualType &qtpe,
37-
const std::string *avoid);
33+
std::shared_ptr<Type> translateFunctionPointer(const clang::QualType &qtpe);
3834

39-
std::shared_ptr<Type> translatePointer(const clang::QualType &pointee,
40-
const std::string *avoid);
35+
std::shared_ptr<Type> translatePointer(const clang::QualType &pointee);
4136

4237
std::shared_ptr<Type>
43-
translateConstantArray(const clang::ConstantArrayType *ar,
44-
const std::string *avoid);
38+
translateConstantArray(const clang::ConstantArrayType *ar);
4539
};

bindgen/Utils.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,14 @@ static inline bool isAliasForOpaqueType(const Type *type) {
109109
return false;
110110
}
111111

112+
static inline bool contains(const Type *type,
113+
std::vector<std::shared_ptr<const Type>> &types) {
114+
for (const auto &t : types) {
115+
if (*type == *t) {
116+
return true;
117+
}
118+
}
119+
return false;
120+
}
121+
112122
#endif // UTILS_H

bindgen/ir/Function.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Function &func) {
3131
return s;
3232
}
3333

34-
bool Function::usesType(std::shared_ptr<const Type> type,
35-
bool stopOnTypeDefs) const {
36-
if (*retType == *type || retType->usesType(type, stopOnTypeDefs)) {
34+
bool Function::usesType(
35+
std::shared_ptr<const Type> type, bool stopOnTypeDefs,
36+
std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
37+
visitedTypes.clear();
38+
if (*retType == *type ||
39+
retType.get()->usesType(type, stopOnTypeDefs, visitedTypes)) {
3740
return true;
3841
}
3942
for (const auto &parameter : parameters) {
43+
visitedTypes.clear();
4044
if (*parameter->getType() == *type ||
41-
parameter->getType()->usesType(type, stopOnTypeDefs)) {
45+
parameter->getType().get()->usesType(type, stopOnTypeDefs,
46+
visitedTypes)) {
4247
return true;
4348
}
4449
}

bindgen/ir/Function.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class Function {
2121
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s,
2222
const Function &func);
2323

24-
bool usesType(std::shared_ptr<const Type> type, bool stopOnTypeDefs) const;
24+
bool usesType(std::shared_ptr<const Type> type, bool stopOnTypeDefs,
25+
std::vector<std::shared_ptr<const Type>> &visitedTypes) const;
2526

2627
std::string getName() const;
2728

0 commit comments

Comments
 (0)