Patchwork PR c++/45625 - Template parm name doesn't hide outer class scope's member name

login
register
mail settings
Submitter Dodji Seketeli
Date Aug. 17, 2011, 6:51 p.m.
Message ID <m3k4abdg84.fsf@redhat.com>
Download mbox | patch
Permalink /patch/110343/
State New
Headers show

Comments

Dodji Seketeli - Aug. 17, 2011, 6:51 p.m.
Hello,

Consider this code snippet:

    struct Outer
    {
      static const int value = 1 ;

      template< int value >
      struct Inner
      {
	static const int* get_value() { return &value ; } // #1 -> Error!
      } ;
    };

    template class Outer::Inner<2>;

The line #1 should yield an error because the name "value" should
resolve to the template parameter, not the static member of the outer
class.

The problem seems to be that parameter_of_template_p (notably used by
binding_to_template_parms_of_scope_p) fails to detect that the
template parm it gets in argument is a member of the template.

For each PARM_DECL representing a non-type template parameter,
process_template_parm and push_inline_template_parms_recursive
actually create a CONST_DECL that is added to the symbol table for
that PARM_DECL.

The patch below updates parameter_of_template_p to handle non-type
template parameters.

Tested on x86_64-unknown-linux-gnu against trunk.

gcc/cp/

	* pt.c (parameter_of_template_p): Handle comparison with DECLs of
	template parameters as created by process_template_parm.

gcc/testsuite/

	* g++.dg/lookup/hidden-var1.C: New test case.
---
 gcc/cp/pt.c                               |    9 +++++++--
 gcc/testsuite/g++.dg/lookup/hidden-var1.C |   19 +++++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lookup/hidden-var1.C
Jason Merrill - Aug. 18, 2011, 2:35 a.m.
OK.

Jason

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9ab110a..ed4fe72 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7890,8 +7890,13 @@  parameter_of_template_p (tree parm, tree templ)
   parms = INNERMOST_TEMPLATE_PARMS (parms);
 
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
-    if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i)))
-      return true;
+    {
+      tree p = TREE_VALUE (TREE_VEC_ELT (parms, i));
+      if (parm == p
+	  || (DECL_INITIAL (parm)
+	      && DECL_INITIAL (parm) == DECL_INITIAL (p)))
+	return true;
+    }
 
   return false;
 }
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-var1.C b/gcc/testsuite/g++.dg/lookup/hidden-var1.C
new file mode 100644
index 0000000..6be32b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/hidden-var1.C
@@ -0,0 +1,19 @@ 
+// Origin PR c++/45625
+// { dg-do compile }
+
+struct Outer
+{
+  static const int value = 1 ;
+
+  template< int value >
+  struct Inner
+  {
+    static const int*
+    get_value()
+    { 
+      return &value ;// { dg-error "lvalue required" }
+    }
+  };
+};
+
+template class Outer::Inner<2>;