forked from OSchip/llvm-project
constexpr: support for evaluation and codegen of typeid constants.
llvm-svn: 147290
This commit is contained in:
parent
b668401b2e
commit
6e52514c5d
|
@ -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<
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue