forked from OSchip/llvm-project
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. llvm-svn: 290229
This commit is contained in:
parent
7779484313
commit
505ef81422
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -4539,23 +4539,21 @@ static void TryValueInitialization(Sema &S,
|
|||
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
|
||||
|
|
|
@ -170,6 +170,8 @@ namespace test7 {
|
|||
const B &b2 = B();
|
||||
const int b3 = B().n;
|
||||
|
||||
// CHECK-NOT: @_ZN5test7L2c1E
|
||||
// CHECK: call void @llvm.memset{{.*}} @_ZN5test7L2c1E
|
||||
// CHECK-NOT: @_ZN5test7L2c1E
|
||||
// CHECK: @_ZN5test7L2c2E
|
||||
// CHECK-NOT: @_ZN5test7L2c3E
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
|
@ -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}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue