]> granicus.if.org Git - clang/commitdiff
PR19010: Make sure we initialize (empty) indirect base class subobjects when
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 5 Mar 2014 23:32:50 +0000 (23:32 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 5 Mar 2014 23:32:50 +0000 (23:32 +0000)
evaluating trivial default initialization of a literal class type.

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

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

index e172c9147858ba81618fcb46db27b9c12e74a25b..92eef5e6fc1b2c6769b8c48791e9a520c8f373b9 100644 (file)
@@ -5117,16 +5117,15 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
     if (!Result.isUninit())
       return true;
 
-    if (ZeroInit)
-      return ZeroInitialization(E);
-
-    const CXXRecordDecl *RD = FD->getParent();
-    if (RD->isUnion())
-      Result = APValue((FieldDecl*)0);
-    else
-      Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
-                       std::distance(RD->field_begin(), RD->field_end()));
-    return true;
+    // We can get here in two different ways:
+    //  1) We're performing value-initialization, and should zero-initialize
+    //     the object, or
+    //  2) We're performing default-initialization of an object with a trivial
+    //     constexpr default constructor, in which case we should start the
+    //     lifetimes of all the base subobjects (there can be no data member
+    //     subobjects in this case) per [basic.life]p1.
+    // Either way, ZeroInitialization is appropriate.
+    return ZeroInitialization(E);
   }
 
   const FunctionDecl *Definition = 0;
@@ -5606,19 +5605,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
     if (HadZeroInit)
       return true;
 
-    if (ZeroInit) {
-      ImplicitValueInitExpr VIE(Type);
-      return EvaluateInPlace(*Value, Info, Subobject, &VIE);
-    }
-
-    const CXXRecordDecl *RD = FD->getParent();
-    if (RD->isUnion())
-      *Value = APValue((FieldDecl*)0);
-    else
-      *Value =
-          APValue(APValue::UninitStruct(), RD->getNumBases(),
-                  std::distance(RD->field_begin(), RD->field_end()));
-    return true;
+    // See RecordExprEvaluator::VisitCXXConstructExpr for explanation.
+    ImplicitValueInitExpr VIE(Type);
+    return EvaluateInPlace(*Value, Info, Subobject, &VIE);
   }
 
   const FunctionDecl *Definition = 0;
index 4e617776439d678c67b28f22ed7310378efdc941..574e9b389f341a1e7baf4ccd849addc13290a4db 100644 (file)
@@ -1863,3 +1863,13 @@ namespace BuiltinStrlen {
   constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator.
   constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} expected-note {{one-past-the-end}}
 }
+
+namespace PR19010 {
+  struct Empty {};
+  struct Empty2 : Empty {};
+  struct Test : Empty2 {
+    constexpr Test() {}
+    Empty2 array[2];
+  };
+  void test() { constexpr Test t; }
+}