Skip to content

Commit 0953277

Browse files
committed
[Support] Extend ExtensibleRTTI utility to support basic multiple inheritance.
Clients can now pass multiple parent classes to RTTIExtends. Each parent class will be inherited from publicly (and non-virtually). The isa, cast, and dyn_cast methods will now work as expected for types with multiple inheritance.
1 parent 90767bc commit 0953277

File tree

2 files changed

+67
-19
lines changed

2 files changed

+67
-19
lines changed

llvm/include/llvm/Support/ExtensibleRTTI.h

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ class RTTIRoot {
8181
return ClassID == classID();
8282
}
8383

84-
/// Check whether this instance is a subclass of QueryT.
85-
template <typename QueryT>
86-
bool isA() const { return isA(QueryT::classID()); }
87-
8884
private:
8985
virtual void anchor();
9086

@@ -110,21 +106,37 @@ class RTTIRoot {
110106
/// static char ID;
111107
/// };
112108
///
113-
template <typename ThisT, typename ParentT>
114-
class RTTIExtends : public ParentT {
109+
template <typename ThisT, typename... ParentTs>
110+
class RTTIExtends : public ParentTs... {
115111
public:
116112
// Inherit constructors from ParentT.
117-
using ParentT::ParentT;
113+
using ParentTs::ParentTs...;
118114

119115
static const void *classID() { return &ThisT::ID; }
120116

121117
const void *dynamicClassID() const override { return &ThisT::ID; }
122118

119+
/// Check whether this instance is a subclass of QueryT.
120+
template <typename QueryT>
121+
bool isA() const { return isA(QueryT::classID()); }
122+
123123
bool isA(const void *const ClassID) const override {
124-
return ClassID == classID() || ParentT::isA(ClassID);
124+
return ClassID == classID() || parentsAreA<ParentTs...>(ClassID);
125+
}
126+
127+
template <typename T>
128+
static bool classof(const T *R) { return R->template isA<ThisT>(); }
129+
private:
130+
131+
template <typename T>
132+
bool parentsAreA(const void *const ClassID) const {
133+
return T::isA(ClassID);
125134
}
126135

127-
static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); }
136+
template <typename T, typename T2, typename... Ts>
137+
bool parentsAreA(const void *const ClassID) const {
138+
return T::isA(ClassID) || parentsAreA<T2, Ts...>(ClassID);
139+
}
128140
};
129141

130142
} // end namespace llvm

llvm/unittests/Support/ExtensibleRTTITest.cpp

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,24 @@ class MyDeeperDerivedType
3636
static char ID;
3737
};
3838

39+
class MyMultipleInheritanceType
40+
: public RTTIExtends<MyMultipleInheritanceType,
41+
MyDerivedType, MyOtherDerivedType> {
42+
public:
43+
static char ID;
44+
};
45+
3946
char MyBaseType::ID = 0;
4047
char MyDerivedType::ID = 0;
4148
char MyOtherDerivedType::ID = 0;
4249
char MyDeeperDerivedType::ID = 0;
50+
char MyMultipleInheritanceType::ID = 0;
4351

4452
TEST(ExtensibleRTTI, isa) {
4553
MyBaseType B;
4654
MyDerivedType D;
4755
MyDeeperDerivedType DD;
56+
MyMultipleInheritanceType MI;
4857

4958
EXPECT_TRUE(isa<MyBaseType>(B));
5059
EXPECT_FALSE(isa<MyDerivedType>(B));
@@ -60,26 +69,53 @@ TEST(ExtensibleRTTI, isa) {
6069
EXPECT_TRUE(isa<MyDerivedType>(DD));
6170
EXPECT_FALSE(isa<MyOtherDerivedType>(DD));
6271
EXPECT_TRUE(isa<MyDeeperDerivedType>(DD));
72+
73+
EXPECT_TRUE(isa<MyBaseType>(MI));
74+
EXPECT_TRUE(isa<MyDerivedType>(MI));
75+
EXPECT_TRUE(isa<MyOtherDerivedType>(MI));
76+
EXPECT_FALSE(isa<MyDeeperDerivedType>(MI));
77+
EXPECT_TRUE(isa<MyMultipleInheritanceType>(MI));
6378
}
6479

6580
TEST(ExtensibleRTTI, cast) {
66-
MyDerivedType D;
67-
MyBaseType &BD = D;
68-
69-
(void)cast<MyBaseType>(D);
70-
(void)cast<MyBaseType>(BD);
71-
(void)cast<MyDerivedType>(BD);
81+
MyMultipleInheritanceType MI;
82+
MyDerivedType &D = MI;
83+
MyOtherDerivedType &OD = MI;
84+
MyBaseType &B = D;
85+
86+
EXPECT_EQ(&cast<MyBaseType>(D), &B);
87+
EXPECT_EQ(&cast<MyDerivedType>(MI), &D);
88+
EXPECT_EQ(&cast<MyOtherDerivedType>(MI), &OD);
89+
EXPECT_EQ(&cast<MyMultipleInheritanceType>(MI), &MI);
7290
}
7391

7492
TEST(ExtensibleRTTI, dyn_cast) {
75-
MyBaseType B;
76-
MyDerivedType D;
93+
MyMultipleInheritanceType MI;
94+
MyDerivedType &D = MI;
95+
MyOtherDerivedType &OD = MI;
7796
MyBaseType &BD = D;
97+
MyBaseType &BOD = OD;
7898

79-
EXPECT_EQ(dyn_cast<MyDerivedType>(&B), nullptr);
80-
EXPECT_EQ(dyn_cast<MyDerivedType>(&D), &D);
8199
EXPECT_EQ(dyn_cast<MyBaseType>(&BD), &BD);
82100
EXPECT_EQ(dyn_cast<MyDerivedType>(&BD), &D);
101+
102+
EXPECT_EQ(dyn_cast<MyBaseType>(&BOD), &BOD);
103+
EXPECT_EQ(dyn_cast<MyOtherDerivedType>(&BOD), &OD);
104+
105+
EXPECT_EQ(dyn_cast<MyBaseType>(&D), &BD);
106+
EXPECT_EQ(dyn_cast<MyDerivedType>(&D), &D);
107+
EXPECT_EQ(dyn_cast<MyMultipleInheritanceType>(&D), &MI);
108+
109+
EXPECT_EQ(dyn_cast<MyBaseType>(&OD), &BOD);
110+
EXPECT_EQ(dyn_cast<MyOtherDerivedType>(&OD), &OD);
111+
EXPECT_EQ(dyn_cast<MyMultipleInheritanceType>(&OD), &MI);
112+
113+
EXPECT_EQ(dyn_cast<MyDerivedType>(&MI), &D);
114+
EXPECT_EQ(dyn_cast<MyMultipleInheritanceType>(&MI), &MI);
115+
116+
EXPECT_EQ(dyn_cast<MyDerivedType>(&MI), &D);
117+
EXPECT_EQ(dyn_cast<MyOtherDerivedType>(&MI), &OD);
118+
EXPECT_EQ(dyn_cast<MyMultipleInheritanceType>(&MI), &MI);
83119
}
84120

85121
} // namespace

0 commit comments

Comments
 (0)