Concept code also needs some updates to accommodate my GCC 7 fix for
10200. First, and not limited to concepts, we need to treat a member
template as dependent if its signature depends on template parameters of
its enclosing class (which, more importantly, are template parameters of
the scope where the member template is named). Second,
constraints_satisfied_p needs the same kind of change that I made to
instantiate_decl and fn_type_unification to handle non-dependent calls
within a template. The testcase tests both these changes.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 44d09c91bac2a200149e30c1d1bbc13042c6a723
Author: Jason Merrill <ja...@redhat.com>
Date: Mon Jun 20 11:22:49 2016 +0300
Fix type_dependent_expression_p of member templates.
* pt.c (template_parm_outer_level, uses_outer_template_parms): New.
(type_dependent_expression_p): Use uses_outer_template_parms.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 11b5d82..c5f65a7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5064,6 +5064,24 @@ template_parm_this_level_p (tree t, void* data)
return level == this_level;
}
+/* Worker for uses_outer_template_parms, called via for_each_template_parm.
+ DATA is really an int, indicating the innermost outer level of parameters.
+ If T is a template parameter of that level or further out, return
+ nonzero. */
+
+static int
+template_parm_outer_level (tree t, void *data)
+{
+ int this_level = *(int *)data;
+ int level;
+
+ if (TREE_CODE (t) == TEMPLATE_PARM_INDEX)
+ level = TEMPLATE_PARM_LEVEL (t);
+ else
+ level = TEMPLATE_TYPE_LEVEL (t);
+ return level <= this_level;
+}
+
/* Creates a TEMPLATE_DECL for the indicated DECL using the template
parameters given by current_template_args, or reuses a
previously existing one, if appropriate. Returns the DECL, or an
@@ -9032,6 +9050,33 @@ uses_template_parms_level (tree t, int level)
/*include_nondeduced_p=*/true);
}
+/* Returns true if the signature of DECL depends on any template parameter from
+ its enclosing class. */
+
+bool
+uses_outer_template_parms (tree decl)
+{
+ int depth = template_class_depth (CP_DECL_CONTEXT (decl));
+ if (depth == 0)
+ return false;
+ if (for_each_template_parm (TREE_TYPE (decl), template_parm_outer_level,
+ &depth, NULL, /*include_nondeduced_p=*/true))
+ return true;
+ if (PRIMARY_TEMPLATE_P (decl)
+ && for_each_template_parm (INNERMOST_TEMPLATE_PARMS
+ (DECL_TEMPLATE_PARMS (decl)),
+ template_parm_outer_level,
+ &depth, NULL, /*include_nondeduced_p=*/true))
+ return true;
+ tree ci = get_constraints (decl);
+ if (ci)
+ ci = CI_NORMALIZED_CONSTRAINTS (ci);
+ if (ci && for_each_template_parm (ci, template_parm_outer_level,
+ &depth, NULL, /*nondeduced*/true))
+ return true;
+ return false;
+}
+
/* Returns TRUE iff INST is an instantiation we don't need to do in an
ill-formed translation unit, i.e. a variable or function that isn't
usable in a constant expression. */
@@ -23008,7 +23053,7 @@ type_dependent_expression_p (tree expression)
if (TREE_CODE (expression) == TEMPLATE_DECL
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
- return false;
+ return uses_outer_template_parms (expression);
if (TREE_CODE (expression) == STMT_EXPR)
expression = stmt_expr_value_expr (expression);
commit 2f9c0996e3c50d7c84c34c3353ac70a7c10c0141
Author: Jason Merrill <ja...@redhat.com>
Date: Mon Jun 20 11:24:10 2016 +0300
Fix constraint satisfaction in uninstantiated template.
* constraint.cc (constraints_satisfied_p): Keep as many levels of
args as our template has levels of parms.
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 5e42fa9..af7a593 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2122,8 +2122,10 @@ constraints_satisfied_p (tree decl)
tree args = NULL_TREE;
if (tree ti = DECL_TEMPLATE_INFO (decl))
{
- ci = get_constraints (TI_TEMPLATE (ti));
- args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti));
+ tree tmpl = TI_TEMPLATE (ti);
+ ci = get_constraints (tmpl);
+ int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+ args = get_innermost_template_args (TI_ARGS (ti), depth);
}
else
{
diff --git a/gcc/testsuite/g++.dg/concepts/memtmpl1.C b/gcc/testsuite/g++.dg/concepts/memtmpl1.C
new file mode 100644
index 0000000..6f3d5a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/memtmpl1.C
@@ -0,0 +1,15 @@
+// { dg-options "-std=c++1z -fconcepts" }
+
+template <class T>
+struct A {
+ template <class U>
+ requires sizeof(T) == 1
+ static void f(U);
+ template <class U>
+ requires sizeof(T) == 2
+ static void f(U);
+ void g()
+ {
+ f(42);
+ }
+};