[cfe-commits] r131796 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp test/CXX/dcl.decl/dcl.init/p6.cpp

Douglas Gregor dgregor at apple.com
Sat May 21 10:52:48 PDT 2011


Author: dgregor
Date: Sat May 21 12:52:48 2011
New Revision: 131796

URL: http://llvm.org/viewvc/llvm-project?rev=131796&view=rev
Log:
Teach Sema::ActOnUninitializedDecl() not to try to interpret when one
should use a constructor to default-initialize a
variable. InitializationSequence knows the rules for default
initialization, better. Fixes <rdar://problem/8501008>.

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

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=131796&r1=131795&r2=131796&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat May 21 12:52:48 2011
@@ -5616,55 +5616,53 @@
       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);
   }

Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp?rev=131796&r1=131795&r2=131796&view=diff
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp Sat May 21 12:52:48 2011
@@ -45,6 +45,9 @@
 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() {

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp?rev=131796&r1=131795&r2=131796&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp Sat May 21 12:52:48 2011
@@ -14,3 +14,15 @@
   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





More information about the cfe-commits mailing list