Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On 3/1/21 7:59 PM, Marek Polacek wrote: On Mon, Mar 01, 2021 at 03:08:58PM -0500, Jason Merrill wrote: On 3/1/21 2:54 PM, Marek Polacek wrote: On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches wrote: On 2/25/21 5:41 PM, Marek Polacek wrote: On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote: On 2/12/21 6:12 PM, Marek Polacek wrote: We represent deduction guides with FUNCTION_DECLs, but they are built without DECL_CONTEXT Hmm, that seems wrong: "A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access." But it probably isn't necessary to change this: leading to an ICE in type_dependent_expression_p on the assert that the type of a function template with no dependent (innermost!) template arguments must be non-dependent. Consider the attached class-deduction79.C: we create a deduction guide: template G(T)-> E::G we deduce T and create a partial instantiation: G(T) -> E::G [with T = int] And then do_class_deduction wants to create a CALL_EXPR from the above using build_new_function_call -> build_over_call which calls mark_used -> maybe_instantiate_noexcept -> type_dependent_expression_p. There, the innermost template arguments are non-dependent (), but the fntype is dependent -- the return type is a TYPENAME_TYPE, and since we have no DECL_CONTEXT, this check holds: /* Otherwise, if the function decl isn't from a dependent scope, it can't be type-dependent. Checking this is important for functions with auto return type, which looks like a dependent type. */ if (TREE_CODE (expression) == FUNCTION_DECL && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) whereupon we ICE. Experiments with setting DECL_CONTEXT didn't pan out. In c8 of the PR it looks like you were using the class itself as DECL_CONTEXT; the quote above says that the right context is the enclosing scope of the class. Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in retrieve_specialization: /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == (TREE_CODE (tmpl) == TEMPLATE_DECL ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) : template_class_depth (DECL_CONTEXT (tmpl; Yeah, probably simpler not to bother. So perhaps we just want to skip the assert for deduction guides, because they are a little special. Better ideas solicited. In c3 you mention that one of the variants broke with r269093; this is because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the template pattern itself (E). And the original test started with my r11-1713 because using TREE_TYPE directly instead of decltype (which is a non-deduced context) means we can deduced from the argument. But I think probably the right answer is to defer this deduction until the enclosing scope is non-dependent, i.e. (untested) Thanks. That mostly works, except the new class-deduction-aggr[89].C tests. Consider 8: namespace N { template struct S { template S(T, U); }; } // namespace N template struct E { template struct G { T t; }; void fn() { G{N::S{'a', 1}}; } }; void g () { E<1> e; e.fn (); } With your patch, when in do_class_deduction when processing_template_decl, we just return. When we call do_class_deduction again when p_t_d is 0, maybe_aggr_guide returns early here: if (!CP_AGGREGATE_TYPE_P (type)) return NULL_TREE because G is not complete (and rightly so, we didn't instantiate it). So we aren't able to deduce the template parameters. I'm not sure if I should pursue this direction further. :( I think so; we just need to test CP_AGGREGATE_TYPE_P on the original template pattern instead of the instantiation E<1>::G. I'm sorry, I've got stuck again. Yes, using the original template pattern helps us get past the CP_AGGREGATE_TYPE_P check. However, using TREE_TYPE (DECL_TI_TEMPLATE (tmpl)) as the type of the deduction guide means the guide will be "template G(T)-> E< >::G" which results in class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename E< >::G >' which makes sense I guess: when we defer building up the guide until we've instantiated E<1>, finding the dependent type E<> is not expected. Yeah, I was only thinking to use the pattern for the aggregate check. Ack. Though I think I also have to use the pattern here: init = reshape_init (type, init, complain); otherwise reshape_init returns a TARGET_EXPR and we immediately crash in collect_ctor_idx_types because that only expects a CONSTRUCTOR. And what we need to get is the type T -- of the constructor's index. But creating the guide with "struct E<1>::G" as its type seems wrong; I'm not even sure if a
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On Mon, Mar 01, 2021 at 03:08:58PM -0500, Jason Merrill wrote: > On 3/1/21 2:54 PM, Marek Polacek wrote: > > On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches > > wrote: > > > On 2/25/21 5:41 PM, Marek Polacek wrote: > > > > On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote: > > > > > On 2/12/21 6:12 PM, Marek Polacek wrote: > > > > > > We represent deduction guides with FUNCTION_DECLs, but they are > > > > > > built > > > > > > without DECL_CONTEXT > > > > > > > > > > Hmm, that seems wrong: "A deduction-guide shall be declared in the > > > > > same scope as the corresponding class template and, for a member class > > > > > template, with the same access." But it probably isn't necessary to > > > > > change > > > > > this: > > > > > > > > > > > leading to an ICE in type_dependent_expression_p > > > > > > on the assert that the type of a function template with no dependent > > > > > > (innermost!) template arguments must be non-dependent. Consider the > > > > > > attached class-deduction79.C: we create a deduction guide: > > > > > > > > > > > > template G(T)-> E::G > > > > > > > > > > > > we deduce T and create a partial instantiation: > > > > > > > > > > > > G(T) -> E::G [with T = int] > > > > > > > > > > > > And then do_class_deduction wants to create a CALL_EXPR from the > > > > > > above > > > > > > using build_new_function_call -> build_over_call which calls > > > > > > mark_used > > > > > > -> maybe_instantiate_noexcept -> type_dependent_expression_p. > > > > > > > > > > > > There, the innermost template arguments are non-dependent (), > > > > > > but > > > > > > the fntype is dependent -- the return type is a TYPENAME_TYPE, and > > > > > > since we have no DECL_CONTEXT, this check holds: > > > > > > > > > > > > /* Otherwise, if the function decl isn't from a dependent > > > > > > scope, it can't be > > > > > > type-dependent. Checking this is important for functions > > > > > > with auto return > > > > > > type, which looks like a dependent type. */ > > > > > > if (TREE_CODE (expression) == FUNCTION_DECL > > > > > > && !(DECL_CLASS_SCOPE_P (expression) > > > > > > && dependent_type_p (DECL_CONTEXT (expression))) > > > > > > > > > > > > whereupon we ICE. > > > > > > > > > > > > Experiments with setting DECL_CONTEXT didn't pan out. > > > > > > > > > > In c8 of the PR it looks like you were using the class itself as > > > > > DECL_CONTEXT; the quote above says that the right context is the > > > > > enclosing > > > > > scope of the class. > > > > > > > > Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in > > > > retrieve_specialization: > > > > > > > > /* There should be as many levels of arguments as there are > > > >levels of parameters. */ > > > > gcc_assert (TMPL_ARGS_DEPTH (args) > > > > == (TREE_CODE (tmpl) == TEMPLATE_DECL > > > > ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > > > > : template_class_depth (DECL_CONTEXT (tmpl; > > > > > > Yeah, probably simpler not to bother. > > > > > > > > > So perhaps we > > > > > > just want to skip the assert for deduction guides, because they are > > > > > > a little special. Better ideas solicited. > > > > > > > > > > In c3 you mention that one of the variants broke with r269093; this is > > > > > because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false > > > > > for the > > > > > template pattern itself (E). > > > > > > > > And the original test started with my r11-1713 because using TREE_TYPE > > > > directly instead of decltype (which is a non-deduced context) means we > > > > can deduced from the argument. > > > > > But I think probably the right answer is to defer this deduction > > > > > until the > > > > > enclosing scope is non-dependent, i.e. (untested) > > > > > > > > Thanks. That mostly works, except the new class-deduction-aggr[89].C > > > > tests. Consider 8: > > > > > > > > namespace N { > > > > template struct S { > > > > template S(T, U); > > > > }; > > > > } // namespace N > > > > template struct E { > > > > template struct G { T t; }; > > > > void fn() { G{N::S{'a', 1}}; } > > > > }; > > > > > > > > void > > > > g () > > > > { > > > > E<1> e; > > > > e.fn (); > > > > } > > > > > > > > With your patch, when in do_class_deduction when > > > > processing_template_decl, > > > > we just return. When we call do_class_deduction again when p_t_d is 0, > > > > maybe_aggr_guide returns early here: > > > > > > > > if (!CP_AGGREGATE_TYPE_P (type)) > > > > return NULL_TREE > > > > > > > > because G is not complete (and rightly so, we didn't instantiate it). > > > > So > > > > we aren't able to deduce the template parameters. I'm not sure if I > > > > should > > > > pursue this direction further. :( > > > > > > I think so; we just need to test CP_AGGREGATE_TYPE_P on the
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On 3/1/21 2:54 PM, Marek Polacek wrote: On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches wrote: On 2/25/21 5:41 PM, Marek Polacek wrote: On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote: On 2/12/21 6:12 PM, Marek Polacek wrote: We represent deduction guides with FUNCTION_DECLs, but they are built without DECL_CONTEXT Hmm, that seems wrong: "A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access." But it probably isn't necessary to change this: leading to an ICE in type_dependent_expression_p on the assert that the type of a function template with no dependent (innermost!) template arguments must be non-dependent. Consider the attached class-deduction79.C: we create a deduction guide: template G(T)-> E::G we deduce T and create a partial instantiation: G(T) -> E::G [with T = int] And then do_class_deduction wants to create a CALL_EXPR from the above using build_new_function_call -> build_over_call which calls mark_used -> maybe_instantiate_noexcept -> type_dependent_expression_p. There, the innermost template arguments are non-dependent (), but the fntype is dependent -- the return type is a TYPENAME_TYPE, and since we have no DECL_CONTEXT, this check holds: /* Otherwise, if the function decl isn't from a dependent scope, it can't be type-dependent. Checking this is important for functions with auto return type, which looks like a dependent type. */ if (TREE_CODE (expression) == FUNCTION_DECL && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) whereupon we ICE. Experiments with setting DECL_CONTEXT didn't pan out. In c8 of the PR it looks like you were using the class itself as DECL_CONTEXT; the quote above says that the right context is the enclosing scope of the class. Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in retrieve_specialization: /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == (TREE_CODE (tmpl) == TEMPLATE_DECL ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) : template_class_depth (DECL_CONTEXT (tmpl; Yeah, probably simpler not to bother. So perhaps we just want to skip the assert for deduction guides, because they are a little special. Better ideas solicited. In c3 you mention that one of the variants broke with r269093; this is because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the template pattern itself (E). And the original test started with my r11-1713 because using TREE_TYPE directly instead of decltype (which is a non-deduced context) means we can deduced from the argument. But I think probably the right answer is to defer this deduction until the enclosing scope is non-dependent, i.e. (untested) Thanks. That mostly works, except the new class-deduction-aggr[89].C tests. Consider 8: namespace N { template struct S { template S(T, U); }; } // namespace N template struct E { template struct G { T t; }; void fn() { G{N::S{'a', 1}}; } }; void g () { E<1> e; e.fn (); } With your patch, when in do_class_deduction when processing_template_decl, we just return. When we call do_class_deduction again when p_t_d is 0, maybe_aggr_guide returns early here: if (!CP_AGGREGATE_TYPE_P (type)) return NULL_TREE because G is not complete (and rightly so, we didn't instantiate it). So we aren't able to deduce the template parameters. I'm not sure if I should pursue this direction further. :( I think so; we just need to test CP_AGGREGATE_TYPE_P on the original template pattern instead of the instantiation E<1>::G. I'm sorry, I've got stuck again. Yes, using the original template pattern helps us get past the CP_AGGREGATE_TYPE_P check. However, using TREE_TYPE (DECL_TI_TEMPLATE (tmpl)) as the type of the deduction guide means the guide will be "template G(T)-> E< >::G" which results in class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename E< >::G >' which makes sense I guess: when we defer building up the guide until we've instantiated E<1>, finding the dependent type E<> is not expected. Yeah, I was only thinking to use the pattern for the aggregate check. But creating the guide with "struct E<1>::G" as its type seems wrong; I'm not even sure if a guide like template G(T)-> E<1>::G makes sense. It looks fine to me. In any case the deduction fails (when we call build_new_function_call in do_class_deduction), because we've got a mismatch: the template parameter T has level 1, but the template function parameter has level 2. Sure, because E<1>::G has been partially instantiated, so the T has been reduced from level 2 to 1. You'll need to do a similar partial instantiation
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches wrote: > On 2/25/21 5:41 PM, Marek Polacek wrote: > > On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote: > > > On 2/12/21 6:12 PM, Marek Polacek wrote: > > > > We represent deduction guides with FUNCTION_DECLs, but they are built > > > > without DECL_CONTEXT > > > > > > Hmm, that seems wrong: "A deduction-guide shall be declared in the > > > same scope as the corresponding class template and, for a member class > > > template, with the same access." But it probably isn't necessary to > > > change > > > this: > > > > > > > leading to an ICE in type_dependent_expression_p > > > > on the assert that the type of a function template with no dependent > > > > (innermost!) template arguments must be non-dependent. Consider the > > > > attached class-deduction79.C: we create a deduction guide: > > > > > > > > template G(T)-> E::G > > > > > > > > we deduce T and create a partial instantiation: > > > > > > > > G(T) -> E::G [with T = int] > > > > > > > > And then do_class_deduction wants to create a CALL_EXPR from the above > > > > using build_new_function_call -> build_over_call which calls mark_used > > > > -> maybe_instantiate_noexcept -> type_dependent_expression_p. > > > > > > > > There, the innermost template arguments are non-dependent (), but > > > > the fntype is dependent -- the return type is a TYPENAME_TYPE, and > > > > since we have no DECL_CONTEXT, this check holds: > > > > > > > > /* Otherwise, if the function decl isn't from a dependent scope, it > > > > can't be > > > >type-dependent. Checking this is important for functions with > > > > auto return > > > >type, which looks like a dependent type. */ > > > > if (TREE_CODE (expression) == FUNCTION_DECL > > > > && !(DECL_CLASS_SCOPE_P (expression) > > > > && dependent_type_p (DECL_CONTEXT (expression))) > > > > > > > > whereupon we ICE. > > > > > > > > Experiments with setting DECL_CONTEXT didn't pan out. > > > > > > In c8 of the PR it looks like you were using the class itself as > > > DECL_CONTEXT; the quote above says that the right context is the enclosing > > > scope of the class. > > > > Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in > > retrieve_specialization: > > > >/* There should be as many levels of arguments as there are > > levels of parameters. */ > >gcc_assert (TMPL_ARGS_DEPTH (args) > >== (TREE_CODE (tmpl) == TEMPLATE_DECL > >? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > >: template_class_depth (DECL_CONTEXT (tmpl; > > Yeah, probably simpler not to bother. > > > > > So perhaps we > > > > just want to skip the assert for deduction guides, because they are > > > > a little special. Better ideas solicited. > > > > > > In c3 you mention that one of the variants broke with r269093; this is > > > because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for > > > the > > > template pattern itself (E). > > > > And the original test started with my r11-1713 because using TREE_TYPE > > directly instead of decltype (which is a non-deduced context) means we > > can deduced from the argument. > > > But I think probably the right answer is to defer this deduction until the > > > enclosing scope is non-dependent, i.e. (untested) > > > > Thanks. That mostly works, except the new class-deduction-aggr[89].C > > tests. Consider 8: > > > > namespace N { > > template struct S { > >template S(T, U); > > }; > > } // namespace N > > template struct E { > >template struct G { T t; }; > >void fn() { G{N::S{'a', 1}}; } > > }; > > > > void > > g () > > { > >E<1> e; > >e.fn (); > > } > > > > With your patch, when in do_class_deduction when processing_template_decl, > > we just return. When we call do_class_deduction again when p_t_d is 0, > > maybe_aggr_guide returns early here: > > > >if (!CP_AGGREGATE_TYPE_P (type)) > > return NULL_TREE > > > > because G is not complete (and rightly so, we didn't instantiate it). So > > we aren't able to deduce the template parameters. I'm not sure if I should > > pursue this direction further. :( > > I think so; we just need to test CP_AGGREGATE_TYPE_P on the original > template pattern instead of the instantiation E<1>::G. I'm sorry, I've got stuck again. Yes, using the original template pattern helps us get past the CP_AGGREGATE_TYPE_P check. However, using TREE_TYPE (DECL_TI_TEMPLATE (tmpl)) as the type of the deduction guide means the guide will be "template G(T)-> E< >::G" which results in class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename E< >::G >' which makes sense I guess: when we defer building up the guide until we've instantiated E<1>, finding the dependent type E<> is not expected. But creating the guide with "struct E<1>::G" as its type seems wrong; I'm not even sure
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On 2/25/21 5:41 PM, Marek Polacek wrote: On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote: On 2/12/21 6:12 PM, Marek Polacek wrote: We represent deduction guides with FUNCTION_DECLs, but they are built without DECL_CONTEXT Hmm, that seems wrong: "A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access." But it probably isn't necessary to change this: leading to an ICE in type_dependent_expression_p on the assert that the type of a function template with no dependent (innermost!) template arguments must be non-dependent. Consider the attached class-deduction79.C: we create a deduction guide: template G(T)-> E::G we deduce T and create a partial instantiation: G(T) -> E::G [with T = int] And then do_class_deduction wants to create a CALL_EXPR from the above using build_new_function_call -> build_over_call which calls mark_used -> maybe_instantiate_noexcept -> type_dependent_expression_p. There, the innermost template arguments are non-dependent (), but the fntype is dependent -- the return type is a TYPENAME_TYPE, and since we have no DECL_CONTEXT, this check holds: /* Otherwise, if the function decl isn't from a dependent scope, it can't be type-dependent. Checking this is important for functions with auto return type, which looks like a dependent type. */ if (TREE_CODE (expression) == FUNCTION_DECL && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) whereupon we ICE. Experiments with setting DECL_CONTEXT didn't pan out. In c8 of the PR it looks like you were using the class itself as DECL_CONTEXT; the quote above says that the right context is the enclosing scope of the class. Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in retrieve_specialization: /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == (TREE_CODE (tmpl) == TEMPLATE_DECL ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) : template_class_depth (DECL_CONTEXT (tmpl; Yeah, probably simpler not to bother. So perhaps we just want to skip the assert for deduction guides, because they are a little special. Better ideas solicited. In c3 you mention that one of the variants broke with r269093; this is because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the template pattern itself (E). And the original test started with my r11-1713 because using TREE_TYPE directly instead of decltype (which is a non-deduced context) means we can deduced from the argument. But I think probably the right answer is to defer this deduction until the enclosing scope is non-dependent, i.e. (untested) Thanks. That mostly works, except the new class-deduction-aggr[89].C tests. Consider 8: namespace N { template struct S { template S(T, U); }; } // namespace N template struct E { template struct G { T t; }; void fn() { G{N::S{'a', 1}}; } }; void g () { E<1> e; e.fn (); } With your patch, when in do_class_deduction when processing_template_decl, we just return. When we call do_class_deduction again when p_t_d is 0, maybe_aggr_guide returns early here: if (!CP_AGGREGATE_TYPE_P (type)) return NULL_TREE because G is not complete (and rightly so, we didn't instantiate it). So we aren't able to deduce the template parameters. I'm not sure if I should pursue this direction further. :( I think so; we just need to test CP_AGGREGATE_TYPE_P on the original template pattern instead of the instantiation E<1>::G. Jason
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote: > On 2/12/21 6:12 PM, Marek Polacek wrote: > > We represent deduction guides with FUNCTION_DECLs, but they are built > > without DECL_CONTEXT > > Hmm, that seems wrong: "A deduction-guide shall be declared in the > same scope as the corresponding class template and, for a member class > template, with the same access." But it probably isn't necessary to change > this: > > > leading to an ICE in type_dependent_expression_p > > on the assert that the type of a function template with no dependent > > (innermost!) template arguments must be non-dependent. Consider the > > attached class-deduction79.C: we create a deduction guide: > > > >template G(T)-> E::G > > > > we deduce T and create a partial instantiation: > > > >G(T) -> E::G [with T = int] > > > > And then do_class_deduction wants to create a CALL_EXPR from the above > > using build_new_function_call -> build_over_call which calls mark_used > > -> maybe_instantiate_noexcept -> type_dependent_expression_p. > > > > There, the innermost template arguments are non-dependent (), but > > the fntype is dependent -- the return type is a TYPENAME_TYPE, and > > since we have no DECL_CONTEXT, this check holds: > > > >/* Otherwise, if the function decl isn't from a dependent scope, it > > can't be > > type-dependent. Checking this is important for functions with auto > > return > > type, which looks like a dependent type. */ > >if (TREE_CODE (expression) == FUNCTION_DECL > >&& !(DECL_CLASS_SCOPE_P (expression) > > && dependent_type_p (DECL_CONTEXT (expression))) > > > > whereupon we ICE. > > > > Experiments with setting DECL_CONTEXT didn't pan out. > > In c8 of the PR it looks like you were using the class itself as > DECL_CONTEXT; the quote above says that the right context is the enclosing > scope of the class. Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in retrieve_specialization: /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == (TREE_CODE (tmpl) == TEMPLATE_DECL ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) : template_class_depth (DECL_CONTEXT (tmpl; > > So perhaps we > > just want to skip the assert for deduction guides, because they are > > a little special. Better ideas solicited. > > In c3 you mention that one of the variants broke with r269093; this is > because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the > template pattern itself (E). And the original test started with my r11-1713 because using TREE_TYPE directly instead of decltype (which is a non-deduced context) means we can deduced from the argument. > But I think probably the right answer is to defer this deduction until the > enclosing scope is non-dependent, i.e. (untested) Thanks. That mostly works, except the new class-deduction-aggr[89].C tests. Consider 8: namespace N { template struct S { template S(T, U); }; } // namespace N template struct E { template struct G { T t; }; void fn() { G{N::S{'a', 1}}; } }; void g () { E<1> e; e.fn (); } With your patch, when in do_class_deduction when processing_template_decl, we just return. When we call do_class_deduction again when p_t_d is 0, maybe_aggr_guide returns early here: if (!CP_AGGREGATE_TYPE_P (type)) return NULL_TREE because G is not complete (and rightly so, we didn't instantiate it). So we aren't able to deduce the template parameters. I'm not sure if I should pursue this direction further. :( Marek
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
On 2/12/21 6:12 PM, Marek Polacek wrote: We represent deduction guides with FUNCTION_DECLs, but they are built without DECL_CONTEXT Hmm, that seems wrong: "A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access." But it probably isn't necessary to change this: leading to an ICE in type_dependent_expression_p on the assert that the type of a function template with no dependent (innermost!) template arguments must be non-dependent. Consider the attached class-deduction79.C: we create a deduction guide: template G(T)-> E::G we deduce T and create a partial instantiation: G(T) -> E::G [with T = int] And then do_class_deduction wants to create a CALL_EXPR from the above using build_new_function_call -> build_over_call which calls mark_used -> maybe_instantiate_noexcept -> type_dependent_expression_p. There, the innermost template arguments are non-dependent (), but the fntype is dependent -- the return type is a TYPENAME_TYPE, and since we have no DECL_CONTEXT, this check holds: /* Otherwise, if the function decl isn't from a dependent scope, it can't be type-dependent. Checking this is important for functions with auto return type, which looks like a dependent type. */ if (TREE_CODE (expression) == FUNCTION_DECL && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) whereupon we ICE. Experiments with setting DECL_CONTEXT didn't pan out. In c8 of the PR it looks like you were using the class itself as DECL_CONTEXT; the quote above says that the right context is the enclosing scope of the class. So perhaps we just want to skip the assert for deduction guides, because they are a little special. Better ideas solicited. In c3 you mention that one of the variants broke with r269093; this is because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the template pattern itself (E). But I think probably the right answer is to defer this deduction until the enclosing scope is non-dependent, i.e. (untested) >From a0c19e712b8d8e6048d7371b237dc38cad2b9119 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 25 Feb 2021 10:55:28 -0500 Subject: [PATCH] dep To: gcc-patches@gcc.gnu.org --- gcc/cp/pt.c | 4 1 file changed, 4 insertions(+) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3576e0effb6..0e383d2434e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -29214,6 +29214,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init, if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)) return ptype; + if (DECL_CLASS_SCOPE_P (tmpl) + && dependent_type_p (DECL_CONTEXT (tmpl))) +return ptype; + /* Initializing one placeholder from another. */ if (init && TREE_CODE (init) == TEMPLATE_PARM_INDEX && is_auto (TREE_TYPE (init)) -- 2.27.0
Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
Ping. On Fri, Feb 12, 2021 at 06:12:12PM -0500, Marek Polacek via Gcc-patches wrote: > We represent deduction guides with FUNCTION_DECLs, but they are built > without DECL_CONTEXT, leading to an ICE in type_dependent_expression_p > on the assert that the type of a function template with no dependent > (innermost!) template arguments must be non-dependent. Consider the > attached class-deduction79.C: we create a deduction guide: > > template G(T)-> E::G > > we deduce T and create a partial instantiation: > > G(T) -> E::G [with T = int] > > And then do_class_deduction wants to create a CALL_EXPR from the above > using build_new_function_call -> build_over_call which calls mark_used > -> maybe_instantiate_noexcept -> type_dependent_expression_p. > > There, the innermost template arguments are non-dependent (), but > the fntype is dependent -- the return type is a TYPENAME_TYPE, and > since we have no DECL_CONTEXT, this check holds: > > /* Otherwise, if the function decl isn't from a dependent scope, it can't be > type-dependent. Checking this is important for functions with auto > return > type, which looks like a dependent type. */ > if (TREE_CODE (expression) == FUNCTION_DECL > && !(DECL_CLASS_SCOPE_P (expression) >&& dependent_type_p (DECL_CONTEXT (expression))) > > whereupon we ICE. > > Experiments with setting DECL_CONTEXT didn't pan out. So perhaps we > just want to skip the assert for deduction guides, because they are > a little special. Better ideas solicited. > > Bootstrapped/regtested on x86_64-pc-linux-gnu. > > gcc/cp/ChangeLog: > > PR c++/97034 > PR c++/99009 > * pt.c (type_dependent_expression_p): Don't assert that the type > of a deduction guide must non-dependent. > > gcc/testsuite/ChangeLog: > > PR c++/97034 > PR c++/99009 > * g++.dg/cpp1z/class-deduction79.C: New test. > * g++.dg/cpp1z/class-deduction80.C: New test. > * g++.dg/cpp2a/class-deduction-aggr8.C: New test. > * g++.dg/cpp2a/class-deduction-aggr9.C: New test. > --- > gcc/cp/pt.c | 5 - > .../g++.dg/cpp1z/class-deduction79.C | 20 +++ > .../g++.dg/cpp1z/class-deduction80.C | 12 +++ > .../g++.dg/cpp2a/class-deduction-aggr8.C | 19 ++ > .../g++.dg/cpp2a/class-deduction-aggr9.C | 18 + > 5 files changed, 73 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction79.C > create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction80.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index 60de8e93ff7..3e6f3407d40 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -27282,7 +27282,10 @@ type_dependent_expression_p (tree expression) > && DECL_UNIQUE_FRIEND_P (expression) > && (!DECL_FRIEND_CONTEXT (expression) > || dependent_type_p (DECL_FRIEND_CONTEXT (expression > - && !DECL_LOCAL_DECL_P (expression)) > + && !DECL_LOCAL_DECL_P (expression) > + /* We build deduction guides without any DECL_CONTEXT, but they can > + be type-dependent. */ > + && !deduction_guide_p (expression)) > { >gcc_assert (!dependent_type_p (TREE_TYPE (expression)) > || undeduced_auto_decl (expression)); > diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C > b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C > new file mode 100644 > index 000..86a68248157 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C > @@ -0,0 +1,20 @@ > +// PR c++/97034 > +// { dg-do compile { target c++17 } } > + > +template > +struct E { > + template > + struct G { > +T t; > +G(T) { } > + }; > + > + void fn() { G{1}; } > +}; > + > +void > +g () > +{ > + E e; > + e.fn (); > +} > diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C > b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C > new file mode 100644 > index 000..238024c508f > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C > @@ -0,0 +1,12 @@ > +// PR c++/99009 > +// { dg-do compile { target c++17 } } > + > +template struct B { > + B(int = A()) {} > + template struct A; > +}; > + > +template struct X { > + template struct Y; > + X() { Y y; }; > +}; > diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C > b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C > new file mode 100644 > index 000..399061100ae > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C > @@ -0,0 +1,19 @@ > +// PR c++/97034 > +// { dg-do compile { target c++20 } } > + > +namespace N { > +template struct S { > + template S(T, U); > +}; > +} // namespace N > +template struct E { > + template struct G { T t; }; > + void fn() {
[PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]
We represent deduction guides with FUNCTION_DECLs, but they are built without DECL_CONTEXT, leading to an ICE in type_dependent_expression_p on the assert that the type of a function template with no dependent (innermost!) template arguments must be non-dependent. Consider the attached class-deduction79.C: we create a deduction guide: template G(T)-> E::G we deduce T and create a partial instantiation: G(T) -> E::G [with T = int] And then do_class_deduction wants to create a CALL_EXPR from the above using build_new_function_call -> build_over_call which calls mark_used -> maybe_instantiate_noexcept -> type_dependent_expression_p. There, the innermost template arguments are non-dependent (), but the fntype is dependent -- the return type is a TYPENAME_TYPE, and since we have no DECL_CONTEXT, this check holds: /* Otherwise, if the function decl isn't from a dependent scope, it can't be type-dependent. Checking this is important for functions with auto return type, which looks like a dependent type. */ if (TREE_CODE (expression) == FUNCTION_DECL && !(DECL_CLASS_SCOPE_P (expression) && dependent_type_p (DECL_CONTEXT (expression))) whereupon we ICE. Experiments with setting DECL_CONTEXT didn't pan out. So perhaps we just want to skip the assert for deduction guides, because they are a little special. Better ideas solicited. Bootstrapped/regtested on x86_64-pc-linux-gnu. gcc/cp/ChangeLog: PR c++/97034 PR c++/99009 * pt.c (type_dependent_expression_p): Don't assert that the type of a deduction guide must non-dependent. gcc/testsuite/ChangeLog: PR c++/97034 PR c++/99009 * g++.dg/cpp1z/class-deduction79.C: New test. * g++.dg/cpp1z/class-deduction80.C: New test. * g++.dg/cpp2a/class-deduction-aggr8.C: New test. * g++.dg/cpp2a/class-deduction-aggr9.C: New test. --- gcc/cp/pt.c | 5 - .../g++.dg/cpp1z/class-deduction79.C | 20 +++ .../g++.dg/cpp1z/class-deduction80.C | 12 +++ .../g++.dg/cpp2a/class-deduction-aggr8.C | 19 ++ .../g++.dg/cpp2a/class-deduction-aggr9.C | 18 + 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction79.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction80.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 60de8e93ff7..3e6f3407d40 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -27282,7 +27282,10 @@ type_dependent_expression_p (tree expression) && DECL_UNIQUE_FRIEND_P (expression) && (!DECL_FRIEND_CONTEXT (expression) || dependent_type_p (DECL_FRIEND_CONTEXT (expression - && !DECL_LOCAL_DECL_P (expression)) + && !DECL_LOCAL_DECL_P (expression) + /* We build deduction guides without any DECL_CONTEXT, but they can +be type-dependent. */ + && !deduction_guide_p (expression)) { gcc_assert (!dependent_type_p (TREE_TYPE (expression)) || undeduced_auto_decl (expression)); diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C new file mode 100644 index 000..86a68248157 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C @@ -0,0 +1,20 @@ +// PR c++/97034 +// { dg-do compile { target c++17 } } + +template +struct E { + template + struct G { +T t; +G(T) { } + }; + + void fn() { G{1}; } +}; + +void +g () +{ + E e; + e.fn (); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C new file mode 100644 index 000..238024c508f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C @@ -0,0 +1,12 @@ +// PR c++/99009 +// { dg-do compile { target c++17 } } + +template struct B { + B(int = A()) {} + template struct A; +}; + +template struct X { + template struct Y; + X() { Y y; }; +}; diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C new file mode 100644 index 000..399061100ae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C @@ -0,0 +1,19 @@ +// PR c++/97034 +// { dg-do compile { target c++20 } } + +namespace N { +template struct S { + template S(T, U); +}; +} // namespace N +template struct E { + template struct G { T t; }; + void fn() { G{N::S{'a', 1}}; } +}; + +void +g () +{ + E<1> e; + e.fn (); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C new file mode 100644 index 000..245a04cd5f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C @@ -0,0 +1,18 @@ +// PR c++/97034 +// {