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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits