public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
@ 2012-01-26 11:44 Dodji Seketeli
  2012-01-26 22:13 ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Dodji Seketeli @ 2012-01-26 11:44 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jason Merrill

Hello,

In the example of the patch, the U in 'typename U::X r' should bind to
the template parameter U rather than the class member U.

I think the problem comes from parameter_of_template_p that compares
parameters by using pointer equality, rather than by using type
equivalence like compparms does.

As a result, binding_to_template_parms_of_scope_p and then
outer_binding (via binding_to_template_parms_of_scope_p) misses the
template parameter U and returns the class member U instead.

Fixed thus, tested on x86_64-unknown-linux-gnu against trunk.

OK for trunk when stage 1 opens?

gcc/cp/

	PR c++/51641
	* cp-tree.h (template_type_parameter_p): Declare ...
	* pt.c (template_type_parameter_p): ... new function.
	(parameter_of_template_p):  Rely on type equivalence rather
	than pointer equality to compare template parms.

gcc/testsuite/

	PR c++/51641
	* g++.dg/lookup/hidden-class17.C: New test.
---
 gcc/cp/cp-tree.h                             |    1 +
 gcc/cp/pt.c                                  |   29 ++++++++++++++++++++++---
 gcc/testsuite/g++.dg/lookup/hidden-class17.C |   22 +++++++++++++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class17.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f27755e..972c600 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5361,6 +5361,7 @@ extern bool parameter_of_template_p		(tree, tree);
 extern void init_template_processing		(void);
 extern void print_template_statistics		(void);
 bool template_template_parameter_p		(const_tree);
+bool template_type_parameter_p                  (const_tree);
 extern bool primary_template_instantiation_p    (const_tree);
 extern tree get_primary_template_innermost_parameters	(const_tree);
 extern tree get_template_parms_at_level (tree, int);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e440be7..cb9554a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2890,6 +2890,18 @@ template_template_parameter_p (const_tree parm)
   return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
 }
 
+/* Return true iff PARM is a DECL representing a type template
+   parameter.  */
+
+bool
+template_type_parameter_p (const_tree parm)
+{
+  return (parm
+	  && (TREE_CODE (parm) == TYPE_DECL
+	      || TREE_CODE (parm) == TEMPLATE_DECL)
+	  && DECL_TEMPLATE_PARM_P (parm));
+}
+
 /* Return the template parameters of T if T is a
    primary template instantiation, NULL otherwise.  */
 
@@ -8160,10 +8172,19 @@ parameter_of_template_p (tree parm, tree templ)
       if (p == error_mark_node)
 	continue;
 
-      if (parm == p
-	  || (DECL_INITIAL (parm)
-	      && DECL_INITIAL (parm) == DECL_INITIAL (p)))
-	return true;
+      if (template_type_parameter_p (parm))
+	{
+	  if (same_type_p (TREE_TYPE (parm), TREE_TYPE (p)))
+	    return true;
+	}
+      else
+	{
+	  if (DECL_INITIAL (parm)
+	      && DECL_INITIAL (p)
+	      && same_type_p (TREE_TYPE (DECL_INITIAL (parm)),
+			      TREE_TYPE (DECL_INITIAL (p))))
+	    return true;
+	}
     }
 
   return false;
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class17.C b/gcc/testsuite/g++.dg/lookup/hidden-class17.C
new file mode 100644
index 0000000..3d5ccec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/hidden-class17.C
@@ -0,0 +1,22 @@
+// Origin PR c++/51641
+// { dg-do compile }
+
+struct A {
+    struct B { typedef int X; };
+};
+
+template<class B> struct C : A {
+    B::X q; // Ok: A::B.
+    struct U { typedef int X; };
+    template<class U>
+        struct D;
+};
+
+template<class B>
+template<class U>
+struct C<B>::D {
+    typename U::X r; // { dg-error "" }
+};
+
+C<int>::D<double> y;
+
-- 
1.7.6.5


