aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-08-17 16:36:33 -0400
committerJason Merrill <jason@redhat.com>2020-08-19 16:08:17 -0400
commitf1612b8ae8a60f62cf5456b3357a341550534a7e (patch)
tree1bd0b125354fadd755b4f4ac1af3d9e35292288a /gcc/cp
parente6e01618e83bcd9eb3a2b27df30ed87106a748b4 (diff)
downloadgcc-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.cc12
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/pt.c35
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]