[cfe-commits] r150502 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/CodeGenCXX/pr11676.cpp test/SemaCXX/dr1301.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Tue Feb 14 13:14:13 PST 2012
Author: rsmith
Date: Tue Feb 14 15:14:13 2012
New Revision: 150502
URL: http://llvm.org/viewvc/llvm-project?rev=150502&view=rev
Log:
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).
Added:
cfe/trunk/test/SemaCXX/dr1301.cpp
Modified:
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/CodeGenCXX/pr11676.cpp
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=150502&r1=150501&r2=150502&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Feb 14 15:14:13 2012
@@ -2699,9 +2699,14 @@
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 @@
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());
Modified: cfe/trunk/test/CodeGenCXX/pr11676.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pr11676.cpp?rev=150502&r1=150501&r2=150502&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pr11676.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pr11676.cpp Tue Feb 14 15:14:13 2012
@@ -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;
+}
Added: cfe/trunk/test/SemaCXX/dr1301.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dr1301.cpp?rev=150502&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/dr1301.cpp (added)
+++ cfe/trunk/test/SemaCXX/dr1301.cpp Tue Feb 14 15:14:13 2012
@@ -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}}
More information about the cfe-commits
mailing list