diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f948a6e32f6..172d121681b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2009-03-17 Paolo Carlini + + PR c++/39475 + * semantics.c (check_trait_type): New. + (finish_trait_expr): Use it. + 2009-03-17 Jakub Jelinek * name-lookup.c (cp_emit_debug_info_for_using): Emit USING_STMTs diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index eb5d25ae80a..82a67971047 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4902,6 +4902,24 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) } } +/* 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 @@ -4950,14 +4968,45 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) 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)) + switch (kind) { - error ("incomplete type %qT not allowed", type2); - return error_mark_node; + 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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 51bd91512ab..235259478cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-03-17 Paolo Carlini + + PR c++/39475 + * g++.dg/ext/unary_trait_incomplete.C: New. + 2009-03-17 Jing Yu PR middle-end/39378 diff --git a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C new file mode 100644 index 00000000000..d5148bebbc6 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C @@ -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);