This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ Patch] Fix PR 39475
- From: Paolo Carlini <paolo dot carlini at oracle dot com>
- To: Mark Mitchell <mark at codesourcery dot com>
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 17 Mar 2009 21:19:21 +0100
- Subject: Re: [C++ Patch] Fix PR 39475
- References: <49C00226.5050806@oracle.com> <49C003BC.4000106@codesourcery.com>
Hi,
> This is OK in principle, but this comment:
>
> + /* Checks that a type fulfills the preconditions in Table 33. */
>
> This should explicitly reference TYPE and should quote the appropriate
> bits of the standard -- or paraphrase them -- rather than referring to
> Table 33.
>
Agreed. The below is what I'm going to commit.
Thanks,
Paolo.
////////////
Index: testsuite/g++.dg/ext/unary_trait_incomplete.C
===================================================================
*** testsuite/g++.dg/ext/unary_trait_incomplete.C (revision 0)
--- testsuite/g++.dg/ext/unary_trait_incomplete.C (revision 0)
***************
*** 0 ****
--- 1,76 ----
+ // PR c++/39475
+
+ struct I;
+ 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 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 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 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 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 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 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 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 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 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 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 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 pol4 = __is_polymorphic(void);
+ bool pol5 = __is_polymorphic(const void);
Index: cp/semantics.c
===================================================================
*** cp/semantics.c (revision 144907)
--- cp/semantics.c (working copy)
*************** trait_expr_value (cp_trait_kind kind, tr
*** 4902,4907 ****
--- 4902,4925 ----
}
}
+ /* Returns true if TYPE is a complete type, an array of unknown bound,
+ or (possibly cv-qualified) void, returns false otherwise. */
+
+ static bool
+ check_trait_type (tree type)
+ {
+ if (COMPLETE_TYPE_P (type))
+ return true;
+
+ if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+ return true;
+
+ if (VOID_TYPE_P (type))
+ return true;
+
+ return false;
+ }
+
/* Process a trait expression. */
tree
*************** finish_trait_expr (cp_trait_kind kind, t
*** 4950,4963 ****
if (type2)
complete_type (type2);
! /* The only required diagnostic. */
! if (kind == CPTK_IS_BASE_OF
! && NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
! && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
! && !COMPLETE_TYPE_P (type2))
{
! error ("incomplete type %qT not allowed", type2);
! return error_mark_node;
}
return (trait_expr_value (kind, type1, type2)
--- 4968,5012 ----
if (type2)
complete_type (type2);
! switch (kind)
{
! case CPTK_HAS_NOTHROW_ASSIGN:
! case CPTK_HAS_TRIVIAL_ASSIGN:
! case CPTK_HAS_NOTHROW_CONSTRUCTOR:
! case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
! case CPTK_HAS_NOTHROW_COPY:
! case CPTK_HAS_TRIVIAL_COPY:
! case CPTK_HAS_TRIVIAL_DESTRUCTOR:
! case CPTK_HAS_VIRTUAL_DESTRUCTOR:
! case CPTK_IS_ABSTRACT:
! case CPTK_IS_EMPTY:
! case CPTK_IS_POD:
! case CPTK_IS_POLYMORPHIC:
! if (!check_trait_type (type1))
! {
! error ("incomplete type %qT not allowed", type1);
! return error_mark_node;
! }
! break;
!
! case CPTK_IS_BASE_OF:
! if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
! && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
! && !COMPLETE_TYPE_P (type2))
! {
! error ("incomplete type %qT not allowed", type2);
! return error_mark_node;
! }
! break;
!
! case CPTK_IS_CLASS:
! case CPTK_IS_ENUM:
! case CPTK_IS_UNION:
! break;
!
! case CPTK_IS_CONVERTIBLE_TO:
! default:
! gcc_unreachable ();
}
return (trait_expr_value (kind, type1, type2)