Implement typeid for class types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88843 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCXXExpr.cpp b/lib/CodeGen/CGCXXExpr.cpp
index abf8d16..565685c 100644
--- a/lib/CodeGen/CGCXXExpr.cpp
+++ b/lib/CodeGen/CGCXXExpr.cpp
@@ -334,3 +334,39 @@
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 c446c03..bd1c12c 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -271,6 +271,8 @@
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::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 5f8a196..743bf94 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -663,6 +663,8 @@
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
+ llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
+
//===--------------------------------------------------------------------===//
// Declaration Emission
//===--------------------------------------------------------------------===//
@@ -856,6 +858,7 @@
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 @@
bool IsInitializer = false);
void EmitCXXThrowExpr(const CXXThrowExpr *E);
-
+
//===--------------------------------------------------------------------===//
// Internal Helpers
//===--------------------------------------------------------------------===//
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index e644ff3..91e89fb 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -1286,6 +1286,8 @@
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";