diff options
author | Jason Merrill <jason@redhat.com> | 2019-11-27 17:05:47 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-11-27 17:05:47 -0500 |
commit | 1f41df916c2d6d7598cb5e67cdaebdc86910e902 (patch) | |
tree | 50c06c4b53bf6fd71ab1e834aabdcf0a2c7e4b37 /gcc/cp | |
parent | 96cbfa7ff8a146febd6af9a53d10468a90706419 (diff) | |
download | gcc-1f41df916c2d6d7598cb5e67cdaebdc86910e902.zip gcc-1f41df916c2d6d7598cb5e67cdaebdc86910e902.tar.gz gcc-1f41df916c2d6d7598cb5e67cdaebdc86910e902.tar.bz2 |
Fix constrained alias template transparency.
A constrained alias template can't be treated as equivalent to its
underlying template/type for much the same reason that an alias template
like void_t can't; we're relying on checking during substitution.
* cxx-pretty-print.c (pp_cxx_unqualified_id): Handle alias
template-id.
* pt.c (complex_alias_template_p): True if constraints.
(get_underlying_template, tsubst): Check alias constraints.
(push_template_decl_real): Set alias constraints here.
* parser.c (cp_parser_alias_declaration): Not here.
* constraint.cc (get_constraints): Take const_tree.
From-SVN: r278785
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/constraint.cc | 15 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 6 | ||||
-rw-r--r-- | gcc/cp/parser.c | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 53 |
6 files changed, 75 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0f26009..9dbc61c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2019-11-16 Jason Merrill <jason@redhat.com> + + * cxx-pretty-print.c (pp_cxx_unqualified_id): Handle alias + template-id. + * pt.c (complex_alias_template_p): True if constraints. + (get_underlying_template, tsubst): Check alias constraints. + (push_template_decl_real): Set alias constraints here. + * parser.c (cp_parser_alias_declaration): Not here. + * constraint.cc (get_constraints): Take const_tree. + 2019-11-12 Jason Merrill <jason@redhat.com> PR c++/92206 - ICE with typedef to dependent alias. diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index fadbe7c..0d1c27a 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1124,7 +1124,7 @@ static GTY ((cache)) decl_tree_cache_map *decl_constraints; constrained, return NULL_TREE. Note that T must be non-null. */ tree -get_constraints (tree t) +get_constraints (const_tree t) { if (!flag_concepts) return NULL_TREE; @@ -1134,7 +1134,7 @@ get_constraints (tree t) gcc_assert (DECL_P (t)); if (TREE_CODE (t) == TEMPLATE_DECL) t = DECL_TEMPLATE_RESULT (t); - tree* found = decl_constraints->get (t); + tree* found = decl_constraints->get (CONST_CAST_TREE (t)); if (found) return *found; else @@ -2966,6 +2966,17 @@ more_constrained (tree d1, tree d2) return winner; } +/* Return whether D1 is at least as constrained as D2. */ + +bool +at_least_as_constrained (tree d1, tree d2) +{ + tree n1 = get_normalized_constraints_from_decl (d1); + tree n2 = get_normalized_constraints_from_decl (d2); + + return subsumes (n1, n2); +} + /*--------------------------------------------------------------------------- Constraint diagnostics ---------------------------------------------------------------------------*/ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d8e12e9..fd3be60 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7772,7 +7772,8 @@ extern cp_expr finish_constraint_and_expr (location_t, cp_expr, cp_expr); extern cp_expr finish_constraint_primary_expr (cp_expr); extern tree finish_concept_definition (cp_expr, tree); extern tree combine_constraint_expressions (tree, tree); -extern tree get_constraints (tree); +extern tree append_constraint (tree, tree); +extern tree get_constraints (const_tree); extern void set_constraints (tree, tree); extern void remove_constraints (tree); extern tree current_template_constraints (void); @@ -7834,6 +7835,7 @@ extern bool subsumes_constraints (tree, tree); extern bool strictly_subsumes (tree, tree, tree); extern bool weakly_subsumes (tree, tree, tree); extern int more_constrained (tree, tree); +extern bool at_least_as_constrained (tree, tree); extern bool constraints_equivalent_p (tree, tree); extern bool atomic_constraints_identical_p (tree, tree); extern hashval_t iterative_hash_constraint (tree, hashval_t); diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 8ece11d..909b2a4e 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -172,11 +172,11 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t) case TYPENAME_TYPE: case UNBOUND_CLASS_TEMPLATE: pp_cxx_unqualified_id (pp, TYPE_NAME (t)); - if (CLASS_TYPE_P (t) && CLASSTYPE_USE_TEMPLATE (t)) + if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (t)) { pp_cxx_begin_template_argument_list (pp); - pp_cxx_template_argument_list (pp, INNERMOST_TEMPLATE_ARGS - (CLASSTYPE_TI_ARGS (t))); + tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti)); + pp_cxx_template_argument_list (pp, args); pp_cxx_end_template_argument_list (pp); } break; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 27318d3..c08b7b3 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19901,14 +19901,6 @@ cp_parser_alias_declaration (cp_parser* parser) if (decl == error_mark_node) return decl; - /* Attach constraints to the alias declaration. */ - if (flag_concepts && current_template_parms) - { - tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); - tree constr = build_constraints (reqs, NULL_TREE); - set_constraints (decl, constr); - } - cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0); if (pushed_scope) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 244eb7d..6e712bd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -215,6 +215,7 @@ 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); static tree make_argument_pack (tree); @@ -5989,9 +5990,18 @@ push_template_decl_real (tree decl, bool is_friend) } if (TREE_CODE (decl) == TYPE_DECL - && TYPE_DECL_ALIAS_P (decl) - && complex_alias_template_p (tmpl)) - TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true; + && TYPE_DECL_ALIAS_P (decl)) + { + if (tree constr + = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl))) + { + /* ??? Why don't we do this here for all templates? */ + constr = build_constraints (constr, NULL_TREE); + set_constraints (decl, constr); + } + if (complex_alias_template_p (tmpl)) + TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true; + } } /* The DECL_TI_ARGS of DECL contains full set of arguments referring @@ -6350,6 +6360,14 @@ uses_all_template_parms_r (tree t, void *data_) static bool complex_alias_template_p (const_tree tmpl) { + /* A renaming alias isn't complex. */ + if (get_underlying_template (CONST_CAST_TREE (tmpl)) != tmpl) + return false; + + /* Any other constrained alias is complex. */ + if (get_constraints (tmpl)) + return true; + struct uses_all_template_parms_data data; tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl)); tree parms = DECL_TEMPLATE_PARMS (tmpl); @@ -6395,7 +6413,7 @@ dependent_alias_template_spec_p (const_tree t, bool transparent_typedefs) /* Return the number of innermost template parameters in TMPL. */ static int -num_innermost_template_parms (tree tmpl) +num_innermost_template_parms (const_tree tmpl) { tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl)); return TREE_VEC_LENGTH (parms); @@ -6430,6 +6448,11 @@ get_underlying_template (tree tmpl) if (!comp_template_args (TI_ARGS (tinfo), alias_args)) break; + /* If TMPL adds or changes any constraints, it isn't equivalent. I think + it's appropriate to treat a less-constrained alias as equivalent. */ + if (!at_least_as_constrained (underlying, tmpl)) + break; + /* Alias is equivalent. Strip it and repeat. */ tmpl = underlying; } @@ -9679,7 +9702,9 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, Note that the check is deferred until after the hash lookup. This prevents redundant checks on previously instantiated specializations. */ - if (flag_concepts && !constraints_satisfied_p (gen_tmpl, arglist)) + if (flag_concepts + && !DECL_ALIAS_TEMPLATE_P (gen_tmpl) + && !constraints_satisfied_p (gen_tmpl, arglist)) { if (complain & tf_error) { @@ -20499,8 +20524,6 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain) { if (tmpl == error_mark_node || args == error_mark_node) return error_mark_node; - if (!push_tinst_level (tmpl, args)) - return error_mark_node; args = coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl), @@ -20508,6 +20531,22 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain) /*require_all_args=*/true, /*use_default_args=*/true); + /* FIXME check for satisfaction in check_instantiated_args. */ + if (flag_concepts + && !any_dependent_template_arguments_p (args) + && !constraints_satisfied_p (tmpl, args)) + { + if (complain & tf_error) + { + auto_diagnostic_group d; + error ("template constraint failure for %qD", tmpl); + diagnose_constraints (input_location, tmpl, args); + } + return error_mark_node; + } + + if (!push_tinst_level (tmpl, args)) + return error_mark_node; tree r = instantiate_template (tmpl, args, complain); pop_tinst_level (); |