-- 
		Dodji

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
  2012-01-26 11:44 [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter Dodji Seketeli
@ 2012-01-26 22:13 ` Jason Merrill
  2012-01-27 23:20   ` Dodji Seketeli
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2012-01-26 22:13 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

Comparing by same_type_p means that we treat any template parameter of 
the appropriate level and index as equivalent.  But that should be OK, 
since we only have one set of level N template parameters in scope.  So 
I think we should be able to just compare the level of the template 
parameter to the level of the parameters of the template.  Right?

Jason

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
  2012-01-26 22:13 ` Jason Merrill
@ 2012-01-27 23:20   ` Dodji Seketeli
  2012-01-29 21:01     ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Dodji Seketeli @ 2012-01-27 23:20 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Jason Merrill <jason@redhat.com> writes:

> Comparing by same_type_p means that we treat any template parameter of
> the appropriate level and index as equivalent.  But that should be OK,
> since we only have one set of level N template parameters in scope.
> So I think we should be able to just compare the level of the template
> parameter to the level of the parameters of the template.  Right?

OK.  I understand that just comparing levels like that is not a good
enough implementation for parameter_of_template_p in the general case.
So I removed that function and did the test inline in
binding_to_template_parms_of_scope_p instead.

Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.

gcc/cp/

	PR c++/51641
	* cp-tree.h (template_type_parameter_p): Declare new function.
	(parameter_of_template_p): Remove
	* pt.c (template_type_parameter_p): Define new function.
	(parameter_of_template_p): Remove.
	* name-lookup.c (binding_to_template_parms_of_scope_p): Don't rely
	on parameter_of_template_p anymore.  Compare the level of the
	template parameter to the depth of the template.

gcc/testsuite/

	PR c++/51641
	* g++.dg/lookup/hidden-class17.C: New test.
---
 gcc/cp/cp-tree.h                             |    2 +-
 gcc/cp/name-lookup.c                         |   36 ++++++++++++++++-----
 gcc/cp/pt.c                                  |   44 +++++++-------------------
 gcc/testsuite/g++.dg/lookup/hidden-class17.C |   22 +++++++++++++
 4 files changed, 62 insertions(+), 42 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-class17.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f27755e..71bca53 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5357,10 +5357,10 @@ extern bool explicit_class_specialization_p     (tree);
 extern int push_tinst_level                     (tree);
 extern void pop_tinst_level                     (void);
 extern struct tinst_level *outermost_tinst_level(void);
-extern bool parameter_of_template_p		(tree, tree);
 extern void init_template_processing		(void);
 extern void print_template_statistics		(void);
 bool template_template_parameter_p		(const_tree);
+bool template_type_parameter_p                  (const_tree);
 extern bool primary_template_instantiation_p    (const_tree);
 extern tree get_primary_template_innermost_parameters	(const_tree);
 extern tree get_template_parms_at_level (tree, int);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2351342..3330138 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4466,21 +4466,39 @@ static bool
 binding_to_template_parms_of_scope_p (cxx_binding *binding,
 				      cp_binding_level *scope)
 {
-  tree binding_value;
+  tree binding_value, tmpl;
+  int level;
 
   if (!binding || !scope)
     return false;
 
   binding_value = binding->value ?  binding->value : binding->type;
+  /* BINDING_VALUE must be a template parm.  */
+  if (binding_value == NULL_TREE
+      && (!DECL_P (binding_value)
+          || !DECL_TEMPLATE_PARM_P (binding_value)))
+    return false;
 
-  return (scope
-	  && scope->this_entity
-	  && get_template_info (scope->this_entity)
-	  && PRIMARY_TEMPLATE_P (TI_TEMPLATE
-				 (get_template_info (scope->this_entity)))
-	  && parameter_of_template_p (binding_value,
-				      TI_TEMPLATE (get_template_info \
-						    (scope->this_entity))));
+  /*  The level of BINDING_VALUE.  */
+  level =
+    template_type_parameter_p (binding_value)
+    ? TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX
+			 (TREE_TYPE (binding_value)))
+    : TEMPLATE_PARM_LEVEL (DECL_INITIAL (binding_value));
+
+  /* The template of the current scope, iff said scope is a primary
+     template.  */
+  tmpl =
+    (scope
+     && scope->this_entity
+     && get_template_info (scope->this_entity)
+     && PRIMARY_TEMPLATE_P (TI_TEMPLATE (get_template_info (scope->this_entity))))
+    ? TI_TEMPLATE (get_template_info (scope->this_entity))
+    : NULL_TREE;
+
+  /* If the level of the parm BINDING_VALUE equals the depth of TMPL,
+     then BINDING_VALUE is a parameter of TMPL.  */
+  return (tmpl && level == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
 }
 
 /* Return the innermost non-namespace binding for NAME from a scope
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e440be7..76d09aa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2890,6 +2890,18 @@ template_template_parameter_p (const_tree parm)
   return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
 }
 
+/* Return true iff PARM is a DECL representing a type template
+   parameter.  */
+
+bool
+template_type_parameter_p (const_tree parm)
+{
+  return (parm
+	  && (TREE_CODE (parm) == TYPE_DECL
+	      || TREE_CODE (parm) == TEMPLATE_DECL)
+	  && DECL_TEMPLATE_PARM_P (parm));
+}
+
 /* Return the template parameters of T if T is a
    primary template instantiation, NULL otherwise.  */
 
@@ -8137,38 +8149,6 @@ outermost_tinst_level (void)
   return level;
 }
 
