forked from OSchip/llvm-project
PR11650: Implement resolution of core issue 1301. Value initialization can't be
used to construct an object of union type with a deleted default constructor (plus fixes for some related value-initialization corner cases). llvm-svn: 150502
This commit is contained in:
parent
b2cde923cf
commit
1bfe068e71
|
@ -2699,9 +2699,14 @@ static bool TryListConstructionSpecialCases(Sema &S,
|
|||
QualType DestType,
|
||||
InitializationSequence &Sequence) {
|
||||
// C++11 [dcl.init.list]p3:
|
||||
// List-initialization of an object of type T is defined as follows:
|
||||
// - If the initializer list has no elements and T is a class type with
|
||||
// a default constructor, the object is value-initialized.
|
||||
// List-initialization of an object or reference of type T is defined as
|
||||
// follows:
|
||||
// - If T is an aggregate, aggregate initialization is performed.
|
||||
if (DestType->isAggregateType())
|
||||
return false;
|
||||
|
||||
// - Otherwise, if the initializer list has no elements and T is a class
|
||||
// type with a default constructor, the object is value-initialized.
|
||||
if (List->getNumInits() == 0) {
|
||||
if (CXXConstructorDecl *DefaultConstructor =
|
||||
S.LookupDefaultConstructor(DestRecordDecl)) {
|
||||
|
@ -3549,31 +3554,42 @@ static void TryValueInitialization(Sema &S,
|
|||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
InitializationSequence &Sequence) {
|
||||
// C++ [dcl.init]p5:
|
||||
// C++98 [dcl.init]p5, C++11 [dcl.init]p7:
|
||||
//
|
||||
// To value-initialize an object of type T means:
|
||||
QualType T = Entity.getType();
|
||||
|
||||
// -- if T is an array type, then each element is value-initialized;
|
||||
while (const ArrayType *AT = S.Context.getAsArrayType(T))
|
||||
T = AT->getElementType();
|
||||
T = S.Context.getBaseElementType(T);
|
||||
|
||||
if (const RecordType *RT = T->getAs<RecordType>()) {
|
||||
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
|
||||
// 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);
|
||||
//
|
||||
// FIXME: we really want to refer to a single subobject of the array,
|
||||
// but Entity doesn't have a way to capture that (yet).
|
||||
if (ClassDecl->hasUserDeclaredConstructor())
|
||||
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
|
||||
if (!S.getLangOptions().CPlusPlus0x) {
|
||||
if (ClassDecl->hasUserDeclaredConstructor())
|
||||
// FIXME: we really want to refer to a single subobject of the array,
|
||||
// but Entity doesn't have a way to capture that (yet).
|
||||
return TryConstructorInitialization(S, Entity, Kind, 0, 0,
|
||||
T, Sequence);
|
||||
} 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())
|
||||
return TryConstructorInitialization(S, Entity, Kind, 0, 0,
|
||||
T, Sequence);
|
||||
}
|
||||
|
||||
// -- if T is a (possibly cv-qualified) non-union class type
|
||||
// without a user-provided constructor, then the object is
|
||||
// zero-initialized and, if T's implicitly-declared default
|
||||
// constructor is non-trivial, that constructor is called.
|
||||
// -- if T is a (possibly cv-qualified) non-union class type without a
|
||||
// user-provided or deleted default constructor, then the object is
|
||||
// zero-initialized and, if T has a non-trivial default constructor,
|
||||
// default-initialized;
|
||||
if ((ClassDecl->getTagKind() == TTK_Class ||
|
||||
ClassDecl->getTagKind() == TTK_Struct)) {
|
||||
Sequence.AddZeroInitializationStep(Entity.getType());
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm-only
|
||||
// CHECK that we don't crash.
|
||||
|
||||
// PR11676's example is ill-formed:
|
||||
/*
|
||||
union _XEvent {
|
||||
};
|
||||
void ProcessEvent() {
|
||||
_XEvent pluginEvent = _XEvent();
|
||||
}
|
||||
*/
|
||||
|
||||
// Example from PR11665:
|
||||
void f() {
|
||||
union U { int field; } u = U();
|
||||
(void)U().field;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -verify %s
|
||||
struct A { // expected-note 2{{candidate}}
|
||||
A(int); // expected-note {{candidate}}
|
||||
int n;
|
||||
};
|
||||
int a = A().n; // expected-error {{no matching constructor}}
|
||||
|
||||
struct B {
|
||||
B() = delete; // expected-note {{here}}
|
||||
int n;
|
||||
};
|
||||
int b = B().n; // expected-error {{call to deleted}}
|
||||
|
||||
struct C { // expected-note {{here}}
|
||||
B b;
|
||||
};
|
||||
int c = C().b.n; // expected-error {{call to deleted}}
|
||||
|
||||
struct D {
|
||||
D() = default; // expected-note {{here}}
|
||||
B b;
|
||||
};
|
||||
int d = D().b.n; // expected-error {{call to deleted}}
|
||||
|
||||
struct E {
|
||||
E() = default;
|
||||
int n;
|
||||
};
|
||||
int e = E().n; // ok
|
||||
|
||||
struct F {
|
||||
F();
|
||||
int n;
|
||||
};
|
||||
int f = F().n; // ok
|
||||
|
||||
union G { // expected-note {{here}}
|
||||
F f;
|
||||
};
|
||||
int g = G().f.n; // expected-error {{call to deleted}}
|
||||
|
||||
struct H {
|
||||
int n;
|
||||
private:
|
||||
H(); // expected-note {{here}}
|
||||
};
|
||||
int h = H().n; // expected-error {{private constructor}}
|
||||
|
||||
struct I { // expected-note {{here}}
|
||||
H h;
|
||||
};
|
||||
int i = I().h.n; // expected-error {{call to deleted}}
|
||||
|
||||
struct J {
|
||||
J();
|
||||
virtual int f();
|
||||
int n;
|
||||
};
|
||||
int j1 = J().n; // ok
|
||||
int j2 = J().f(); // ok
|
||||
|
||||
union K { // expected-note 2{{here}}
|
||||
J j;
|
||||
int m;
|
||||
};
|
||||
int k1 = K().j.n; // expected-error {{call to deleted}}
|
||||
int k2 = K().j.f(); // expected-error {{call to deleted}}
|
Loading…
Reference in New Issue