r290229 - Fix defaulted-functions-in-C++98 extension to give the functions the same

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 20 17:57:02 PST 2016


Author: rsmith
Date: Tue Dec 20 19:57:02 2016
New Revision: 290229

URL: http://llvm.org/viewvc/llvm-project?rev=290229&view=rev
Log:
Fix defaulted-functions-in-C++98 extension to give the functions the same
effect they would have in C++11. In particular, they do not prevent
value-initialization from performing zero-initialization, nor do they prevent a
struct from being an aggregate.

Added:
    cfe/trunk/test/SemaCXX/aggregate-init-cxx98.cpp
Modified:
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CodeGenCXX/global-init.cpp
    cfe/trunk/test/CodeGenCXX/value-init.cpp
    cfe/trunk/test/SemaCXX/aggregate-initialization.cpp

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=290229&r1=290228&r2=290229&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Dec 20 19:57:02 2016
@@ -534,15 +534,10 @@ void CXXRecordDecl::addedMember(Decl *D)
         SMKind |= SMF_MoveConstructor;
     }
 
-    // C++ [dcl.init.aggr]p1:
-    //   An aggregate is an array or a class with no user-declared
-    //   constructors [...].
     // C++11 [dcl.init.aggr]p1: DR1518
-    //  An aggregate is an array or a class with no user-provided, explicit, or
-    //  inherited constructors
-    if (getASTContext().getLangOpts().CPlusPlus11
-            ? (Constructor->isUserProvided() || Constructor->isExplicit())
-            : !Constructor->isImplicit())
+    //   An aggregate is an array or a class with no user-provided, explicit, or
+    //   inherited constructors
+    if (Constructor->isUserProvided() || Constructor->isExplicit())
       data().Aggregate = false;
   }
 

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=290229&r1=290228&r2=290229&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Dec 20 19:57:02 2016
@@ -4539,23 +4539,21 @@ static void TryValueInitialization(Sema
   if (const RecordType *RT = T->getAs<RecordType>()) {
     if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
       bool NeedZeroInitialization = true;
-      if (!S.getLangOpts().CPlusPlus11) {
-        // C++98:
-        // -- if T is a class type (clause 9) with a user-declared constructor
-        //    (12.1), then the default constructor for T is called (and the
-        //    initialization is ill-formed if T has no accessible default
-        //    constructor);
-        if (ClassDecl->hasUserDeclaredConstructor())
-          NeedZeroInitialization = false;
-      } else {
-        // C++11:
-        // -- if T is a class type (clause 9) with either no default constructor
-        //    (12.1 [class.ctor]) or a default constructor that is user-provided
-        //    or deleted, then the object is default-initialized;
-        CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl);
-        if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted())
-          NeedZeroInitialization = false;
-      }
+      // C++98:
+      // -- if T is a class type (clause 9) with a user-declared constructor
+      //    (12.1), then the default constructor for T is called (and the
+      //    initialization is ill-formed if T has no accessible default
+      //    constructor);
+      // C++11:
+      // -- if T is a class type (clause 9) with either no default constructor
+      //    (12.1 [class.ctor]) or a default constructor that is user-provided
+      //    or deleted, then the object is default-initialized;
+      //
+      // Note that the C++11 rule is the same as the C++98 rule if there are no
+      // defaulted or deleted constructors, so we just use it unconditionally.
+      CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl);
+      if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted())
+        NeedZeroInitialization = false;
 
       // -- if T is a (possibly cv-qualified) non-union class type without a
       //    user-provided or deleted default constructor, then the object is

Modified: cfe/trunk/test/CodeGenCXX/global-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-init.cpp?rev=290229&r1=290228&r2=290229&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/global-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/global-init.cpp Tue Dec 20 19:57:02 2016
@@ -171,6 +171,8 @@ namespace test7 {
   const int b3 = B().n;
 
   // CHECK-NOT: @_ZN5test7L2c1E
+  // CHECK: call void @llvm.memset{{.*}} @_ZN5test7L2c1E
+  // CHECK-NOT: @_ZN5test7L2c1E
   // CHECK: @_ZN5test7L2c2E
   // CHECK-NOT: @_ZN5test7L2c3E
   // CHECK: @_ZN5test7L2c4E

Modified: cfe/trunk/test/CodeGenCXX/value-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/value-init.cpp?rev=290229&r1=290228&r2=290229&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/value-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/value-init.cpp Tue Dec 20 19:57:02 2016
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
 
 struct A {
   virtual ~A();
@@ -315,6 +315,14 @@ namespace PR20256 {
   // CHECK: }
 }
 
+// CHECK-LABEL: define {{.*}}@_Z20explicitly_defaultedv
+int explicitly_defaulted() {
+  struct A { A() = default; int n; };
+  // CHECK: call void @llvm.memset
+  A a = A();
+  return a.n;
+} // CHECK-LABEL: }
+
 // CHECK-LABEL: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%"struct.zeroinit::X3"* %this) unnamed_addr
 // CHECK: call void @llvm.memset.p0i8.i64
 // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev

Added: cfe/trunk/test/SemaCXX/aggregate-init-cxx98.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-init-cxx98.cpp?rev=290229&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-init-cxx98.cpp (added)
+++ cfe/trunk/test/SemaCXX/aggregate-init-cxx98.cpp Tue Dec 20 19:57:02 2016
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++98 -verify %s
+
+struct A {
+  A() = default; // expected-warning {{C++11}}
+  int n;
+};
+A a = {0};

Modified: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=290229&r1=290228&r2=290229&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Tue Dec 20 19:57:02 2016
@@ -4,8 +4,6 @@
 
 // Verify that using an initializer list for a non-aggregate looks for
 // constructors..
-// Note that due to a (likely) standard bug, this is technically an aggregate,
-// but we do not treat it as one.
 struct NonAggr1 { // expected-note 2 {{candidate constructor}}
   NonAggr1(int, int) { } // expected-note {{candidate constructor}}
 




More information about the cfe-commits mailing list