gcc/cp/ChangeLog:
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Jan 2009 22:47:49 +0000 (22:47 +0000)
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Jan 2009 22:47:49 +0000 (22:47 +0000)
2009-01-12  Dodji Seketeli  <dodji@redhat.com>

PR c++/36019
* pt.c (parameter_of_template_p): New function.
* cp-tree.h: Declare it.
* name-lookup.c (binding_to_template_parms_of_scope_p): New
function.
(outer_binding): Take template parameters in account when looking for
a name binding.

gcc/testsuite/ChangeLog:
2009-01-12  Dodji Seketeli  <dodji@redhat.com>

PR c++/36019
* g++.dg/lookup/hidden-class12.C: New test.
* g++.dg/lookup/hidden-class13.C: New test.
* g++.dg/lookup/hidden-class14.C: New test.
* g++.dg/lookup/hidden-class15.C: New test.
* g++.dg/lookup/hidden-class16.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143315 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/hidden-class12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/hidden-class13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/hidden-class14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/hidden-class15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/hidden-class16.C [new file with mode: 0644]

index 1a9ca4f..542b71d 100644 (file)
@@ -1,3 +1,13 @@
+2009-01-12  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/36019
+       * pt.c (parameter_of_template_p): New function.
+       * cp-tree.h: Declare it.
+       * name-lookup.c (binding_to_template_parms_of_scope_p): New
+       function.
+       (outer_binding): Take template parameters in account when looking for
+       a name binding.
+
 2009-01-12  Jason Merrill  <jason@redhat.com>
 
        PR c++/31488
index 9c89d96..718167f 100644 (file)
@@ -4603,6 +4603,7 @@ extern bool reregister_specialization             (tree, tree, tree);
 extern tree fold_non_dependent_expr            (tree);
 extern bool explicit_class_specialization_p     (tree);
 extern struct tinst_level *outermost_tinst_level(void);
+extern bool parameter_of_template_p            (tree, tree);
 
 /* in repo.c */
 extern void init_repo                          (void);
index 4c06afd..889d9ef 100644 (file)
@@ -3968,9 +3968,34 @@ qualified_lookup_using_namespace (tree name, tree scope,
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
 }
 
+/* Subroutine of outer_binding.
+   Returns TRUE if BINDING is a binding to a template parameter of SCOPE,
+   FALSE otherwise.  */
+
+static bool
+binding_to_template_parms_of_scope_p (cxx_binding *binding,
+                                     cxx_scope *scope)
+{
+  tree binding_value;
+
+  if (!binding || !scope)
+    return false;
+
+  binding_value = binding->value ?  binding->value : binding->type;
+
+  return (scope
+         && scope->this_entity
+         && get_template_info (scope->this_entity)
+         && parameter_of_template_p (binding_value,
+                                     TI_TEMPLATE (get_template_info \
+                                                   (scope->this_entity))));
+}
+
 /* Return the innermost non-namespace binding for NAME from a scope
-   containing BINDING, or, if BINDING is NULL, the current scope.  If
-   CLASS_P is false, then class bindings are ignored.  */
+   containing BINDING, or, if BINDING is NULL, the current scope.
+   Please note that for a given template, the template parameters are
+   considered to be in the scope containing the current scope.
+   If CLASS_P is false, then class bindings are ignored.  */
 
 cxx_binding *
 outer_binding (tree name,
@@ -4018,6 +4043,12 @@ outer_binding (tree name,
                return class_binding;
              }
          }
+       /* If SCOPE is a template and if NAME binds to one of its template parameters
+          return the binding, otherwise we might miss it.  */
+       if (outer_scope && outer_scope->kind == sk_template_parms
+           && binding_to_template_parms_of_scope_p (outer, scope))
+         return outer;
+
        scope = scope->level_chain;
       }
 
index 410641d..de70e53 100644 (file)
@@ -6427,6 +6427,30 @@ 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)
+    if (parm == TREE_VALUE (TREE_VEC_ELT (parms, i)))
+      return true;
+
+  return false;
+}
+
 /* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL.  ARGS is the
    vector of template arguments, as for tsubst.
 
index 53ad9ce..6d2fe90 100644 (file)
@@ -1,3 +1,12 @@
+2009-01-12  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/36019
+       * g++.dg/lookup/hidden-class12.C: New test.
+       * g++.dg/lookup/hidden-class13.C: New test.
+       * g++.dg/lookup/hidden-class14.C: New test.
+       * g++.dg/lookup/hidden-class15.C: New test.
+       * g++.dg/lookup/hidden-class16.C: New test.
+
 2009-01-12  Mark Mitchell  <mark@codesourcery.com>
 
        * gcc.dg/struct/wo_prof_single_str_global.c: Mask return value.
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class12.C b/gcc/testsuite/g++.dg/lookup/hidden-class12.C
new file mode 100644 (file)
index 0000000..4a3f2d7
--- /dev/null
@@ -0,0 +1,24 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/36019
+// { dg-do compile }
+
+struct F {
+  static const int x = 0;
+};
+
+struct A {
+  template <typename A>
+  static int f ()
+  {
+    return A::x;
+  }
+};
+
+
+int
+main ()
+{
+  int i = A::f<F> ();
+  return i;
+}
+
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class13.C b/gcc/testsuite/g++.dg/lookup/hidden-class13.C
new file mode 100644 (file)
index 0000000..2f685b2
--- /dev/null
@@ -0,0 +1,25 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/36019
+// { dg-do compile }
+
+struct F {
+  static const int x = 0;
+};
+
+struct B {
+  template <typename B>
+  struct C
+  {
+    static int f ()
+    {
+      return B::x;
+    }
+  };
+};
+
+int
+main ()
+{
+  int j = B::C<F>::f ();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class14.C b/gcc/testsuite/g++.dg/lookup/hidden-class14.C
new file mode 100644 (file)
index 0000000..99bd673
--- /dev/null
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/36019
+// { dg-do compile }
+
+struct F {
+  static const int x = 0;
+  typedef int A;
+};
+
+struct A {
+  template <typename A>
+  struct G : public F 
+  {
+    static const A i = 0;
+  };
+};
+
+int
+main ()
+{
+  return A::G<F>::i ;
+}
+
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class15.C b/gcc/testsuite/g++.dg/lookup/hidden-class15.C
new file mode 100644 (file)
index 0000000..b0ed660
--- /dev/null
@@ -0,0 +1,30 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/36019
+// { dg-do compile }
+
+struct F {
+  static const int y = 0;
+};
+
+struct A {
+  static const int x = 0;
+};
+
+struct B : public A {
+  template <typename A>
+  struct C
+  {
+    static int f ()
+    {
+      return A::x; // { dg-error "'x' is not a member of 'F'" }
+    }
+  };
+};
+
+int
+main ()
+{
+  int j = B::C<F>::f ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class16.C b/gcc/testsuite/g++.dg/lookup/hidden-class16.C
new file mode 100644 (file)
index 0000000..25cc402
--- /dev/null
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/36019
+// { dg-do compile }
+
+struct F {
+  static const int y = 0;
+};
+
+struct A {
+  static const int x = 0;
+};
+
+struct B : public A {
+  template <typename A>
+  static int f ()
+  {
+    return A::x; // { dg-error "'x' is not a member of 'F'" }
+  }
+};
+
+int
+main ()
+{
+  int j = B::f<F> ();
+  return 0;
+}
+