[cfe-commits] r111802 - in /cfe/trunk: lib/Sema/SemaExpr.cpp lib/Sema/SemaInit.cpp test/SemaCXX/default-constructor-initializers.cpp

Chandler Carruth chandlerc at gmail.com
Mon Aug 23 00:55:51 PDT 2010


Author: chandlerc
Date: Mon Aug 23 02:55:51 2010
New Revision: 111802

URL: http://llvm.org/viewvc/llvm-project?rev=111802&view=rev
Log:
Relax the construction of a definition for implicit, trivial default
constructors. We perform semantic checking when creating the definition, and
this isn't needed in certain contexts (value initialization) but is in others
(default initialization). This fixes PR7948.

We add explicit code to the default initialization path to ensure the
definition is both present and valid.

Doug, please review. I think this follows your latest suggestion, and it ended
up remarkably cleaner than I anticipated. Also let me know if similar logic
should be followed for destructors and copy-constructors.

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=111802&r1=111801&r2=111802&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 23 02:55:51 2010
@@ -7654,8 +7654,10 @@
   if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
     unsigned TypeQuals;
     if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
-        if (!Constructor->isUsed(false))
-          DefineImplicitDefaultConstructor(Loc, Constructor);
+      if (Constructor->getParent()->hasTrivialConstructor())
+        return;
+      if (!Constructor->isUsed(false))
+        DefineImplicitDefaultConstructor(Loc, Constructor);
     } else if (Constructor->isImplicit() &&
                Constructor->isCopyConstructor(TypeQuals)) {
       if (!Constructor->isUsed(false))

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=111802&r1=111801&r2=111802&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Aug 23 02:55:51 2010
@@ -2862,8 +2862,8 @@
   //       constructor for T is called (and the initialization is ill-formed if
   //       T has no accessible default constructor);
   if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
-    return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
-                                        Sequence);
+    TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence);
+    return;
   }
   
   //     - otherwise, no initialization is performed.
@@ -3838,14 +3838,25 @@
       SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
                              ? Kind.getEqualLoc()
                              : Kind.getLocation();
-          
+
+      if (Kind.getKind() == InitializationKind::IK_Default) {
+        // Force even a trivial, implicit default constructor to be
+        // semantically checked. We do this explicitly because we don't build
+        // the definition for completely trivial constructors.
+        CXXRecordDecl *ClassDecl = Constructor->getParent();
+        assert(ClassDecl && "No parent class for constructor.");
+        if (Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
+            ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false))
+          S.DefineImplicitDefaultConstructor(Loc, Constructor);
+      }
+
       // Determine the arguments required to actually perform the constructor
       // call.
       if (S.CompleteConstructorCall(Constructor, move(Args), 
                                     Loc, ConstructorArgs))
         return S.ExprError();
           
-      // Build the expression that constructs a temporary.
+      
       if (Entity.getKind() == InitializedEntity::EK_Temporary &&
           NumArgs != 1 && // FIXME: Hack to work around cast weirdness
           (Kind.getKind() == InitializationKind::IK_Direct ||

Modified: cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp?rev=111802&r1=111801&r2=111802&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp (original)
+++ cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp Mon Aug 23 02:55:51 2010
@@ -43,7 +43,6 @@
 
 // More tests
 
-
 struct Z1 { // expected-error {{must explicitly initialize the reference member 'z'}} \
             // expected-error {{must explicitly initialize the const member 'c1'}}
   int& z;       // expected-note {{declared here}}
@@ -51,5 +50,12 @@
   volatile int v1;
 };
 
+// Test default initialization which *requires* a constructor call for non-POD.
 Z1 z1; // expected-note {{first required here}}
 
+// Ensure that value initialization doesn't use trivial implicit constructors.
+namespace PR7948 {
+  // Note that this is also non-POD to ensure we don't just special case PODs.
+  struct S { const int x; ~S(); };
+  const S arr[2] = { { 42 } };
+}





More information about the cfe-commits mailing list