diff options
-rw-r--r-- | lib/AST/ExprConstant.cpp | 18 | ||||
-rw-r--r-- | test/CodeGenCXX/typeid-cxx11.cpp | 8 | ||||
-rw-r--r-- | test/SemaCXX/constant-expression-cxx11.cpp | 11 |
3 files changed, 22 insertions, 15 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 323a1746bf..6e0b5fca60 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2886,19 +2886,13 @@ LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { } bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { - if (E->isTypeOperand()) + if (!E->isPotentiallyEvaluated()) return Success(E); - CXXRecordDecl *RD = E->getExprOperand()->getType()->getAsCXXRecordDecl(); - // FIXME: The standard says "a typeid expression whose operand is of a - // polymorphic class type" is not a constant expression, but it probably - // means "a typeid expression whose operand is potentially evaluated". - if (RD && RD->isPolymorphic()) { - Info.Diag(E, diag::note_constexpr_typeid_polymorphic) - << E->getExprOperand()->getType() - << E->getExprOperand()->getSourceRange(); - return false; - } - return Success(E); + + Info.Diag(E, diag::note_constexpr_typeid_polymorphic) + << E->getExprOperand()->getType() + << E->getExprOperand()->getSourceRange(); + return false; } bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { diff --git a/test/CodeGenCXX/typeid-cxx11.cpp b/test/CodeGenCXX/typeid-cxx11.cpp index 940274e965..4e32d2dcb5 100644 --- a/test/CodeGenCXX/typeid-cxx11.cpp +++ b/test/CodeGenCXX/typeid-cxx11.cpp @@ -18,13 +18,15 @@ 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. +// CHECK: @_ZN5Test1L5itemsE = internal constant [4 x {{.*}}] [{{.*}} @_ZTIN5Test11AE {{.*}}, {{.*}}, {{.*}} @_ZN5Test19make_implINS_1AEEEPvv }, {{.*}} @_ZTIN5Test11BE {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} @_ZTIN5Test11CE {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} @_ZTIi {{.*}} @_ZN5Test19make_implIiEEPvv }] 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 +// CHECK: @_ZN5Test11xE = constant %"class.std::type_info"* bitcast ({{.*}}* @_ZTIN5Test11AE to %"class.std::type_info"*), align 8 constexpr auto &x = items[0].ti; +// CHECK: @_ZN5Test11yE = constant %"class.std::type_info"* bitcast ({{.*}}* @_ZTIN5Test11BE to %"class.std::type_info"*), align 8 +constexpr auto &y = typeid(B{}); + } diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 065e396b15..583344c793 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1408,3 +1408,14 @@ namespace Void { static_assert(get(arr, 0) == 4, ""); // expected-error{{not an integral constant expression}} \ // expected-note{{in call to 'get(arr, 0)'}} } + +namespace std { struct type_info; } + +namespace TypeId { + struct A { virtual ~A(); }; + A f(); + A &g(); + constexpr auto &x = typeid(f()); + constexpr auto &y = typeid(g()); // expected-error{{constant expression}} \ + // expected-note{{typeid applied to expression of polymorphic type 'TypeId::A' is not allowed in a constant expression}} +} |