llvm.org GIT mirror llvm / 8b8fa7b
Casting.h: Automatically handle isa<Base>(Derived). Additionally, all such cases are handled with no dynamic check. All `classof()` of the form class Foo { [...] static bool classof(const Bar *) { return true; } [...] } where Foo is an ancestor of Bar are no longer necessary. Don't write them! Note: The exact test is `is_base_of<Foo, Bar>`, which is non-strict, so that Foo is considered an ancestor of itself. This leads to the following rule of thumb for LLVM-style RTTI: The argument type of `classof()` should be a strict ancestor. For more information about implementing LLVM-style RTTI, see docs/HowToSetUpLLVMStyleRTTI.rst git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165765 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Silva 8 years ago
2 changed file(s) with 63 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
1414 #ifndef LLVM_SUPPORT_CASTING_H
1515 #define LLVM_SUPPORT_CASTING_H
1616
17 #include "llvm/Support/type_traits.h"
1718 #include
1819
1920 namespace llvm {
4344 // The core of the implementation of isa is here; To and From should be
4445 // the names of classes. This template can be specialized to customize the
4546 // implementation of isa<> without rewriting it from scratch.
46 template >
47 template , typename Enabler = void>
4748 struct isa_impl {
4849 static inline bool doit(const From &Val) {
4950 return To::classof(&Val);
5051 }
52 };
53
54 /// \brief Always allow upcasts, and perform no dynamic check for them.
55 template
56 struct isa_impl
57 typename llvm::enable_if_c<
58 llvm::is_base_of::value
59 >::type
60 > {
61 static inline bool doit(const From &) { return true; }
5162 };
5263
5364 template struct isa_impl_cl {
152152 } // anonymous namespace
153153
154154 bar *llvm::fub() { return 0; }
155
156 namespace {
157 namespace inferred_upcasting {
158 // This test case verifies correct behavior of inferred upcasts when the
159 // types are statically known to be OK to upcast. This is the case when,
160 // for example, Derived inherits from Base, and we do `isa(Derived)`.
161
162 // Note: This test will actually fail to compile without inferred
163 // upcasting.
164
165 class Base {
166 public:
167 // No classof. We are testing that the upcast is inferred.
168 Base() {}
169 };
170
171 class Derived : public Base {
172 public:
173 Derived() {}
174 };
175
176 // Even with no explicit classof() in Base, we should still be able to cast
177 // Derived to its base class.
178 TEST(CastingTest, UpcastIsInferred) {
179 Derived D;
180 EXPECT_TRUE(isa(D));
181 Base *BP = dyn_cast(&D);
182 EXPECT_TRUE(BP != NULL);
183 }
184
185
186 // This test verifies that the inferred upcast takes precedence over an
187 // explicitly written one. This is important because it verifies that the
188 // dynamic check gets optimized away.
189 class UseInferredUpcast {
190 public:
191 int Dummy;
192 static bool classof(const UseInferredUpcast *) {
193 return false;
194 }
195 };
196
197 TEST(CastingTest, InferredUpcastTakesPrecedence) {
198 UseInferredUpcast UIU;
199 // Since the explicit classof() returns false, this will fail if the
200 // explicit one is used.
201 EXPECT_TRUE(isa(&UIU));
202 }
203
204 } // end namespace inferred_upcasting
205 } // end anonymous namespace