]> granicus.if.org Git - clang/commitdiff
DR1535: only potentially-evaluated typeid expressions are disallowed in constant
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 17 Oct 2012 23:52:07 +0000 (23:52 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 17 Oct 2012 23:52:07 +0000 (23:52 +0000)
expressions, not *any* typeid on a polymorphic class type.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166156 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
test/CodeGenCXX/typeid-cxx11.cpp
test/SemaCXX/constant-expression-cxx11.cpp

index 323a1746bfbe18a168d50ff355670388ce3a9b4c..6e0b5fca60c097940c4b20e9a966a561a505127c 100644 (file)
@@ -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) {
index 940274e96575bc228e01c1f5dc53330c59d0e0b3..4e32d2dcb5a527b130b92e95a58e3d837c2d3e38 100644 (file)
@@ -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{});
+
 }
index 065e396b1527c98d3c8af04c144fc5e1f2ef6ebf..583344c793c8252b7b770708077650de17c25230 100644 (file)
@@ -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}}
+}