constexpr: support for evaluation and codegen of typeid constants.

llvm-svn: 147290
This commit is contained in:
Richard Smith 2011-12-27 12:18:28 +00:00
parent b668401b2e
commit 6e52514c5d
6 changed files with 81 additions and 3 deletions

View File

@ -33,6 +33,9 @@ def note_constexpr_past_end : Note<
"%select{temporary|%2}1 is not a constant expression">;
def note_constexpr_var_init_non_constant : Note<
"initializer of %0 is not a constant expression">;
def note_constexpr_typeid_polymorphic : Note<
"typeid applied to expression of polymorphic type %0 is "
"not allowed in a constant expression">;
def note_constexpr_temporary_here : Note<"temporary created here">;
def note_constexpr_literal_here : Note<"literal written here">;
def note_constexpr_depth_limit_exceeded : Note<

View File

@ -697,6 +697,7 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
case Expr::PredefinedExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::CXXTypeidExprClass:
return true;
case Expr::CallExprClass:
return IsStringLiteralCall(cast<CallExpr>(E));
@ -2329,6 +2330,7 @@ public:
// - Literals
// * CompoundLiteralExpr in C
// * StringLiteral
// * CXXTypeidExpr
// * PredefinedExpr
// * ObjCStringLiteralExpr
// * ObjCEncodeExpr
@ -2356,6 +2358,7 @@ public:
bool VisitMemberExpr(const MemberExpr *E);
bool VisitStringLiteral(const StringLiteral *E) { return Success(E); }
bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); }
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
bool VisitUnaryDeref(const UnaryOperator *E);
@ -2451,6 +2454,19 @@ LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
return Success(E);
}
bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
if (E->isTypeOperand())
return Success(E);
CXXRecordDecl *RD = E->getExprOperand()->getType()->getAsCXXRecordDecl();
if (RD && RD->isPolymorphic()) {
Info.Diag(E->getExprLoc(), diag::note_constexpr_typeid_polymorphic)
<< E->getExprOperand()->getType()
<< E->getExprOperand()->getSourceRange();
return false;
}
return Success(E);
}
bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
// Handle static data members.
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) {

View File

@ -934,6 +934,15 @@ public:
return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
}
case Expr::CXXTypeidExprClass: {
CXXTypeidExpr *Typeid = cast<CXXTypeidExpr>(E);
QualType T;
if (Typeid->isTypeOperand())
T = Typeid->getTypeOperand();
else
T = Typeid->getExprOperand()->getType();
return CGM.GetAddrOfRTTIDescriptor(T);
}
}
return 0;

View File

@ -280,11 +280,10 @@ namespace std {
namespace TypeId {
struct S { virtual void f(); };
constexpr S *p = 0;
constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}}
constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} expected-note {{typeid applied to expression of polymorphic type 'TypeId::S'}}
// FIXME: Implement typeid evaluation.
struct T {} t;
constexpr const std::type_info &ti2 = typeid(t); // unexpected-error {{must be initialized by a constant expression}}
constexpr const std::type_info &ti2 = typeid(t);
}
// - a new-expression (5.3.4);

View File

@ -0,0 +1,30 @@
// RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -o - | FileCheck %s
#include <typeinfo>
namespace Test1 {
struct Item {
const std::type_info &ti;
const char *name;
void *(*make)();
};
template<typename T> void *make_impl() { return new T; }
template<typename T> constexpr Item item(const char *name) {
return { typeid(T), name, make_impl<T> };
}
struct A { virtual ~A(); };
struct B : virtual A {};
struct C { int n; };
// FIXME: check we produce a constant array for this, once we support IRGen of
// folded structs and arrays.
constexpr Item items[] = {
item<A>("A"), item<B>("B"), item<C>("C"), item<int>("int")
};
// CHECK: @_ZN5Test11xE = constant %"class.std::type_info"* bitcast (i8** @_ZTIN5Test11AE to %"class.std::type_info"*), align 8
constexpr auto &x = items[0].ti;
}

View File

@ -6,6 +6,27 @@ namespace Test1 {
// PR7400
struct A { virtual void f(); };
// CHECK: @_ZN5Test16int_tiE = constant %"class.std::type_info"* bitcast (i8** @_ZTIi to %"class.std::type_info"*), align 8
const std::type_info &int_ti = typeid(int);
// CHECK: @_ZN5Test14A_tiE = constant %"class.std::type_info"* bitcast (i8** @_ZTIN5Test11AE to %"class.std::type_info"*), align 8
const std::type_info &A_ti = typeid(const volatile A &);
volatile char c;
// CHECK: @_ZN5Test14c_tiE = constant %"class.std::type_info"* bitcast (i8** @_ZTIc to %"class.std::type_info"*), align 8
const std::type_info &c_ti = typeid(c);
extern const double &d;
// CHECK: @_ZN5Test14d_tiE = constant %"class.std::type_info"* bitcast (i8** @_ZTId to %"class.std::type_info"*), align 8
const std::type_info &d_ti = typeid(d);
extern A &a;
// CHECK: @_ZN5Test14a_tiE = global
const std::type_info &a_ti = typeid(a);
// CHECK: define i8* @_ZN5Test11fEv
const char *f() {
try {