Re: [PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679]
On 12/15/23 14:06, Patrick Palka wrote: On Mon, 11 Sep 2023, Patrick Palka wrote: On Thu, 1 Jun 2023, Patrick Palka wrote: For a complex alias template-id, dependent_alias_template_spec_p returns true if any template argument of the template-id is dependent. This predicate indicates that substitution into the template-id may behave differently with respect to SFINAE than substitution into the expanded alias, and so the alias is in a way non-transparent. For example 'first_t' in template using first_t = T; template first_t f(); is such an alias template-id since first_t doesn't use its second template parameter and so the substitution into the expanded alias would discard the SFINAE effects of the corresponding (dependent) argument 'T&'. But this predicate is overly conservative since what really matters for sake of SFINAE equivalence is whether a template argument corresponding to an _unused_ template parameter is dependent. So the predicate should return false for e.g. 'first_t' or 'first_t'. This patch refines the predicate appropriately. We need to be able to efficiently determine which template parameters of a complex alias template are unused, so to that end we add a new out parameter to complex_alias_template_p and cache its result in an on-the-side hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P flag. And in doing so, we fix a latent bug that this flag wasn't being propagated during partial instantiation, and so we were treating all partially instantiated member alias templates as non-complex. PR c++/90679 gcc/cp/ChangeLog: * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. (most_general_template): Constify parameter. * pt.cc (push_template_decl): Adjust after removing TEMPLATE_DECL_COMPLEX_ALIAS_P. (complex_alias_tmpl_info): New hash_map. (uses_all_template_parms_data::seen): Change type to tree* from bool*. (complex_alias_template_r): Adjust accordingly. (complex_alias_template_p): Add 'seen_out' out parameter. Call most_general_template and check PRIMARY_TEMPLATE_P. Use complex_alias_tmpl_info to cache the result and set '*seen_out' accordigly. (dependent_alias_template_spec_p): Add !processing_template_decl early exit test. Consider dependence of only template arguments corresponding to seen template parameters as per gcc/testsuite/ChangeLog: * g++.dg/cpp0x/alias-decl-75.C: New test. Ping. Ping. Here's a rebased patch: OK. -- >8 -- Subject: [PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679] For a (complex) alias template-id, dependent_alias_template_spec_p returns true if any template argument of the template-id is dependent. This predicate indicates that substitution into the template-id may behave differently with respect to SFINAE than substitution into the expanded alias, and so the alias is in a way non-transparent. For example, 'first_t' in template using first_t = T; template first_t f(); is such an alias template-id since first_t doesn't use its second template parameter and so the substitution into the expanded alias would discard the SFINAE effects of the corresponding (dependent) argument 'T&'. But this predicate is overly conservative since what really matters for sake of SFINAE equivalence is whether a template argument corresponding to an _unused_ template parameter is dependent. So the predicate should return false for e.g. 'first_t'. This patch refines the predicate appropriately. We need to be able to efficiently determine which template parameters of a complex alias template are unused, so to that end we add a new out parameter to complex_alias_template_p and cache its result in an on-the-side hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P flag. PR c++/90679 gcc/cp/ChangeLog: * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. (most_general_template): Constify parameter. * pt.cc (push_template_decl): Adjust after removing TEMPLATE_DECL_COMPLEX_ALIAS_P. (complex_alias_tmpl_info): New hash_map. (uses_all_template_parms_data::seen): Change type to tree* from bool*. (complex_alias_template_r): Adjust accordingly. (complex_alias_template_p): Add 'seen_out' out parameter. Call most_general_template and check PRIMARY_TEMPLATE_P. Use complex_alias_tmpl_info to cache the result and set '*seen_out' accordigly. (dependent_alias_template_spec_p): Add !processing_template_decl early exit test. Consider dependence of only template arguments corresponding to seen template parameters as per gcc/testsuite/ChangeLog: * g++.dg/cpp0x/alias-decl-76.C: New test. --- gcc/cp/cp-tree.h | 7 +- gcc/cp/pt.cc | 104 +++-- gcc/testsuite/g
Re: [PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679]
On Mon, 11 Sep 2023, Patrick Palka wrote: > On Thu, 1 Jun 2023, Patrick Palka wrote: > > > For a complex alias template-id, dependent_alias_template_spec_p returns > > true if any template argument of the template-id is dependent. This > > predicate indicates that substitution into the template-id may behave > > differently with respect to SFINAE than substitution into the expanded > > alias, and so the alias is in a way non-transparent. For example > > 'first_t' in > > > > template using first_t = T; > > template first_t f(); > > > > is such an alias template-id since first_t doesn't use its second > > template parameter and so the substitution into the expanded alias would > > discard the SFINAE effects of the corresponding (dependent) argument 'T&'. > > > > But this predicate is overly conservative since what really matters for > > sake of SFINAE equivalence is whether a template argument corresponding > > to an _unused_ template parameter is dependent. So the predicate should > > return false for e.g. 'first_t' or 'first_t'. > > > > This patch refines the predicate appropriately. We need to be able to > > efficiently determine which template parameters of a complex alias > > template are unused, so to that end we add a new out parameter to > > complex_alias_template_p and cache its result in an on-the-side > > hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P > > flag. And in doing so, we fix a latent bug that this flag wasn't > > being propagated during partial instantiation, and so we were treating > > all partially instantiated member alias templates as non-complex. > > > > PR c++/90679 > > > > gcc/cp/ChangeLog: > > > > * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. > > (most_general_template): Constify parameter. > > * pt.cc (push_template_decl): Adjust after removing > > TEMPLATE_DECL_COMPLEX_ALIAS_P. > > (complex_alias_tmpl_info): New hash_map. > > (uses_all_template_parms_data::seen): Change type to > > tree* from bool*. > > (complex_alias_template_r): Adjust accordingly. > > (complex_alias_template_p): Add 'seen_out' out parameter. > > Call most_general_template and check PRIMARY_TEMPLATE_P. > > Use complex_alias_tmpl_info to cache the result and set > > '*seen_out' accordigly. > > (dependent_alias_template_spec_p): Add !processing_template_decl > > early exit test. Consider dependence of only template arguments > > corresponding to seen template parameters as per > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp0x/alias-decl-75.C: New test. > > Ping. Ping. Here's a rebased patch: -- >8 -- Subject: [PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679] For a (complex) alias template-id, dependent_alias_template_spec_p returns true if any template argument of the template-id is dependent. This predicate indicates that substitution into the template-id may behave differently with respect to SFINAE than substitution into the expanded alias, and so the alias is in a way non-transparent. For example, 'first_t' in template using first_t = T; template first_t f(); is such an alias template-id since first_t doesn't use its second template parameter and so the substitution into the expanded alias would discard the SFINAE effects of the corresponding (dependent) argument 'T&'. But this predicate is overly conservative since what really matters for sake of SFINAE equivalence is whether a template argument corresponding to an _unused_ template parameter is dependent. So the predicate should return false for e.g. 'first_t'. This patch refines the predicate appropriately. We need to be able to efficiently determine which template parameters of a complex alias template are unused, so to that end we add a new out parameter to complex_alias_template_p and cache its result in an on-the-side hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P flag. PR c++/90679 gcc/cp/ChangeLog: * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. (most_general_template): Constify parameter. * pt.cc (push_template_decl): Adjust after removing TEMPLATE_DECL_COMPLEX_ALIAS_P. (complex_alias_tmpl_info): New hash_map. (uses_all_template_parms_data::seen): Change type to tree* from bool*. (complex_alias_template_r): Adjust accordingly. (complex_alias_template_p): Add 'seen_out' out parameter. Call most_general_template and check PRIMARY_TEMPLATE_P. Use complex_alias_tmpl_info to cache the result and set '*seen_out' accordigly. (dependent_al
Re: [PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679]
On Thu, 1 Jun 2023, Patrick Palka wrote: > For a complex alias template-id, dependent_alias_template_spec_p returns > true if any template argument of the template-id is dependent. This > predicate indicates that substitution into the template-id may behave > differently with respect to SFINAE than substitution into the expanded > alias, and so the alias is in a way non-transparent. For example > 'first_t' in > > template using first_t = T; > template first_t f(); > > is such an alias template-id since first_t doesn't use its second > template parameter and so the substitution into the expanded alias would > discard the SFINAE effects of the corresponding (dependent) argument 'T&'. > > But this predicate is overly conservative since what really matters for > sake of SFINAE equivalence is whether a template argument corresponding > to an _unused_ template parameter is dependent. So the predicate should > return false for e.g. 'first_t' or 'first_t'. > > This patch refines the predicate appropriately. We need to be able to > efficiently determine which template parameters of a complex alias > template are unused, so to that end we add a new out parameter to > complex_alias_template_p and cache its result in an on-the-side > hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P > flag. And in doing so, we fix a latent bug that this flag wasn't > being propagated during partial instantiation, and so we were treating > all partially instantiated member alias templates as non-complex. > > PR c++/90679 > > gcc/cp/ChangeLog: > > * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. > (most_general_template): Constify parameter. > * pt.cc (push_template_decl): Adjust after removing > TEMPLATE_DECL_COMPLEX_ALIAS_P. > (complex_alias_tmpl_info): New hash_map. > (uses_all_template_parms_data::seen): Change type to > tree* from bool*. > (complex_alias_template_r): Adjust accordingly. > (complex_alias_template_p): Add 'seen_out' out parameter. > Call most_general_template and check PRIMARY_TEMPLATE_P. > Use complex_alias_tmpl_info to cache the result and set > '*seen_out' accordigly. > (dependent_alias_template_spec_p): Add !processing_template_decl > early exit test. Consider dependence of only template arguments > corresponding to seen template parameters as per > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/alias-decl-75.C: New test. Ping. > --- > gcc/cp/cp-tree.h | 7 +- > gcc/cp/pt.cc | 101 +++-- > gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C | 24 + > 3 files changed, 100 insertions(+), 32 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index a1b882f11fe..5330d1e1f62 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -543,7 +543,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; > 2: DECL_THIS_EXTERN (in VAR_DECL, FUNCTION_DECL or PARM_DECL) >DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) >DECL_CONSTRAINT_VAR_P (in a PARM_DECL) > - TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL) >DECL_INSTANTIATING_NSDMI_P (in a FIELD_DECL) >USING_DECL_UNRELATED_P (in USING_DECL) > 3: DECL_IN_AGGR_P. > @@ -3655,10 +3654,6 @@ struct GTY(()) lang_decl { > #define TYPE_DECL_ALIAS_P(NODE) \ >DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE)) > > -/* Nonzero for TEMPLATE_DECL means that it is a 'complex' alias template. */ > -#define TEMPLATE_DECL_COMPLEX_ALIAS_P(NODE) \ > - DECL_LANG_FLAG_2 (TEMPLATE_DECL_CHECK (NODE)) > - > /* Nonzero for a type which is an alias for another type; i.e, a type > which declaration was written 'using name-of-type = > another-type'. */ > @@ -7403,7 +7398,7 @@ extern tree tsubst_argument_pack(tree, > tree, tsubst_flags_t, tree); > extern tree tsubst_template_args (tree, tree, tsubst_flags_t, > tree); > extern tree tsubst_template_arg (tree, tree, > tsubst_flags_t, tree); > extern tree tsubst_function_parms(tree, tree, tsubst_flags_t, > tree); > -extern tree most_general_template(tree); > +extern tree most_general_template(const_tree); > extern tree get_mostly_instantiated_function_type (tree); > extern bool problematic_instantiation_changed(void); > extern void record_last_problematic_instantiation (void); > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index 7fb3e75bceb..1b28195e10d 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -211,7 +211,6 @@ static tree listify (tree); > static tree listify_autos (tree, tree); > static tree tsubst_template_parm (tree, tree, tsubst_flags_t); > static tree instantiate_alias_template (tree, tree, tsubst_flags_t); > -static bool complex_alias_template_p (const_tree tmpl); > static tree
Re: [PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679]
On Thu, 1 Jun 2023, Patrick Palka wrote: > For a complex alias template-id, dependent_alias_template_spec_p returns > true if any template argument of the template-id is dependent. This > predicate indicates that substitution into the template-id may behave > differently with respect to SFINAE than substitution into the expanded > alias, and so the alias is in a way non-transparent. For example > 'first_t' in > > template using first_t = T; > template first_t f(); > > is such an alias template-id since first_t doesn't use its second > template parameter and so the substitution into the expanded alias would > discard the SFINAE effects of the corresponding (dependent) argument 'T&'. > > But this predicate is overly conservative since what really matters for > sake of SFINAE equivalence is whether a template argument corresponding > to an _unused_ template parameter is dependent. So the predicate should > return false for e.g. 'first_t' or 'first_t'. > > This patch refines the predicate appropriately. We need to be able to > efficiently determine which template parameters of a complex alias > template are unused, so to that end we add a new out parameter to > complex_alias_template_p and cache its result in an on-the-side > hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P > flag. And in doing so, we fix a latent bug that this flag wasn't > being propagated during partial instantiation, and so we were treating > all partially instantiated member alias templates as non-complex. Whoops, this last sentence is wrong I think. The flag propagation would have happened via the call to copy_decl from tsubst_template_decl, so there was no latent bug. > > PR c++/90679 > > gcc/cp/ChangeLog: > > * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. > (most_general_template): Constify parameter. > * pt.cc (push_template_decl): Adjust after removing > TEMPLATE_DECL_COMPLEX_ALIAS_P. > (complex_alias_tmpl_info): New hash_map. > (uses_all_template_parms_data::seen): Change type to > tree* from bool*. > (complex_alias_template_r): Adjust accordingly. > (complex_alias_template_p): Add 'seen_out' out parameter. > Call most_general_template and check PRIMARY_TEMPLATE_P. > Use complex_alias_tmpl_info to cache the result and set > '*seen_out' accordigly. > (dependent_alias_template_spec_p): Add !processing_template_decl > early exit test. Consider dependence of only template arguments > corresponding to seen template parameters as per > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/alias-decl-75.C: New test. > --- > gcc/cp/cp-tree.h | 7 +- > gcc/cp/pt.cc | 101 +++-- > gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C | 24 + > 3 files changed, 100 insertions(+), 32 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > index a1b882f11fe..5330d1e1f62 100644 > --- a/gcc/cp/cp-tree.h > +++ b/gcc/cp/cp-tree.h > @@ -543,7 +543,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; > 2: DECL_THIS_EXTERN (in VAR_DECL, FUNCTION_DECL or PARM_DECL) >DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) >DECL_CONSTRAINT_VAR_P (in a PARM_DECL) > - TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL) >DECL_INSTANTIATING_NSDMI_P (in a FIELD_DECL) >USING_DECL_UNRELATED_P (in USING_DECL) > 3: DECL_IN_AGGR_P. > @@ -3655,10 +3654,6 @@ struct GTY(()) lang_decl { > #define TYPE_DECL_ALIAS_P(NODE) \ >DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE)) > > -/* Nonzero for TEMPLATE_DECL means that it is a 'complex' alias template. */ > -#define TEMPLATE_DECL_COMPLEX_ALIAS_P(NODE) \ > - DECL_LANG_FLAG_2 (TEMPLATE_DECL_CHECK (NODE)) > - > /* Nonzero for a type which is an alias for another type; i.e, a type > which declaration was written 'using name-of-type = > another-type'. */ > @@ -7403,7 +7398,7 @@ extern tree tsubst_argument_pack(tree, > tree, tsubst_flags_t, tree); > extern tree tsubst_template_args (tree, tree, tsubst_flags_t, > tree); > extern tree tsubst_template_arg (tree, tree, > tsubst_flags_t, tree); > extern tree tsubst_function_parms(tree, tree, tsubst_flags_t, > tree); > -extern tree most_general_template(tree); > +extern tree most_general_template(const_tree); > extern tree get_mostly_instantiated_function_type (tree); > extern bool problematic_instantiation_changed(void); > extern void record_last_problematic_instantiation (void); > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index 7fb3e75bceb..1b28195e10d 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -211,7 +211,6 @@ static tree listify (tree); > static tree listify_autos (tree, tree); > static tree tsubst_template_parm (tree, tree, tsubst_flags_t); >
[PATCH 1/2] c++: refine dependent_alias_template_spec_p [PR90679]
For a complex alias template-id, dependent_alias_template_spec_p returns true if any template argument of the template-id is dependent. This predicate indicates that substitution into the template-id may behave differently with respect to SFINAE than substitution into the expanded alias, and so the alias is in a way non-transparent. For example 'first_t' in template using first_t = T; template first_t f(); is such an alias template-id since first_t doesn't use its second template parameter and so the substitution into the expanded alias would discard the SFINAE effects of the corresponding (dependent) argument 'T&'. But this predicate is overly conservative since what really matters for sake of SFINAE equivalence is whether a template argument corresponding to an _unused_ template parameter is dependent. So the predicate should return false for e.g. 'first_t' or 'first_t'. This patch refines the predicate appropriately. We need to be able to efficiently determine which template parameters of a complex alias template are unused, so to that end we add a new out parameter to complex_alias_template_p and cache its result in an on-the-side hash_map that replaces the existing TEMPLATE_DECL_COMPLEX_ALIAS_P flag. And in doing so, we fix a latent bug that this flag wasn't being propagated during partial instantiation, and so we were treating all partially instantiated member alias templates as non-complex. PR c++/90679 gcc/cp/ChangeLog: * cp-tree.h (TEMPLATE_DECL_COMPLEX_ALIAS_P): Remove. (most_general_template): Constify parameter. * pt.cc (push_template_decl): Adjust after removing TEMPLATE_DECL_COMPLEX_ALIAS_P. (complex_alias_tmpl_info): New hash_map. (uses_all_template_parms_data::seen): Change type to tree* from bool*. (complex_alias_template_r): Adjust accordingly. (complex_alias_template_p): Add 'seen_out' out parameter. Call most_general_template and check PRIMARY_TEMPLATE_P. Use complex_alias_tmpl_info to cache the result and set '*seen_out' accordigly. (dependent_alias_template_spec_p): Add !processing_template_decl early exit test. Consider dependence of only template arguments corresponding to seen template parameters as per gcc/testsuite/ChangeLog: * g++.dg/cpp0x/alias-decl-75.C: New test. --- gcc/cp/cp-tree.h | 7 +- gcc/cp/pt.cc | 101 +++-- gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C | 24 + 3 files changed, 100 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a1b882f11fe..5330d1e1f62 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -543,7 +543,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; 2: DECL_THIS_EXTERN (in VAR_DECL, FUNCTION_DECL or PARM_DECL) DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) DECL_CONSTRAINT_VAR_P (in a PARM_DECL) - TEMPLATE_DECL_COMPLEX_ALIAS_P (in TEMPLATE_DECL) DECL_INSTANTIATING_NSDMI_P (in a FIELD_DECL) USING_DECL_UNRELATED_P (in USING_DECL) 3: DECL_IN_AGGR_P. @@ -3655,10 +3654,6 @@ struct GTY(()) lang_decl { #define TYPE_DECL_ALIAS_P(NODE) \ DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE)) -/* Nonzero for TEMPLATE_DECL means that it is a 'complex' alias template. */ -#define TEMPLATE_DECL_COMPLEX_ALIAS_P(NODE) \ - DECL_LANG_FLAG_2 (TEMPLATE_DECL_CHECK (NODE)) - /* Nonzero for a type which is an alias for another type; i.e, a type which declaration was written 'using name-of-type = another-type'. */ @@ -7403,7 +7398,7 @@ extern tree tsubst_argument_pack (tree, tree, tsubst_flags_t, tree); extern tree tsubst_template_args (tree, tree, tsubst_flags_t, tree); extern tree tsubst_template_arg(tree, tree, tsubst_flags_t, tree); extern tree tsubst_function_parms (tree, tree, tsubst_flags_t, tree); -extern tree most_general_template (tree); +extern tree most_general_template (const_tree); extern tree get_mostly_instantiated_function_type (tree); extern bool problematic_instantiation_changed (void); extern void record_last_problematic_instantiation (void); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 7fb3e75bceb..1b28195e10d 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -211,7 +211,6 @@ static tree listify (tree); static tree listify_autos (tree, tree); static tree tsubst_template_parm (tree, tree, tsubst_flags_t); static tree instantiate_alias_template (tree, tree, tsubst_flags_t); -static bool complex_alias_template_p (const_tree tmpl); static tree get_underlying_template (tree); static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree); static tree canonicalize_expr_argument (tree, tsubst_flags_t); @@ -6233,8 +6232,6 @@ push_template_decl (tree decl, bool is_friend)