diff options
author | Jason Merrill <jason@redhat.com> | 2020-08-17 16:36:33 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-08-19 16:08:17 -0400 |
commit | f1612b8ae8a60f62cf5456b3357a341550534a7e (patch) | |
tree | 1bd0b125354fadd755b4f4ac1af3d9e35292288a /gcc/cp | |
parent | e6e01618e83bcd9eb3a2b27df30ed87106a748b4 (diff) | |
download | gcc-f1612b8ae8a60f62cf5456b3357a341550534a7e.zip gcc-f1612b8ae8a60f62cf5456b3357a341550534a7e.tar.gz gcc-f1612b8ae8a60f62cf5456b3357a341550534a7e.tar.bz2 |
c++: Check satisfaction before non-dep convs. [CWG2369]
It's very hard to use concepts to protect a template from hard errors due to
unwanted instantiation if constraints aren't checked until after doing all
substitution and checking of non-dependent conversions.
It was pretty straightforward to insert the satisfaction check into the
logic, but I needed to make the 3-parameter version of
satisfy_declaration_constraints call push_tinst_level like the 2-parameter
version already does. For simplicity, I also made it add any needed outer
template arguments from the TEMPLATE_DECL to the args.
The testsuite changes are mostly because this change causes unsatisfaction
to cause deduction to fail rather than reject the candidate later in
overload resolution.
gcc/cp/ChangeLog:
DR 2369
* cp-tree.h (push_tinst_level, push_tinst_level_loc): Declare.
* constraint.cc (satisfy_declaration_constraints):
Use add_outermost_template_args and push_tinst_level.
* pt.c (add_outermost_template_args): Handle getting
a TEMPLATE_DECL as the first argument.
(push_tinst_level, push_tinst_level_loc): No longer static.
(fn_type_unification): Check satisfaction before non-dependent
conversions.
gcc/testsuite/ChangeLog:
DR 2369
* g++.dg/concepts/diagnostic10.C: Adjust expexcted errors.
* g++.dg/concepts/diagnostic13.C: Adjust expexcted errors.
* g++.dg/concepts/diagnostic2.C: Adjust expexcted errors.
* g++.dg/concepts/diagnostic3.C: Adjust expexcted errors.
* g++.dg/concepts/diagnostic4.C: Adjust expexcted errors.
* g++.dg/concepts/diagnostic5.C: Adjust expexcted errors.
* g++.dg/concepts/diagnostic9.C: Adjust expexcted errors.
* g++.dg/concepts/expression2.C: Adjust expexcted errors.
* g++.dg/concepts/fn5.C: Adjust expexcted errors.
* g++.dg/concepts/placeholder5.C: Adjust expexcted errors.
* g++.dg/concepts/pr67595.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts-pr78752-2.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts-pr84140.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts-recursive-sat3.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts-requires18.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts-requires19.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts3.C: Adjust expexcted errors.
* g++.dg/cpp2a/concepts-nondep1.C: New test.
* g++.dg/cpp2a/concepts-nondep1a.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/constraint.cc | 12 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 35 |
3 files changed, 39 insertions, 10 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 48d52ec..7a2f3b9 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2814,16 +2814,22 @@ satisfy_declaration_constraints (tree t, tree args, subst_info info) info.in_decl = t; gcc_assert (TREE_CODE (t) == TEMPLATE_DECL); + + args = add_outermost_template_args (t, args); + + tree result = boolean_true_node; if (tree norm = normalize_template_requirements (t, info.noisy ())) { + if (!push_tinst_level (t, args)) + return result; tree pattern = DECL_TEMPLATE_RESULT (t); push_access_scope (pattern); - tree result = satisfy_associated_constraints (norm, args, info); + result = satisfy_associated_constraints (norm, args, info); pop_access_scope (pattern); - return result; + pop_tinst_level (); } - return boolean_true_node; + return result; } static tree diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 44531cd..3f3717a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6981,7 +6981,9 @@ extern bool template_parm_object_p (const_tree); extern tree tparm_object_argument (tree); extern bool explicit_class_specialization_p (tree); extern bool push_tinst_level (tree); +extern bool push_tinst_level (tree, tree); extern bool push_tinst_level_loc (tree, location_t); +extern bool push_tinst_level_loc (tree, tree, location_t); extern void pop_tinst_level (void); extern struct tinst_level *outermost_tinst_level(void); extern void init_template_processing (void); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index edaefcf..5dbdd37 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -586,13 +586,23 @@ add_to_template_args (tree args, tree extra_args) (EXTRA_ARGS) levels are added. This function is used to combine the template arguments from a partial instantiation with the template arguments used to attain the full instantiation from the - partial instantiation. */ + partial instantiation. + + If ARGS is a TEMPLATE_DECL, use its parameters as args. */ tree add_outermost_template_args (tree args, tree extra_args) { tree new_args; + if (!args) + return extra_args; + if (TREE_CODE (args) == TEMPLATE_DECL) + { + tree ti = get_template_info (DECL_TEMPLATE_RESULT (args)); + args = TI_ARGS (ti); + } + /* If there are more levels of EXTRA_ARGS than there are ARGS, something very fishy is going on. */ gcc_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args)); @@ -10772,7 +10782,7 @@ static GTY(()) struct tinst_level *last_error_tinst_level; /* We're starting to instantiate D; record the template instantiation context at LOC for diagnostics and to restore it later. */ -static bool +bool push_tinst_level_loc (tree tldcl, tree targs, location_t loc) { struct tinst_level *new_level; @@ -10826,7 +10836,7 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc) /* We're starting substitution of TMPL<ARGS>; record the template substitution context for diagnostics and to restore it later. */ -static bool +bool push_tinst_level (tree tmpl, tree args) { return push_tinst_level_loc (tmpl, args, input_location); @@ -21297,13 +21307,24 @@ fn_type_unification (tree fn, goto fail; } + deduced: + + /* CWG2369: Check satisfaction before non-deducible conversions. */ + if (!constraints_satisfied_p (fn, targs)) + { + if (explain_p) + diagnose_constraints (DECL_SOURCE_LOCATION (fn), fn, targs); + goto fail; + } + /* DR 1391: All parameters have args, now check non-dependent parms for - convertibility. */ - if (check_non_deducible_conversions (parms, args, nargs, fn, strict, flags, - convs, explain_p)) + convertibility. We don't do this if all args were explicitly specified, + as the standard says that we substitute explicit args immediately. */ + if (incomplete + && check_non_deducible_conversions (parms, args, nargs, fn, strict, flags, + convs, explain_p)) goto fail; - deduced: /* All is well so far. Now, check: [temp.deduct] |