]> granicus.if.org Git - clang/commitdiff
Teach Sema::ActOnUninitializedDecl() not to try to interpret when one
authorDouglas Gregor <dgregor@apple.com>
Sat, 21 May 2011 17:52:48 +0000 (17:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 21 May 2011 17:52:48 +0000 (17:52 +0000)
should use a constructor to default-initialize a
variable. InitializationSequence knows the rules for default
initialization, better. Fixes <rdar://problem/8501008>.

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

lib/Sema/SemaDecl.cpp
test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
test/CXX/dcl.decl/dcl.init/p6.cpp

index 2501e7f4d4a5855f3e3fbb1be174f0fc4eb4c045..a5a494877f2d8f052a667f92fa0738228134ed14 100644 (file)
@@ -5616,55 +5616,53 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
       return;
     }
 
-    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.
-      // C++0x [dcl.init]p11:
-      //   If no initializer is specified for an object, the object is
-      //   default-initialized; [...].
-    } else {
-      // Check for jumps past the implicit initializer.  C++0x
-      // clarifies that this applies to a "variable with automatic
-      // storage duration", not a "local variable".
-      // C++0x [stmt.dcl]p3
-      //   A program that jumps from a point where a variable with automatic
-      //   storage duration is not ins cope to a point where it is in scope is
-      //   ill-formed unless the variable has scalar type, class type with a
-      //   trivial defautl constructor and a trivial destructor, a cv-qualified
-      //   version of one of these types, or an array of one of the preceding
-      //   types and is declared without an initializer.
-      if (getLangOptions().CPlusPlus && Var->hasLocalStorage() && Record) {
+    // Check for jumps past the implicit initializer.  C++0x
+    // clarifies that this applies to a "variable with automatic
+    // storage duration", not a "local variable".
+    // C++0x [stmt.dcl]p3
+    //   A program that jumps from a point where a variable with automatic
+    //   storage duration is not in scope to a point where it is in scope is
+    //   ill-formed unless the variable has scalar type, class type with a
+    //   trivial default constructor and a trivial destructor, a cv-qualified
+    //   version of one of these types, or an array of one of the preceding
+    //   types and is declared without an initializer.
+    if (getLangOptions().CPlusPlus && Var->hasLocalStorage()) {
+      if (const RecordType *Record
+            = Context.getBaseElementType(Type)->getAs<RecordType>()) {
         CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl());
-        if (!getLangOptions().CPlusPlus0x ||
-            !CXXRecord->hasTrivialDefaultConstructor() ||
-            !CXXRecord->hasTrivialDestructor())
+        if ((!getLangOptions().CPlusPlus0x && !CXXRecord->isPOD()) ||
+            (getLangOptions().CPlusPlus0x &&
+             (!CXXRecord->hasTrivialDefaultConstructor() ||
+              (!CXXRecord->hasTrivialDestructor()))))
           getCurFunction()->setHasBranchProtectedScope();
       }
-
-      InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
-      InitializationKind Kind
-        = InitializationKind::CreateDefault(Var->getLocation());
-    
-      InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
-      ExprResult Init = InitSeq.Perform(*this, Entity, Kind,
-                                        MultiExprArg(*this, 0, 0));
-      if (Init.isInvalid())
-        Var->setInvalidDecl();
-      else if (Init.get())
-        Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
     }
+    
+    // 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.
+    // C++0x [dcl.init]p11:
+    //   If no initializer is specified for an object, the object is
+    //   default-initialized; [...].
+    InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+    InitializationKind Kind
+      = InitializationKind::CreateDefault(Var->getLocation());
+    
+    InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+    ExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+                                      MultiExprArg(*this, 0, 0));
+    if (Init.isInvalid())
+      Var->setInvalidDecl();
+    else if (Init.get())
+      Var->setInit(MaybeCreateExprWithCleanups(Init.get()));
 
     CheckCompleteVariableDeclaration(Var);
   }
index 1e5a823663ca9748653291de7c7e6d044d6979f0..ccadf416c9770110bf9754df9ff4903002854811 100644 (file)
@@ -45,6 +45,9 @@ namespace Test {
 namespace test1 {
   template <class T> class A {
     template <class U> friend void foo(A &, U); // expected-note {{not viable: 1st argument ('const A<int>') would lose const qualifier}}
+
+  public:
+    A();
   };
 
   void test() {
index da6f5b5369d03072abae8f2d09263fb141ef4665..514fd0c9b62038ec8a9d82d43a3ba165d79a9453 100644 (file)
@@ -14,3 +14,15 @@ void test_const_default_init() {
   const HasUserDefault x2;
   const int x3; // expected-error{{default initialization of an object of const type 'const int'}}
 }
+
+// rdar://8501008
+struct s0 {};
+struct s1 { static const s0 foo; };
+const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' requires a user-provided default constructor}}
+
+template<typename T>
+struct s2 {
+  static const s0 foo;
+};
+
+template<> const struct s0 s2<int>::foo; // okay