From: Richard Smith Date: Mon, 5 Sep 2011 02:13:09 +0000 (+0000) Subject: Implement the suggested resolution of WG21 N3307 issue 19: When determining whether... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=017ab77655b262311a3550342ca19b85380f8f20;p=clang Implement the suggested resolution of WG21 N3307 issue 19: When determining whether a class is an aggregate in C++0x, treat all functions which are neither deleted nor defaulted as user-provided, not just special member functions. The wording of the standard only defines the term "user-provided" for special member functions, but the intent seems to be that any function can be user-provided. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139111 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index be529f85a6..1821ba8a6a 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -503,18 +503,18 @@ NotASpecialMember:; // Note that we have a user-declared constructor. data().UserDeclaredConstructor = true; - // FIXME: Under C++0x, /only/ special member functions may be user-provided. - // This is probably a defect. - bool UserProvided = false; + // Technically, "user-provided" is only defined for special member + // functions, but the intent of the standard is clearly that it should apply + // to all functions. + bool UserProvided = Constructor->isUserProvided(); // C++0x [class.ctor]p5: // A default constructor is trivial if it is not user-provided [...] if (Constructor->isDefaultConstructor()) { data().DeclaredDefaultConstructor = true; - if (Constructor->isUserProvided()) { + if (UserProvided) { data().HasTrivialDefaultConstructor = false; data().UserProvidedDefaultConstructor = true; - UserProvided = true; } } @@ -528,10 +528,8 @@ NotASpecialMember:; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if it is not // user-provided [...] - if (Constructor->isUserProvided()) { + if (UserProvided) data().HasTrivialCopyConstructor = false; - UserProvided = true; - } } else if (Constructor->isMoveConstructor()) { data().UserDeclaredMoveConstructor = true; data().DeclaredMoveConstructor = true; @@ -539,10 +537,8 @@ NotASpecialMember:; // C++0x [class.copy]p13: // A copy/move constructor for class X is trivial if it is not // user-provided [...] - if (Constructor->isUserProvided()) { + if (UserProvided) data().HasTrivialMoveConstructor = false; - UserProvided = true; - } } } if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) { diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp index 9b92340fa4..146313392a 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp @@ -18,11 +18,10 @@ struct NonAggr1a { NonAggr1a(int, int); int k; }; -// In C++03, this is {{non-aggregate type 'NonAggr1a'}}. // In C++0x, 'user-provided' is only defined for special member functions, so -// this type is considered to be an aggregate. This is probably a langauge -// defect. -NonAggr1a na1a = { 42 }; +// this type is considered to be an aggregate. This is considered to be +// a language defect. +NonAggr1a na1a = { 42 }; // expected-error {{non-aggregate type 'NonAggr1a'}} struct NonAggr1b { NonAggr1b(const NonAggr1b &); diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index b9e69b00b7..90d0ead920 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -2,8 +2,8 @@ // Verify that we can't initialize non-aggregates with an initializer // list. -// FIXME: Note that due to a (likely) standard bug, this is technically an -// aggregate. +// Note that due to a (likely) standard bug, this is technically an aggregate, +// but we do not treat it as one. struct NonAggr1 { NonAggr1(int) { } @@ -24,7 +24,7 @@ struct NonAggr4 { virtual void f(); }; -NonAggr1 na1 = { 17 }; +NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}} NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}} NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}} NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}}