diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index ebf4255e5..6ea791812 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2088,8 +2088,7 @@ type_deducible_p (tree expr, tree type, tree
placeholder, tree args,
expr = force_paren_expr_uneval (expr);
tree deduced_type = do_auto_deduction (type, expr, placeholder,
- info.complain, adc_requirement,
- /*outer_targs=*/args);
+ info.complain, adc_requirement);
return deduced_type != error_mark_node;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4bb3e9c49..961537f9f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7521,8 +7521,7 @@ extern tree do_auto_deduction (tree, tree, tree,
auto_deduction_context
= adc_unspecified,
tree = NULL_TREE,
- int = LOOKUP_NORMAL,
- tree = NULL_TREE);
+ int = LOOKUP_NORMAL);
extern tree type_uses_auto (tree);
extern tree type_uses_auto_or_concept (tree);
extern void append_type_to_template_for_access_check (tree, tree, tree,
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 29616100c..773370b48 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8567,18 +8567,9 @@ cp_finish_decl (tree decl, tree init, bool
init_const_expr_p,
enum auto_deduction_context adc = adc_variable_type;
if (DECL_DECOMPOSITION_P (decl))
adc = adc_decomp_type;
- tree outer_targs = NULL_TREE;
- if (PLACEHOLDER_TYPE_CONSTRAINTS_INFO (auto_node)
- && DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_INFO (decl)
- && !DECL_FUNCTION_SCOPE_P (decl))
- /* The outer template arguments might be needed for satisfaction.
- (For function scope variables, do_auto_deduction will obtain the
- outer template arguments from current_function_decl.) */
- outer_targs = DECL_TI_ARGS (decl);
type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, auto_node,
tf_warning_or_error, adc,
- outer_targs, flags);
+ NULL_TREE, flags);
if (type == error_mark_node)
return;
if (TREE_CODE (type) == FUNCTION_TYPE)
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d1316483e..fdd641e5c 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8781,7 +8781,7 @@ convert_template_argument (tree parm,
else if (tree a = type_uses_auto (t))
{
t = do_auto_deduction (t, arg, a, complain, adc_unify, args,
- LOOKUP_IMPLICIT, /*tmpl=*/in_decl);
+ LOOKUP_IMPLICIT);
if (t == error_mark_node)
return error_mark_node;
}
@@ -16506,8 +16506,8 @@ tsubst (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
if (tree d = TEMPLATE_TYPE_DESCENDANTS (t))
if (TEMPLATE_PARM_LEVEL (d) == TEMPLATE_TYPE_LEVEL (t) - levels
- && (code == TEMPLATE_TYPE_PARM
- || TEMPLATE_TEMPLATE_PARM_SIMPLE_P (t)))
+ && ((code == TEMPLATE_TYPE_PARM && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO(t))
+ || (code == TEMPLATE_TEMPLATE_PARM && TEMPLATE_TEMPLATE_PARM_SIMPLE_P (t))))
/* Cache lowering a type parameter or a simple template
template parameter. */
r = TREE_TYPE (d);
@@ -16515,6 +16515,32 @@ tsubst (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
if (!r)
{
r = copy_type (t);
+
+ if (code == TEMPLATE_TYPE_PARM)
+ if (tree ci = PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t))
+ {
+ tree cparms = TREE_PURPOSE (ci);
+
+ tree auto_vec = make_tree_vec (1);
+ TREE_VEC_ELT (auto_vec, 0) = r;
+ tree extra = template_parms_to_args (cparms);
+ extra = add_outermost_template_args (extra, auto_vec);
+ extra = get_innermost_template_args(extra, level - levels);
+ tree full_args = add_to_template_args (args, extra);
+
+ tree cexpr
+ = tsubst_constraint (TREE_VALUE (ci), full_args, complain, in_decl);
+
+ if (cexpr == error_mark_node)
+ return error_mark_node;
+
+ PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r)
+ = build_tree_list(cparms, cexpr);
+
+ /* reduce_template_parm_level needs proper canonical type */
+ TYPE_CANONICAL (r) = canonical_type_parameter (r);
+ }
+
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels, args, complain);
@@ -16523,12 +16549,6 @@ tsubst (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
TYPE_POINTER_TO (r) = NULL_TREE;
TYPE_REFERENCE_TO (r) = NULL_TREE;
- if (code == TEMPLATE_TYPE_PARM)
- if (tree ci = PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t))
- /* Propagate constraints on placeholders since they are
- only instantiated during satisfaction. */
- PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r) = ci;
-
if (TYPE_STRUCTURAL_EQUALITY_P (t))
SET_TYPE_STRUCTURAL_EQUALITY (r);
else
@@ -24915,9 +24935,8 @@ unify (tree tparms, tree targs, tree parm,
tree arg, int strict,
if (tree a = type_uses_auto (tparm))
{
tparm = do_auto_deduction (tparm, arg, a,
- complain, adc_unify, targs,
- LOOKUP_NORMAL,
- TPARMS_PRIMARY_TEMPLATE (tparms));
+ complain, adc_unify, NULL_TREE,
+ LOOKUP_NORMAL);
if (tparm == error_mark_node)
return 1;
}
@@ -31116,8 +31135,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
tsubst_flags_t complain /* = tf_warning_or_error */,
auto_deduction_context context /* = adc_unspecified */,
tree outer_targs /* = NULL_TREE */,
- int flags /* = LOOKUP_NORMAL */,
- tree tmpl /* = NULL_TREE */)
+ int flags /* = LOOKUP_NORMAL */)
{
if (type == error_mark_node || init == error_mark_node)
return error_mark_node;
@@ -31287,28 +31305,7 @@ do_auto_deduction (tree type, tree init, tree
auto_node,
return type;
}
- if (context == adc_return_type
- || context == adc_variable_type
- || context == adc_decomp_type)
- if (tree fn = current_function_decl)
- if (DECL_TEMPLATE_INFO (fn) || LAMBDA_FUNCTION_P (fn))
- {
- outer_targs = DECL_TEMPLATE_INFO (fn)
- ? DECL_TI_ARGS (fn) : NULL_TREE;
- if (LAMBDA_FUNCTION_P (fn))
- {
- /* As in satisfy_declaration_constraints. */
- tree regen_args = lambda_regenerating_args (fn);
- if (outer_targs)
- outer_targs = add_to_template_args (regen_args, outer_targs);
- else
- outer_targs = regen_args;
- }
- }
-
tree full_targs = outer_targs;
- if (context == adc_unify && tmpl)
- full_targs = add_outermost_template_args (tmpl, full_targs);
full_targs = add_to_template_args (full_targs, targs);
/* HACK: Compensate for callers not always communicating all levels of
@@ -31318,9 +31315,13 @@ do_auto_deduction (tree type, tree init, tree
auto_node,
these missing levels, but this hack otherwise allows us to handle a
large subset of possible constraints (including all non-dependent
constraints). */
- if (int missing_levels = (TEMPLATE_TYPE_ORIG_LEVEL (auto_node)
+ if (int missing_levels = (TEMPLATE_TYPE_LEVEL (auto_node)
- TMPL_ARGS_DEPTH (full_targs)))
{
+ /* For example the case that
+ template <typename T> is_same<bool> auto x = true;
+ will end up here, because it will be deduced before instantiation */
+ gcc_assert (missing_levels > 0);
tree dummy_levels = make_tree_vec (missing_levels);
for (int i = 0; i < missing_levels; ++i)
TREE_VEC_ELT (dummy_levels, i) = make_tree_vec (0);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C
b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C
new file mode 100644
index 000000000..a8bd48e39
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C
@@ -0,0 +1,20 @@
+// PR c++/115030
+// { dg-do compile { target c++20 } }
+
+template<typename T, typename U>
+concept C = __is_same(T, U);
+
+template <typename T>
+struct s {
+};
+
+template <typename T>
+char v = 'a';
+
+template<typename T>
+C<T> auto v<s<T>> = 'c';
+
+int main() {
+ v<s<char>> = 'b';
+ return 0;
+}