-/* Returns TRUE if PARM is a parameter of the template TEMPL.  */
-
-bool
-parameter_of_template_p (tree parm, tree templ)
-{
-  tree parms;
-  int i;
-
-  if (!parm || !templ)
-    return false;
-
-  gcc_assert (DECL_TEMPLATE_PARM_P (parm));
-  gcc_assert (TREE_CODE (templ) == TEMPLATE_DECL);
-
-  parms = DECL_TEMPLATE_PARMS (templ);
-  parms = INNERMOST_TEMPLATE_PARMS (parms);
-
-  for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
-    {
-      tree p = TREE_VALUE (TREE_VEC_ELT (parms, i));
-      if (p == error_mark_node)
-	continue;
-
-      if (parm == p
-	  || (DECL_INITIAL (parm)
-	      && DECL_INITIAL (parm) == DECL_INITIAL (p)))
-	return true;
-    }
-
-  return false;
-}
-
 /* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL.  ARGS is the
    vector of template arguments, as for tsubst.
 
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class17.C b/gcc/testsuite/g++.dg/lookup/hidden-class17.C
new file mode 100644
index 0000000..3d5ccec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/hidden-class17.C
@@ -0,0 +1,22 @@
+// Origin PR c++/51641
+// { dg-do compile }
+
+struct A {
+    struct B { typedef int X; };
+};
+
+template<class B> struct C : A {
+    B::X q; // Ok: A::B.
+    struct U { typedef int X; };
+    template<class U>
+        struct D;
+};
+
+template<class B>
+template<class U>
+struct C<B>::D {
+    typename U::X r; // { dg-error "" }
+};
+
+C<int>::D<double> y;
+
-- 
1.7.6.5


-- 
		Dodji

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter
  2012-01-27 23:20   ` Dodji Seketeli
@ 2012-01-29 21:01     ` Jason Merrill
  0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2012-01-29 21:01 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 01/27/2012 06:19 PM, Dodji Seketeli wrote:
> +  /* BINDING_VALUE must be a template parm.  */
> +  if (binding_value == NULL_TREE
> +      && (!DECL_P (binding_value)
> +          || !DECL_TEMPLATE_PARM_P (binding_value)))
> +    return false;

I think the && should be || here.

OK with that change.

Jason


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-01-29 21:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-26 11:44 [PATCH] PR c++/51641 - Lookup finds enclosing class member instead of template parameter Dodji Seketeli
2012-01-26 22:13 ` Jason Merrill
2012-01-27 23:20   ` Dodji Seketeli
2012-01-29 21:01     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).