Skip to content

Commit d97e6b9

Browse files
authored
Merge pull request #150 from kornilova-l/do-not-generate-typedef-for-enum
Do not generate TypeDef for enum
2 parents 39fb61a + e2777eb commit d97e6b9

16 files changed

+105
-54
lines changed

bindgen/TypeTranslator.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ TypeTranslator::translatePointer(const clang::QualType &pte) {
8282
}
8383

8484
std::shared_ptr<Type>
85-
TypeTranslator::translateRecordOrEnum(const clang::QualType &qtpe) {
85+
TypeTranslator::translateNonAnonymousRecord(const clang::QualType &qtpe) {
8686
std::string name = qtpe.getUnqualifiedType().getAsString();
8787

8888
/* If the struct was already declared then there is a TypeDef instance
@@ -118,7 +118,7 @@ TypeTranslator::translateRecord(const clang::QualType &qtpe) {
118118
}
119119
return nullptr;
120120
}
121-
return translateRecordOrEnum(qtpe);
121+
return translateNonAnonymousRecord(qtpe);
122122
}
123123

124124
std::shared_ptr<Type>
@@ -243,10 +243,17 @@ TypeTranslator::addStructDefinition(clang::RecordDecl *record,
243243

244244
std::shared_ptr<Type>
245245
TypeTranslator::translateEnum(const clang::QualType &type) {
246+
clang::EnumDecl *enumDecl = type->getAs<clang::EnumType>()->getDecl();
246247
if (type->hasUnnamedOrLocalType()) {
247-
clang::EnumDecl *enumDecl = type->getAs<clang::EnumType>()->getDecl();
248248
return std::make_shared<PrimitiveType>(getTypeFromTypeMap(
249249
enumDecl->getIntegerType().getUnqualifiedType().getAsString()));
250250
}
251-
return translateRecordOrEnum(type);
251+
std::string name = enumDecl->getNameAsString();
252+
253+
if (name.empty()) {
254+
name = enumDecl->getTypedefNameForAnonDecl()->getNameAsString();
255+
return ir.getTypeDefWithName(name);
256+
}
257+
assert(!name.empty());
258+
return ir.getEnumWithName(name);
252259
}

bindgen/TypeTranslator.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class TypeTranslator {
3535
*/
3636
std::map<std::string, std::string> typeMap;
3737

38-
std::shared_ptr<Type> translateRecordOrEnum(const clang::QualType &qtpe);
38+
std::shared_ptr<Type>
39+
translateNonAnonymousRecord(const clang::QualType &qtpe);
3940

4041
std::shared_ptr<Type> translateRecord(const clang::QualType &qtpe);
4142

bindgen/ir/Enum.cpp

+11-5
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ Enum::Enum(std::string name, std::string type,
1515

1616
bool Enum::isAnonymous() const { return name.empty(); }
1717

18-
std::shared_ptr<TypeDef> Enum::generateTypeDef() {
19-
return std::make_shared<TypeDef>(getTypeName(), shared_from_this(),
20-
nullptr);
18+
std::string Enum::getDefinition() {
19+
return " type " + getTypeAlias() + " = " + PrimitiveType::str() + "\n";
2120
}
2221

2322
llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Enum &e) {
@@ -51,7 +50,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Enum &e) {
5150

5251
std::string Enum::getName() const { return name; }
5352

54-
std::string Enum::getTypeName() const {
53+
std::string Enum::getTypeAlias() const {
5554
assert(!isAnonymous());
56-
return "enum " + name;
55+
return "enum_" + name;
56+
}
57+
58+
std::string Enum::str(const LocationManager &locationManager) const {
59+
if (locationManager.isImported(*location)) {
60+
return locationManager.getImportedType(*location, getTypeAlias());
61+
}
62+
return getTypeAlias();
5763
}

bindgen/ir/Enum.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ class Enum : public PrimitiveType, public LocatableType {
2727

2828
bool isAnonymous() const;
2929

30-
std::shared_ptr<TypeDef> generateTypeDef();
30+
std::string getDefinition();
3131

3232
std::string getName() const;
3333

3434
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const Enum &e);
3535

36-
std::string getTypeName() const;
36+
std::string getTypeAlias() const;
37+
38+
std::string str(const LocationManager &locationManager) const override;
3739

3840
private:
3941
std::string name; // might be empty

bindgen/ir/IR.cpp

+18-7
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ std::shared_ptr<TypeDef> IR::addTypeDef(std::string name,
2222
return typeDefs.back();
2323
}
2424

25-
void IR::addEnum(std::string name, const std::string &type,
26-
std::vector<Enumerator> enumerators,
27-
std::shared_ptr<Location> location) {
25+
std::shared_ptr<Enum> IR::addEnum(std::string name, const std::string &type,
26+
std::vector<Enumerator> enumerators,
27+
std::shared_ptr<Location> location) {
2828
std::shared_ptr<Enum> e = std::make_shared<Enum>(
2929
std::move(name), type, std::move(enumerators), std::move(location));
30+
3031
enums.push_back(e);
31-
if (!e->isAnonymous()) {
32-
typeDefs.push_back(e->generateTypeDef());
33-
}
32+
33+
return e;
3434
}
3535

3636
std::shared_ptr<TypeDef>
@@ -89,7 +89,7 @@ void IR::addVarDefine(std::string name, std::shared_ptr<Variable> variable) {
8989
bool IR::libObjEmpty() const {
9090
return functions.empty() && !shouldOutputType(typeDefs) &&
9191
!shouldOutputType(structs) && !shouldOutputType(unions) &&
92-
varDefines.empty() && variables.empty();
92+
varDefines.empty() && variables.empty() && enums.empty();
9393
}
9494

9595
llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
@@ -120,6 +120,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
120120

121121
std::vector<std::shared_ptr<const Type>> visitedTypes;
122122

123+
for (const auto &e : ir.enums) {
124+
visitedTypes.clear();
125+
if (!e->isAnonymous() && ir.shouldOutput(e, visitedTypes)) {
126+
s << e->getDefinition();
127+
}
128+
}
129+
123130
for (const auto &typeDef : ir.typeDefs) {
124131
visitedTypes.clear();
125132
if (ir.shouldOutputTypeDef(typeDef, visitedTypes)) {
@@ -435,6 +442,10 @@ std::shared_ptr<TypeDef> IR::getTypeDefWithName(const std::string &name) const {
435442
return getDeclarationWithName(typeDefs, name);
436443
}
437444

445+
std::shared_ptr<Enum> IR::getEnumWithName(const std::string &name) const {
446+
return getDeclarationWithName(enums, name);
447+
}
448+
438449
template <typename T>
439450
T IR::getDeclarationWithName(const std::vector<T> &declarations,
440451
const std::string &name) const {

bindgen/ir/IR.h

+5-6
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,9 @@ class IR {
2929
std::shared_ptr<Type> type,
3030
std::shared_ptr<Location> location);
3131

32-
/**
33-
* @return type alias for the enum
34-
*/
35-
void addEnum(std::string name, const std::string &type,
36-
std::vector<Enumerator> enumerators,
37-
std::shared_ptr<Location> location);
32+
std::shared_ptr<Enum> addEnum(std::string name, const std::string &type,
33+
std::vector<Enumerator> enumerators,
34+
std::shared_ptr<Location> location);
3835

3936
std::shared_ptr<TypeDef>
4037
addStruct(std::string name, std::vector<std::shared_ptr<Field>> fields,
@@ -76,6 +73,8 @@ class IR {
7673

7774
std::shared_ptr<TypeDef> getTypeDefWithName(const std::string &name) const;
7875

76+
std::shared_ptr<Enum> getEnumWithName(const std::string &name) const;
77+
7978
private:
8079
/**
8180
* @return true if helper methods will be generated for this library

bindgen/ir/TypeDef.cpp

+8-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "TypeDef.h"
22
#include "../Utils.h"
3-
#include "Enum.h"
43
#include "Struct.h"
54
#include "Union.h"
65
#include <sstream>
@@ -82,12 +81,7 @@ std::shared_ptr<Location> TypeDef::getLocation() const {
8281
if (recordPointer) {
8382
return recordPointer->getLocation();
8483
}
85-
auto enumPointer = std::dynamic_pointer_cast<const Enum>(type);
86-
if (enumPointer) {
87-
return enumPointer->getLocation();
88-
}
89-
throw std::logic_error(
90-
"Generated typedef may reference only struct, union or enum");
84+
throw std::logic_error("Generated typedef may reference only records.");
9185
}
9286

9387
bool TypeDef::hasLocation() const { return location || type; }
@@ -105,8 +99,7 @@ bool TypeDef::findAllCycles(
10599
}
106100

107101
std::shared_ptr<const Type> TypeDef::unrollTypedefs() const {
108-
if (!type || isInstanceOf<Struct>(type.get()) ||
109-
isInstanceOf<Union>(type.get()) || isInstanceOf<Enum>(type.get())) {
102+
if (isGenerated()) {
110103
return std::make_shared<TypeDef>(name, type, nullptr);
111104
}
112105
return type->unrollTypedefs();
@@ -115,9 +108,7 @@ std::shared_ptr<const Type> TypeDef::unrollTypedefs() const {
115108
std::shared_ptr<const Type>
116109
TypeDef::replaceType(const std::shared_ptr<const Type> &type,
117110
const std::shared_ptr<const Type> &replacement) const {
118-
if (!this->type || isInstanceOf<Struct>(this->type.get()) ||
119-
isInstanceOf<Union>(this->type.get()) ||
120-
isInstanceOf<Enum>(this->type.get())) {
111+
if (isGenerated()) {
121112
return std::make_shared<TypeDef>(name, this->type, nullptr);
122113
}
123114
if (*this->type == *type) {
@@ -128,3 +119,8 @@ TypeDef::replaceType(const std::shared_ptr<const Type> &type,
128119
}
129120

130121
bool TypeDef::wrapperForOpaqueType() const { return !type; }
122+
123+
bool TypeDef::isGenerated() const {
124+
return !this->type || isInstanceOf<Struct>(this->type.get()) ||
125+
isInstanceOf<Union>(this->type.get());
126+
}

bindgen/ir/TypeDef.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ class TypeDef : public TypeAndName, public LocatableType {
4747

4848
/**
4949
* @return location of the typedef is it is not generated otherwise
50-
* location of referenced type (struct, union or enum).
50+
* location of referenced record.
5151
*/
5252
std::shared_ptr<Location> getLocation() const override;
53+
54+
private:
55+
bool isGenerated() const;
5356
};
5457

5558
#endif // SCALA_NATIVE_BINDGEN_TYPEDEF_H

bindgen/ir/types/PrimitiveType.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
PrimitiveType::PrimitiveType(std::string type) : type(std::move(type)) {}
66

7+
std::string PrimitiveType::str() const { return handleReservedWords(type); }
8+
79
std::string PrimitiveType::str(const LocationManager &locationManager) const {
8-
return handleReservedWords(type);
10+
return str();
911
}
1012

1113
std::string PrimitiveType::getType() const { return type; }

bindgen/ir/types/PrimitiveType.h

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class PrimitiveType : virtual public Type {
1717
const std::shared_ptr<const Type> &type, bool stopOnTypeDefs,
1818
std::vector<std::shared_ptr<const Type>> &visitedTypes) const override;
1919

20+
std::string str() const;
21+
2022
std::string str(const LocationManager &locationManager) const override;
2123

2224
bool operator==(const Type &other) const override;

bindgen/visitor/TreeVisitor.cpp

+28-8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ bool TreeVisitor::VisitFunctionDecl(clang::FunctionDecl *func) {
3434
bool TreeVisitor::VisitTypedefDecl(clang::TypedefDecl *tpdef) {
3535
std::string name = tpdef->getName();
3636

37+
if (isAliasForAnonymousEnum(tpdef)) {
38+
/* typedef was already created */
39+
return true;
40+
}
41+
3742
std::shared_ptr<Type> type =
3843
typeTranslator.translate(tpdef->getUnderlyingType());
3944
if (type) {
@@ -42,25 +47,40 @@ bool TreeVisitor::VisitTypedefDecl(clang::TypedefDecl *tpdef) {
4247
return true;
4348
}
4449

45-
bool TreeVisitor::VisitEnumDecl(clang::EnumDecl *enumdecl) {
46-
std::string name = enumdecl->getNameAsString();
50+
bool TreeVisitor::isAliasForAnonymousEnum(clang::TypedefDecl *tpdef) const {
51+
clang::QualType underlyingType = tpdef->getUnderlyingType();
52+
if (!underlyingType->isEnumeralType()) {
53+
return false;
54+
}
55+
const clang::EnumType *enumType = underlyingType->getAs<clang::EnumType>();
56+
return enumType->getDecl()->getTypedefNameForAnonDecl();
57+
}
58+
59+
bool TreeVisitor::VisitEnumDecl(clang::EnumDecl *enumDecl) {
60+
std::string name = enumDecl->getNameAsString();
4761

48-
if (name.empty() && enumdecl->getTypedefNameForAnonDecl()) {
49-
name = enumdecl->getTypedefNameForAnonDecl()->getNameAsString();
62+
clang::TypedefNameDecl *typedefName = enumDecl->getTypedefNameForAnonDecl();
63+
if (name.empty() && typedefName) {
64+
name = typedefName->getNameAsString();
5065
}
5166

5267
std::vector<Enumerator> enumerators;
5368

54-
for (const clang::EnumConstantDecl *en : enumdecl->enumerators()) {
69+
for (const clang::EnumConstantDecl *en : enumDecl->enumerators()) {
5570
int64_t value = en->getInitVal().getSExtValue();
5671
enumerators.emplace_back(en->getNameAsString(), value);
5772
}
5873

5974
std::string scalaType = typeTranslator.getTypeFromTypeMap(
60-
enumdecl->getIntegerType().getUnqualifiedType().getAsString());
75+
enumDecl->getIntegerType().getUnqualifiedType().getAsString());
6176

62-
ir.addEnum(name, scalaType, std::move(enumerators),
63-
typeTranslator.getLocation(enumdecl));
77+
std::shared_ptr<Enum> e =
78+
ir.addEnum(name, scalaType, std::move(enumerators),
79+
typeTranslator.getLocation(enumDecl));
80+
81+
if (typedefName) {
82+
ir.addTypeDef(name, e, typeTranslator.getLocation(typedefName));
83+
}
6484

6585
return true;
6686
}

bindgen/visitor/TreeVisitor.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class TreeVisitor : public clang::RecursiveASTVisitor<TreeVisitor> {
1111
TypeTranslator typeTranslator;
1212
IR &ir;
1313

14+
bool isAliasForAnonymousEnum(clang::TypedefDecl *tpdef) const;
15+
1416
public:
1517
TreeVisitor(clang::CompilerInstance *CI, IR &ir)
1618
: astContext(&(CI->getASTContext())), typeTranslator(astContext, ir),
@@ -20,7 +22,7 @@ class TreeVisitor : public clang::RecursiveASTVisitor<TreeVisitor> {
2022

2123
virtual bool VisitFunctionDecl(clang::FunctionDecl *func);
2224
virtual bool VisitTypedefDecl(clang::TypedefDecl *tpdef);
23-
virtual bool VisitEnumDecl(clang::EnumDecl *enumdecl);
25+
virtual bool VisitEnumDecl(clang::EnumDecl *enumDecl);
2426
virtual bool VisitRecordDecl(clang::RecordDecl *record);
2527
virtual bool VisitVarDecl(clang::VarDecl *VD);
2628
};

tests/samples/IncludesHeader.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import scala.scalanative.native._
66
@native.link("bindgentests")
77
@native.extern
88
object IncludesHeader {
9+
type enum_semester = native.CUnsignedInt
910
type size = native.CInt
1011
type struct_metadata = native.CStruct2[native.CUnsignedInt, native.CString]
1112
type metadata = struct_metadata
1213
type struct_document = native.CStruct1[metadata]
13-
type enum_semester = native.CUnsignedInt
1414
type struct_courseInfo = native.CStruct2[native.CString, enum_semester]
1515
def getSize(d: native.Ptr[struct_document]): size = native.extern
1616
}

tests/samples/PrivateMembers.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import scala.scalanative.native._
66
@native.link("bindgentests")
77
@native.extern
88
object PrivateMembers {
9+
type enum___privateEnum = native.CUnsignedInt
10+
type enum_enumWithPrivateMembers = native.CUnsignedInt
911
type pid_t = native.CInt
1012
type __private_type = native.CInt
1113
type struct_structWithPrivateType = native.CStruct2[native.CInt, __private_type]
1214
type union___unionWithPrivateName = native.CArray[Byte, native.Nat._4]
1315
type struct_structWithPrivateStruct = native.CStruct1[native.Ptr[struct_structWithPrivateType]]
1416
type struct_normalStruct = native.CStruct1[native.CInt]
15-
type enum___privateEnum = native.CUnsignedInt
16-
type enum_enumWithPrivateMembers = native.CUnsignedInt
1717
type struct_privateStructWithTypedef = native.CStruct1[native.Ptr[__private_type]]
1818
type privateStructWithTypedef = struct_privateStructWithTypedef
1919
type privateStructWithTypedefPtr = native.Ptr[struct_privateStructWithTypedef]

tests/samples/Struct.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ import scala.scalanative.native._
66
@native.link("bindgentests")
77
@native.extern
88
object Struct {
9+
type enum_pointIndex = native.CUnsignedInt
10+
type enum_struct_op = native.CUnsignedInt
911
type struct_point = native.CStruct2[native.CInt, native.CInt]
1012
type point = struct_point
1113
type struct_points = native.CStruct2[struct_point, point]
12-
type enum_pointIndex = native.CUnsignedInt
1314
type point_s = native.Ptr[struct_point]
1415
type struct_bigStruct = native.CArray[Byte, native.Nat.Digit[native.Nat._1, native.Nat.Digit[native.Nat._1, native.Nat._2]]]
1516
type struct_anonymous_0 = native.CStruct2[native.CChar, native.CInt]
1617
type struct_structWithAnonymousStruct = native.CStruct2[native.CInt, struct_anonymous_0]
1718
type struct_packedStruct = native.CStruct1[native.CChar]
1819
type struct_bitFieldStruct = native.CArray[Byte, native.Nat._2]
1920
type struct_bitFieldOffsetDivByEight = native.CArray[Byte, native.Nat._4]
20-
type enum_struct_op = native.CUnsignedInt
2121
def setPoints(points: native.Ptr[struct_points], x1: native.CInt, y1: native.CInt, x2: native.CInt, y2: native.CInt): Unit = native.extern
2222
def getPoint(points: native.Ptr[struct_points], pointIndex: enum_pointIndex): native.CInt = native.extern
2323
def createPoint(): native.Ptr[struct_point] = native.extern

0 commit comments

Comments
 (0)