This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for concept checking in non-dependent expressions


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 <jason@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 <jason@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);
+  }
+};

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]