diff options
author | Mike Stump <mrs@apple.com> | 2009-11-15 08:09:41 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-11-15 08:09:41 +0000 |
commit | c2e84ae9a6d25cea3e583c768e576b4c981ec028 (patch) | |
tree | 29b48802ad5ceeaafef5a900a5a983cd95d72bb2 | |
parent | 593564ba94ff854b7a410a4ca17ad34a90c5b761 (diff) |
Implement typeid for class types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88843 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCXXExpr.cpp | 36 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 5 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/rtti.cpp | 26 |
5 files changed, 76 insertions, 1 deletions
diff --git a/lib/CodeGen/CGCXXExpr.cpp b/lib/CodeGen/CGCXXExpr.cpp index abf8d16524..565685c6d0 100644 --- a/lib/CodeGen/CGCXXExpr.cpp +++ b/lib/CodeGen/CGCXXExpr.cpp @@ -334,3 +334,39 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { EmitBlock(DeleteEnd); } + +llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { + QualType Ty = E->getType(); + const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); + if (E->isTypeOperand()) { + QualType Ty = E->getTypeOperand(); + if (const RecordType *RT = Ty->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->isPolymorphic()) + return Builder.CreateBitCast(CGM.GenerateRttiRef(RD), LTy); + return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy); + } + // FIXME: return the rtti for the non-class static type. + ErrorUnsupported(E, "typeid expression"); + return 0; + } + Expr *subE = E->getExprOperand(); + if (const RecordType *RT = Ty->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->isPolymorphic()) { + // FIXME: if subE is an lvalue do + LValue Obj = EmitLValue(subE); + llvm::Value *This = Obj.getAddress(); + // FIXME: need to do a 0 check here for *p on This + llvm::Value *V = Builder.CreateBitCast(This, LTy->getPointerTo()->getPointerTo()); + V = Builder.CreateLoad(V, "vtable"); + V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); + V = Builder.CreateLoad(V); + return V; + } + return CGM.GenerateRtti(RD); + } + // FIXME: return rtti for the non-class static type. + ErrorUnsupported(E, "typeid expression"); + return 0; +} diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index c446c03689..bd1c12ccb3 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -271,6 +271,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E)); case Expr::CXXDefaultArgExprClass: return EmitLValue(cast<CXXDefaultArgExpr>(E)->getExpr()); + case Expr::CXXTypeidExprClass: + return EmitCXXTypeidLValue(cast<CXXTypeidExpr>(E)); case Expr::ObjCMessageExprClass: return EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E)); @@ -1465,6 +1467,12 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { } LValue +CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { + llvm::Value *Temp = EmitCXXTypeidExpr(E); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); +} + +LValue CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); PushCXXTemporary(E->getTemporary(), LV.getAddress()); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 5f8a1969f9..743bf947f8 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -663,6 +663,8 @@ public: llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); void EmitCXXDeleteExpr(const CXXDeleteExpr *E); + llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E); + //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// @@ -856,6 +858,7 @@ public: LValue EmitCXXConstructLValue(const CXXConstructExpr *E); LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E); LValue EmitCXXExprWithTemporariesLValue(const CXXExprWithTemporaries *E); + LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E); LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E); LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E); @@ -1022,7 +1025,7 @@ public: bool IsInitializer = false); void EmitCXXThrowExpr(const CXXThrowExpr *E); - + //===--------------------------------------------------------------------===// // Internal Helpers //===--------------------------------------------------------------------===// diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index e644ff3e4e..91e89fb711 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1286,6 +1286,8 @@ static bool isCharSpecialization(QualType T, const char *Name) { bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { // <substitution> ::= St # ::std:: + // FIXME: type_info == comes out as __ZNK3std9type_infoeqERKS0_ instead of + // __ZNKSt9type_infoeqERKS_ if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (isStdNamespace(NS)) { Out << "St"; diff --git a/test/CodeGenCXX/rtti.cpp b/test/CodeGenCXX/rtti.cpp index d5ac986b38..f89396dd11 100644 --- a/test/CodeGenCXX/rtti.cpp +++ b/test/CodeGenCXX/rtti.cpp @@ -1,6 +1,11 @@ // RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -O0 -S %s -o %t.s // RUN: FileCheck --input-file=%t.s %s +// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll +// RUN: FileCheck -check-prefix LL --input-file=%t.ll %s + +#include <typeinfo> + class test1_B1 { virtual void foo() { } }; @@ -87,3 +92,24 @@ class test1_D : public test1_B7 { // CHECK-NEXT: .quad (__ZTVN10__cxxabiv120__si_class_type_infoE) + 16 // CHECK-NEXT: .quad __ZTS8test1_B2 // CHECK-NEXT: .quad __ZTI8test1_B1 + + +class NP { }; +void test2_1(); +void test2_2(test1_D *dp) { + test1_D &d = *dp; + if (typeid(d) == typeid(test1_D)) + test2_1(); + if (typeid(NP) == typeid(test1_D)) + test2_1(); +} + +// CHECK-LL:define void @_Z7test2_2P7test1_D(%class.test1_B7* %dp) nounwind { +// CHECK-LL: %tmp1 = load %class.test1_B7** %d +// CHECK-LL-NEXT: %0 = bitcast %class.test1_B7* %tmp1 to %"class.std::type_info"*** +// CHECK-LL-NEXT: %vtable = load %"class.std::type_info"*** %0 +// CHECK-LL-NEXT: %1 = getelementptr inbounds %"class.std::type_info"** %vtable, i64 -1 +// CHECK-LL-NEXT: %2 = load %"class.std::type_info"** %1 +// CHECK-LL-NEXT: %call = call zeroext i1 @_ZNK3std9type_infoeqERKS0_(%"class.std::type_info"* %2, %"class.std::type_info"* bitcast (%1* @_ZTI7test1_D to %"class.std::type_info"*)) + +// CHECK-LL: %call2 = call zeroext i1 @_ZNK3std9type_infoeqERKS0_(%"class.std::type_info"* bitcast (%0* @_ZTI2NP to %"class.std::type_info"*), %"class.std::type_info"* bitcast (%1* @_ZTI7test1_D to %"class.std::type_info"*)) |