From patchwork Tue Jun 22 04:32:01 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++0x PATCH to trait handling of array of incomplete type X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 56398 Message-Id: <4C203CC1.7000807@redhat.com> To: gcc-patches List , Paolo Carlini Date: Tue, 22 Jun 2010 00:32:01 -0400 From: Jason Merrill List-Id: I've been reworking how we find constructors and such for determining the exception specification of a synthesized method (basically, by using the overload machinery rather than a custom search). This turned up a problem with our handling of __has_noexcept_ctor; it was previously perfectly content to return false for an array of unknown bound of incomplete type, which seems wrong; if it's invalid to use that predicate on the incomplete type itself, simply wrapping it in an array of unknown bound shouldn't make it well-formed. The standard ought to be clarified as well, but I think this is sufficiently common-sense that a fix there isn't absolutely necessary. Tested x86_64-pc-linux-gnu, applied to trunk. commit 0902252ad2c7ab356b0d084713a7706a09307f00 Author: Jason Merrill Date: Mon Jun 21 22:31:10 2010 -0400 * semantics.c (check_trait_type): Check COMPLETE_TYPE_P for array element type. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8eb5336..4869cfc 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5152,7 +5152,8 @@ check_trait_type (tree type) if (COMPLETE_TYPE_P (type)) return true; - if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)) + if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) + && COMPLETE_TYPE_P (TREE_TYPE (type))) return true; if (VOID_TYPE_P (type)) diff --git a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C index d5148be..51cc80c 100644 --- a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C +++ b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C @@ -5,72 +5,72 @@ struct C { }; bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" } bool nas2 = __has_nothrow_assign(C[]); -bool nas3 = __has_nothrow_assign(I[]); +bool nas3 = __has_nothrow_assign(I[]); // { dg-error "incomplete type" } bool nas4 = __has_nothrow_assign(void); bool nas5 = __has_nothrow_assign(const void); bool tas1 = __has_trivial_assign(I); // { dg-error "incomplete type" } bool tas2 = __has_trivial_assign(C[]); -bool tas3 = __has_trivial_assign(I[]); +bool tas3 = __has_trivial_assign(I[]); // { dg-error "incomplete type" } bool tas4 = __has_trivial_assign(void); bool tas5 = __has_trivial_assign(const void); bool nco1 = __has_nothrow_constructor(I); // { dg-error "incomplete type" } bool nco2 = __has_nothrow_constructor(C[]); -bool nco3 = __has_nothrow_constructor(I[]); +bool nco3 = __has_nothrow_constructor(I[]); // { dg-error "incomplete type" } bool nco4 = __has_nothrow_constructor(void); bool nco5 = __has_nothrow_constructor(const void); bool tco1 = __has_trivial_constructor(I); // { dg-error "incomplete type" } bool tco2 = __has_trivial_constructor(C[]); -bool tco3 = __has_trivial_constructor(I[]); +bool tco3 = __has_trivial_constructor(I[]); // { dg-error "incomplete type" } bool tco4 = __has_trivial_constructor(void); bool tco5 = __has_trivial_constructor(const void); bool ncp1 = __has_nothrow_copy(I); // { dg-error "incomplete type" } bool ncp2 = __has_nothrow_copy(C[]); -bool ncp3 = __has_nothrow_copy(I[]); +bool ncp3 = __has_nothrow_copy(I[]); // { dg-error "incomplete type" } bool ncp4 = __has_nothrow_copy(void); bool ncp5 = __has_nothrow_copy(const void); bool tcp1 = __has_trivial_copy(I); // { dg-error "incomplete type" } bool tcp2 = __has_trivial_copy(C[]); -bool tcp3 = __has_trivial_copy(I[]); +bool tcp3 = __has_trivial_copy(I[]); // { dg-error "incomplete type" } bool tcp4 = __has_trivial_copy(void); bool tcp5 = __has_trivial_copy(const void); bool vde1 = __has_virtual_destructor(I); // { dg-error "incomplete type" } bool vde2 = __has_virtual_destructor(C[]); -bool vde3 = __has_virtual_destructor(I[]); +bool vde3 = __has_virtual_destructor(I[]); // { dg-error "incomplete type" } bool vde4 = __has_virtual_destructor(void); bool vde5 = __has_virtual_destructor(const void); bool tde1 = __has_trivial_destructor(I); // { dg-error "incomplete type" } bool tde2 = __has_trivial_destructor(C[]); -bool tde3 = __has_trivial_destructor(I[]); +bool tde3 = __has_trivial_destructor(I[]); // { dg-error "incomplete type" } bool tde4 = __has_trivial_destructor(void); bool tde5 = __has_trivial_destructor(const void); bool abs1 = __is_abstract(I); // { dg-error "incomplete type" } bool abs2 = __is_abstract(C[]); -bool abs3 = __is_abstract(I[]); +bool abs3 = __is_abstract(I[]); // { dg-error "incomplete type" } bool abs4 = __is_abstract(void); bool abs5 = __is_abstract(const void); bool pod1 = __is_pod(I); // { dg-error "incomplete type" } bool pod2 = __is_pod(C[]); -bool pod3 = __is_pod(I[]); +bool pod3 = __is_pod(I[]); // { dg-error "incomplete type" } bool pod4 = __is_pod(void); bool pod5 = __is_pod(const void); bool emp1 = __is_empty(I); // { dg-error "incomplete type" } bool emp2 = __is_empty(C[]); -bool emp3 = __is_empty(I[]); +bool emp3 = __is_empty(I[]); // { dg-error "incomplete type" } bool emp4 = __is_empty(void); bool emp5 = __is_empty(const void); bool pol1 = __is_polymorphic(I); // { dg-error "incomplete type" } bool pol2 = __is_polymorphic(C[]); -bool pol3 = __is_polymorphic(I[]); +bool pol3 = __is_polymorphic(I[]); // { dg-error "incomplete type" } bool pol4 = __is_polymorphic(void); bool pol5 = __is_polymorphic(const void);