]> granicus.if.org Git - clang/commitdiff
In C++98/03, an uninitialized variable that has POD class type will be
authorDouglas Gregor <dgregor@apple.com>
Mon, 8 Mar 2010 02:45:10 +0000 (02:45 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 8 Mar 2010 02:45:10 +0000 (02:45 +0000)
uninitialized. This seems not to be the case in C++0x, where we still
call the (trivial) default constructor for a POD class
(!). Previously, we had implemented only the C++0x rules; now we
implement both. Fixes PR6536.

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

lib/Sema/SemaDecl.cpp
test/CXX/dcl.decl/dcl.init/p6.cpp
test/CodeGenCXX/internal-linkage.cpp
test/SemaCXX/statements.cpp

index 935adcf1b650fd4448bb5d15182d0686236f7a41..82dcd60aa0693e404695a198104b5eb198a7713a 100644 (file)
@@ -3809,24 +3809,38 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
       return;
     }
 
-    InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
-    InitializationKind Kind
-      = InitializationKind::CreateDefault(Var->getLocation());
+    const RecordType *Record
+      = Context.getBaseElementType(Type)->getAs<RecordType>();
+    if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x &&
+        cast<CXXRecordDecl>(Record->getDecl())->isPOD()) {
+      // C++03 [dcl.init]p9:
+      //   If no initializer is specified for an object, and the
+      //   object is of (possibly cv-qualified) non-POD class type (or
+      //   array thereof), the object shall be default-initialized; if
+      //   the object is of const-qualified type, the underlying class
+      //   type shall have a user-declared default
+      //   constructor. Otherwise, if no initializer is specified for
+      //   a non- static object, the object and its subobjects, if
+      //   any, have an indeterminate initial value); if the object
+      //   or any of its subobjects are of const-qualified type, the
+      //   program is ill-formed.
+      // FIXME: DPG thinks it is very fishy that C++0x disables this.
+    } else {
+      InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+      InitializationKind Kind
+        = InitializationKind::CreateDefault(Var->getLocation());
     
-    InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
-    OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
-                                            MultiExprArg(*this, 0, 0));
-    if (Init.isInvalid())
-      Var->setInvalidDecl();
-    else {
-      if (Init.get())
+      InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+      OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+                                              MultiExprArg(*this, 0, 0));
+      if (Init.isInvalid())
+        Var->setInvalidDecl();
+      else if (Init.get())
         Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
-
-      if (getLangOptions().CPlusPlus)
-        if (const RecordType *Record
-                        = Context.getBaseElementType(Type)->getAs<RecordType>())
-          FinalizeVarWithDestructor(Var, Record);
     }
+
+    if (!Var->isInvalidDecl() && getLangOptions().CPlusPlus && Record)
+      FinalizeVarWithDestructor(Var, Record);
   }
 }
 
index f627a199eca672f369854a142d2dff38578f2daf..df5dcfe97a74774dfa94c0ddf3e0e9ee0864589b 100644 (file)
@@ -5,7 +5,8 @@
 // If a program calls for the default initialization of an object of a
 // const-qualified type T, T shall be a class type with a
 // user-provided default constructor.
-struct NoUserDefault { };
+struct MakeNonPOD { MakeNonPOD(); };
+struct NoUserDefault : public MakeNonPOD { };
 struct HasUserDefault { HasUserDefault(); };
 
 void test_const_default_init() {
index 1ae0f08f86ee11cd08ef068ca58c4a2977eaaef5..4263891e57f51971ab302f3fba281378f6caf9e4 100644 (file)
@@ -1,11 +1,11 @@
 // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
 
-struct Global { };
-template<typename T> struct X { };
+struct Global { Global(); };
+template<typename T> struct X { X(); };
 
 
 namespace {
-  struct Anon { };
+  struct Anon { Anon(); };
 
   // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global
   Global anon0;
index 852086ed9a9497f19698de02605f3dc1d391b79b..0e27f4645af48aaf10ee8c95e1e1585f1af8a4f3 100644 (file)
@@ -15,3 +15,8 @@ void test2() {
 later:
   ;
 }
+
+namespace PR6536 {
+  struct A {};
+  void a() { goto out; A x; out: return; }
+}