* [C++ Patch] PR 50732 @ 2011-10-14 18:48 Paolo Carlini 2011-10-14 18:56 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2011-10-14 18:48 UTC (permalink / raw) To: gcc-patches; +Cc: Jason Merrill [-- Attachment #1: Type: text/plain, Size: 316 bytes --] Hi, submitter complains that, at variance with C++11, __is_base_of doesn't handle an incomplete base type (the first parameter). The reason seems simple: in finish_trait_expr we try to complete *both* types instead of doing it where/when necessary. Tested x86_64-linux. Ok? Thanks, Paolo. /////////////////// [-- Attachment #2: CL_50732 --] [-- Type: text/plain, Size: 305 bytes --] /cp 2011-10-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/50732 * semantics.c (finish_trait_expr): Do not try to instantiate the the base type of an __is_base_of trait. /testsuite 2011-10-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/50732 * g++.dg/ext/is_base_of_incomplete.C: New. [-- Attachment #3: patch_50732 --] [-- Type: text/plain, Size: 1449 bytes --] Index: testsuite/g++.dg/ext/is_base_of_incomplete.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) +++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) @@ -0,0 +1,7 @@ +template <typename T> +struct non_instantiable +{ + typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type; +}; + +int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1]; Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 179997) +++ cp/semantics.c (working copy) @@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, return trait_expr; } - complete_type (type1); - if (type2) - complete_type (type2); - switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: @@ -5297,6 +5293,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, case CPTK_IS_POLYMORPHIC: case CPTK_IS_STD_LAYOUT: case CPTK_IS_TRIVIAL: + complete_type (type1); if (!check_trait_type (type1)) { error ("incomplete type %qT not allowed", type1); @@ -5305,6 +5302,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, break; case CPTK_IS_BASE_OF: + complete_type (type2); 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)) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-14 18:48 [C++ Patch] PR 50732 Paolo Carlini @ 2011-10-14 18:56 ` Paolo Carlini 2011-10-14 19:12 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2011-10-14 18:56 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches, Jason Merrill On 10/14/2011 08:23 PM, Paolo Carlini wrote: > Hi, > > submitter complains that, at variance with C++11, __is_base_of doesn't > handle an incomplete base type (the first parameter). The reason seems > simple: in finish_trait_expr we try to complete *both* types instead > of doing it where/when necessary. Hmm, maybe we should be even more careful and call complete (type2) only when NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) && !same_type_ignoring_top_level_qualifiers_p (type1, type2) is true? Paolo. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-14 18:56 ` Paolo Carlini @ 2011-10-14 19:12 ` Paolo Carlini 2011-10-14 19:41 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2011-10-14 19:12 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches, Jason Merrill [-- Attachment #1: Type: text/plain, Size: 632 bytes --] On 10/14/2011 08:30 PM, Paolo Carlini wrote: > On 10/14/2011 08:23 PM, Paolo Carlini wrote: >> Hi, >> >> submitter complains that, at variance with C++11, __is_base_of >> doesn't handle an incomplete base type (the first parameter). The >> reason seems simple: in finish_trait_expr we try to complete *both* >> types instead of doing it where/when necessary. > Hmm, maybe we should be even more careful and call complete (type2) > only when > > NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) && > !same_type_ignoring_top_level_qualifiers_p (type1, type2) > > is true? Like this? Paolo. /////////////////// [-- Attachment #2: patch_50732_alt --] [-- Type: text/plain, Size: 1746 bytes --] Index: testsuite/g++.dg/ext/is_base_of_incomplete.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) +++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) @@ -0,0 +1,7 @@ +template <typename T> +struct non_instantiable +{ + typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type; +}; + +int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1]; Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 179997) +++ cp/semantics.c (working copy) @@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, return trait_expr; } - complete_type (type1); - if (type2) - complete_type (type2); - switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: @@ -5297,6 +5293,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, case CPTK_IS_POLYMORPHIC: case CPTK_IS_STD_LAYOUT: case CPTK_IS_TRIVIAL: + complete_type (type1); if (!check_trait_type (type1)) { error ("incomplete type %qT not allowed", type1); @@ -5306,11 +5303,14 @@ finish_trait_expr (cp_trait_kind kind, tree type1, 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)) + && !same_type_ignoring_top_level_qualifiers_p (type1, type2)) { - error ("incomplete type %qT not allowed", type2); - return error_mark_node; + complete_type (type2); + if (!COMPLETE_TYPE_P (type2)) + { + error ("incomplete type %qT not allowed", type2); + return error_mark_node; + } } break; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-14 19:12 ` Paolo Carlini @ 2011-10-14 19:41 ` Jason Merrill 2011-10-14 23:03 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Jason Merrill @ 2011-10-14 19:41 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches How about using complete_type_or_else? Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-14 19:41 ` Jason Merrill @ 2011-10-14 23:03 ` Paolo Carlini 2011-10-14 23:26 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2011-10-14 23:03 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 659 bytes --] On 10/14/2011 09:08 PM, Jason Merrill wrote: > How about using complete_type_or_else? The CPTK_IS_BASE_OF case becomes much simpler indeed, thanks. For the unary traits, though, I don't see an advantage in using it, because in some cases in check_trait_type we don't want to error out even when complete_type_or_else would. Unless we can check whether we are dealing with an array of unknown bound *before* completing the type? That is: if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) && COMPLETE_TYPE_P (TREE_TYPE (type))) is the outcome always the same before and after trying to complete (type)? Thanks, Paolo. ////////////////////// [-- Attachment #2: patch_50732_2 --] [-- Type: text/plain, Size: 2111 bytes --] Index: testsuite/g++.dg/ext/is_base_of_diagnostic.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_diagnostic.C (revision 180007) +++ testsuite/g++.dg/ext/is_base_of_diagnostic.C (working copy) @@ -1,7 +1,7 @@ class A { }; -class B; +class B; // { dg-error "forward declaration" } union C { }; Index: testsuite/g++.dg/ext/is_base_of_incomplete.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) +++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) @@ -0,0 +1,7 @@ +template <typename T> +struct non_instantiable +{ + typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type; +}; + +int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1]; Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 180007) +++ cp/semantics.c (working copy) @@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, return trait_expr; } - complete_type (type1); - if (type2) - complete_type (type2); - switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: @@ -5297,9 +5293,10 @@ finish_trait_expr (cp_trait_kind kind, tree type1, case CPTK_IS_POLYMORPHIC: case CPTK_IS_STD_LAYOUT: case CPTK_IS_TRIVIAL: + complete_type (type1); if (!check_trait_type (type1)) { - error ("incomplete type %qT not allowed", type1); + error ("invalid use of incomplete type %qT", type1); return error_mark_node; } break; @@ -5307,11 +5304,9 @@ finish_trait_expr (cp_trait_kind kind, tree type1, 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; - } + && !complete_type_or_else (type2, NULL_TREE)) + /* We already issued an error. */ + return error_mark_node; break; case CPTK_IS_CLASS: ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-14 23:03 ` Paolo Carlini @ 2011-10-14 23:26 ` Jason Merrill 2011-10-15 1:17 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Jason Merrill @ 2011-10-14 23:26 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 10/14/2011 05:58 PM, Paolo Carlini wrote: > On 10/14/2011 09:08 PM, Jason Merrill wrote: >> How about using complete_type_or_else? > The CPTK_IS_BASE_OF case becomes much simpler indeed, thanks. For the > unary traits, though, I don't see an advantage in using it, because in > some cases in check_trait_type we don't want to error out even when > complete_type_or_else would. Unless we can check whether we are dealing > with an array of unknown bound *before* completing the type? That is: > > if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) > && COMPLETE_TYPE_P (TREE_TYPE (type))) > > is the outcome always the same before and after trying to complete (type)? That should work. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-14 23:26 ` Jason Merrill @ 2011-10-15 1:17 ` Paolo Carlini 2011-10-15 20:42 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2011-10-15 1:17 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 245 bytes --] On 10/15/2011 12:20 AM, Jason Merrill wrote: > That should work. Excellent. Then we can do something like the below, a great improvement. I'm finishing testing it (already past g++.dg), Ok if it passes? Thanks, Paolo. /////////////////////// [-- Attachment #2: CL_50732_3 --] [-- Type: text/plain, Size: 475 bytes --] /cp 2011-10-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/50732 * semantics.c (finish_trait_expr): Do not try to instantiate the the base type of an __is_base_of trait. (check_trait_type): Return a tree; use complete_type_or_else. /testsuite 2011-10-14 Paolo Carlini <paolo.carlini@oracle.com> PR c++/50732 * g++.dg/ext/is_base_of_incomplete.C: New. * g++.dg/ext/is_base_of_diagnostic.C: Adjust dg-errors. * g++.dg/ext/unary_trait_incomplete.C: Likewise. [-- Attachment #3: patch_50732_3 --] [-- Type: text/plain, Size: 7227 bytes --] Index: testsuite/g++.dg/ext/unary_trait_incomplete.C =================================================================== --- testsuite/g++.dg/ext/unary_trait_incomplete.C (revision 180007) +++ testsuite/g++.dg/ext/unary_trait_incomplete.C (working copy) @@ -1,76 +1,76 @@ // PR c++/39475 -struct I; +struct I; // { dg-error "forward declaration" } struct C { }; bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" } bool nas2 = __has_nothrow_assign(C[]); -bool nas3 = __has_nothrow_assign(I[]); // { dg-error "incomplete type" } +bool nas3 = __has_nothrow_assign(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool tas3 = __has_trivial_assign(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool nco3 = __has_nothrow_constructor(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool tco3 = __has_trivial_constructor(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool ncp3 = __has_nothrow_copy(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool tcp3 = __has_trivial_copy(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool vde3 = __has_virtual_destructor(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool tde3 = __has_trivial_destructor(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool abs3 = __is_abstract(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool pod3 = __is_pod(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool emp3 = __is_empty(I[]); // { dg-error "unspecified bounds" } 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[]); // { dg-error "incomplete type" } +bool pol3 = __is_polymorphic(I[]); // { dg-error "unspecified bounds" } bool pol4 = __is_polymorphic(void); bool pol5 = __is_polymorphic(const void); Index: testsuite/g++.dg/ext/is_base_of_diagnostic.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_diagnostic.C (revision 180007) +++ testsuite/g++.dg/ext/is_base_of_diagnostic.C (working copy) @@ -1,7 +1,7 @@ class A { }; -class B; +class B; // { dg-error "forward declaration" } union C { }; Index: testsuite/g++.dg/ext/is_base_of_incomplete.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) +++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) @@ -0,0 +1,7 @@ +template <typename T> +struct non_instantiable +{ + typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type; +}; + +int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1]; Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 180007) +++ cp/semantics.c (working copy) @@ -5210,23 +5210,20 @@ trait_expr_value (cp_trait_kind kind, tree type1, } } -/* Returns true if TYPE is a complete type, an array of unknown bound, - or (possibly cv-qualified) void, returns false otherwise. */ +/* If TYPE is an array of unknown bound, or (possibly cv-qualified) + void, or a complete type, returns it, otherwise NULL_TREE. */ -static bool +static tree check_trait_type (tree type) { - if (COMPLETE_TYPE_P (type)) - return true; - if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) && COMPLETE_TYPE_P (TREE_TYPE (type))) - return true; + return type; if (VOID_TYPE_P (type)) - return true; + return type; - return false; + return complete_type_or_else (type, NULL_TREE); } /* Process a trait expression. */ @@ -5276,10 +5273,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, return trait_expr; } - complete_type (type1); - if (type2) - complete_type (type2); - switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: @@ -5298,20 +5291,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1, case CPTK_IS_STD_LAYOUT: case CPTK_IS_TRIVIAL: if (!check_trait_type (type1)) - { - error ("incomplete type %qT not allowed", type1); - return error_mark_node; - } + 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; - } + && !complete_type_or_else (type2, NULL_TREE)) + /* We already issued an error. */ + return error_mark_node; break; case CPTK_IS_CLASS: ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-15 1:17 ` Paolo Carlini @ 2011-10-15 20:42 ` Jason Merrill 2011-10-15 21:21 ` Paolo Carlini 0 siblings, 1 reply; 10+ messages in thread From: Jason Merrill @ 2011-10-15 20:42 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 10/14/2011 06:57 PM, Paolo Carlini wrote: > - return false; > + return complete_type_or_else (type, NULL_TREE); I think I'd do complete_type_or_else (strip_array_types (type), NULL_TREE) so that the error doesn't complain about unspecified bounds, which would be misleading. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-15 20:42 ` Jason Merrill @ 2011-10-15 21:21 ` Paolo Carlini 2011-10-15 21:27 ` Jason Merrill 0 siblings, 1 reply; 10+ messages in thread From: Paolo Carlini @ 2011-10-15 21:21 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 485 bytes --] On 10/15/2011 08:33 PM, Jason Merrill wrote: > On 10/14/2011 06:57 PM, Paolo Carlini wrote: >> - return false; >> + return complete_type_or_else (type, NULL_TREE); > > I think I'd do > > complete_type_or_else (strip_array_types (type), NULL_TREE) > > so that the error doesn't complain about unspecified bounds, which > would be misleading. Good point, thanks. Thus, what about the below? Again, testing already past g++.dg/dg.exp. Thanks again, Paolo. /////////////////////// [-- Attachment #2: patch_50732_4 --] [-- Type: text/plain, Size: 3216 bytes --] Index: testsuite/g++.dg/ext/unary_trait_incomplete.C =================================================================== --- testsuite/g++.dg/ext/unary_trait_incomplete.C (revision 180046) +++ testsuite/g++.dg/ext/unary_trait_incomplete.C (working copy) @@ -1,6 +1,6 @@ // PR c++/39475 -struct I; +struct I; // { dg-error "forward declaration" } struct C { }; bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" } Index: testsuite/g++.dg/ext/is_base_of_diagnostic.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_diagnostic.C (revision 180046) +++ testsuite/g++.dg/ext/is_base_of_diagnostic.C (working copy) @@ -1,7 +1,7 @@ class A { }; -class B; +class B; // { dg-error "forward declaration" } union C { }; Index: testsuite/g++.dg/ext/is_base_of_incomplete.C =================================================================== --- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) +++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0) @@ -0,0 +1,9 @@ +// PR c++/50732 + +template <typename T> +struct non_instantiable +{ + typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type; +}; + +int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1]; Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 180007) +++ cp/semantics.c (working copy) @@ -5210,23 +5210,20 @@ trait_expr_value (cp_trait_kind kind, tree type1, } } -/* Returns true if TYPE is a complete type, an array of unknown bound, - or (possibly cv-qualified) void, returns false otherwise. */ +/* If TYPE is an array of unknown bound, or (possibly cv-qualified) + void, or a complete type, returns it, otherwise NULL_TREE. */ -static bool +static tree check_trait_type (tree type) { - if (COMPLETE_TYPE_P (type)) - return true; - if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) && COMPLETE_TYPE_P (TREE_TYPE (type))) - return true; + return type; if (VOID_TYPE_P (type)) - return true; + return type; - return false; + return complete_type_or_else (strip_array_types (type), NULL_TREE); } /* Process a trait expression. */ @@ -5276,10 +5273,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, return trait_expr; } - complete_type (type1); - if (type2) - complete_type (type2); - switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: @@ -5298,20 +5291,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1, case CPTK_IS_STD_LAYOUT: case CPTK_IS_TRIVIAL: if (!check_trait_type (type1)) - { - error ("incomplete type %qT not allowed", type1); - return error_mark_node; - } + 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; - } + && !complete_type_or_else (type2, NULL_TREE)) + /* We already issued an error. */ + return error_mark_node; break; case CPTK_IS_CLASS: ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ Patch] PR 50732 2011-10-15 21:21 ` Paolo Carlini @ 2011-10-15 21:27 ` Jason Merrill 0 siblings, 0 replies; 10+ messages in thread From: Jason Merrill @ 2011-10-15 21:27 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches OK. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-10-15 19:00 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-10-14 18:48 [C++ Patch] PR 50732 Paolo Carlini 2011-10-14 18:56 ` Paolo Carlini 2011-10-14 19:12 ` Paolo Carlini 2011-10-14 19:41 ` Jason Merrill 2011-10-14 23:03 ` Paolo Carlini 2011-10-14 23:26 ` Jason Merrill 2011-10-15 1:17 ` Paolo Carlini 2011-10-15 20:42 ` Jason Merrill 2011-10-15 21:21 ` Paolo Carlini 2011-10-15 21:27 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).