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<class T> G(T)-> E<Z>::G<T> > > > > > > > > we deduce T and create a partial instantiation: > > > > > > > > G(T) -> E<Z>::G<T> [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 (<int>), 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<Z>). > > > > 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 <typename, typename> struct S { > > template <typename T, typename U> S(T, U); > > }; > > } // namespace N > > template <int> struct E { > > template <typename T> struct G { T t; }; > > void fn() { G{N::S<char, int>{'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<class T> G(T)-> E<<anonymous> >::G<T>" which results in class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename E<<anonymous> >::G<N::S<char, int> >' 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<T>" as its type seems wrong; I'm not even sure if a guide like template<class T> G(T)-> E<1>::G<T> makes sense. 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. Marek