PR c++/48884
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 May 2011 20:26:47 +0000 (20:26 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 May 2011 20:26:47 +0000 (20:26 +0000)
* class.c (pushclass): Accept NULL argument.
(popclass): Deal with popping null class.
* pt.c (push_access_scope, pop_access_scope): Use them rather than
push_to_top_level/pop_from_top_level.
(push_deduction_access_scope, pop_defarg_context): New.
(fn_type_unification): Use them.
* name-lookup.c (lookup_name_real_1): Check current_class_type.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/access21.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/access22.C [new file with mode: 0644]

index 351b072..c011c83 100644 (file)
@@ -1,3 +1,14 @@
+2011-05-24  Jason Merrill  <jason@redhat.com>
+
+       PR c++/48884
+       * class.c (pushclass): Accept NULL argument.
+       (popclass): Deal with popping null class.
+       * pt.c (push_access_scope, pop_access_scope): Use them rather than
+       push_to_top_level/pop_from_top_level.
+       (push_deduction_access_scope, pop_defarg_context): New.
+       (fn_type_unification): Use them.
+       * name-lookup.c (lookup_name_real_1): Check current_class_type.
+
 2011-05-24  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * decl.c (grokdeclarator): Use current_class_name.
index 4e52b18..69627cb 100644 (file)
@@ -6082,6 +6082,9 @@ restore_class_cache (void)
    So that we may avoid calls to lookup_name, we cache the _TYPE
    nodes of local TYPE_DECLs in the TREE_TYPE field of the name.
 
+   For use by push_access_scope, we allow TYPE to be null to temporarily
+   push out of class scope.  This does not actually change binding levels.
+
    For multiple inheritance, we perform a two-pass depth-first search
    of the type lattice.  */
 
@@ -6090,8 +6093,6 @@ pushclass (tree type)
 {
   class_stack_node_t csn;
 
-  type = TYPE_MAIN_VARIANT (type);
-
   /* Make sure there is enough room for the new entry on the stack.  */
   if (current_class_depth + 1 >= current_class_stack_size)
     {
@@ -6110,6 +6111,15 @@ pushclass (tree type)
   csn->hidden = 0;
   current_class_depth++;
 
+  if (type == NULL_TREE)
+    {
+      current_class_name = current_class_type = NULL_TREE;
+      csn->hidden = true;
+      return;
+    }
+
+  type = TYPE_MAIN_VARIANT (type);
+
   /* Now set up the new type.  */
   current_class_name = TYPE_NAME (type);
   if (TREE_CODE (current_class_name) == TYPE_DECL)
@@ -6154,7 +6164,11 @@ invalidate_class_lookup_cache (void)
 void
 popclass (void)
 {
-  poplevel_class ();
+  if (current_class_type)
+    poplevel_class ();
+  else
+    gcc_assert (current_class_depth
+               && current_class_stack[current_class_depth - 1].hidden);
 
   current_class_depth--;
   current_class_name = current_class_stack[current_class_depth].name;
index 3d1c64d..bb6d4b9 100644 (file)
@@ -4469,7 +4469,7 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
   /* Conversion operators are handled specially because ordinary
      unqualified name lookup will not find template conversion
      operators.  */
-  if (IDENTIFIER_TYPENAME_P (name))
+  if (IDENTIFIER_TYPENAME_P (name) && current_class_type)
     {
       struct cp_binding_level *level;
 
index dbff91e..98844c3 100644 (file)
@@ -212,7 +212,7 @@ push_access_scope (tree t)
   else if (DECL_CLASS_SCOPE_P (t))
     push_nested_class (DECL_CONTEXT (t));
   else
-    push_to_top_level ();
+    pushclass (NULL_TREE);
 
   if (TREE_CODE (t) == FUNCTION_DECL)
     {
@@ -237,7 +237,7 @@ pop_access_scope (tree t)
   if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t))
     pop_nested_class ();
   else
-    pop_from_top_level ();
+    popclass ();
 }
 
 /* Do any processing required when DECL (a member template
@@ -13820,6 +13820,30 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
   return ret;
 }
 
+/* We're going to do deduction substitution on the type of TMPL, a function
+   template.  In C++11 mode, push into that access scope.  In C++03 mode,
+   disable access checking.  */
+
+static void
+push_deduction_access_scope (tree tmpl)
+{
+  if (cxx_dialect >= cxx0x)
+    push_access_scope (DECL_TEMPLATE_RESULT (tmpl));
+  else
+    push_deferring_access_checks (dk_no_check);
+}
+
+/* And pop back out.  */
+
+static void
+pop_deduction_access_scope (tree tmpl)
+{
+  if (cxx_dialect >= cxx0x)
+    pop_access_scope (DECL_TEMPLATE_RESULT (tmpl));
+  else
+    pop_deferring_access_checks ();
+}
+
 /* The FN is a TEMPLATE_DECL for a function.  ARGS is an array with
    NARGS elements of the arguments that are being used when calling
    it.  TARGS is a vector into which the deduced template arguments
@@ -13958,7 +13982,9 @@ fn_type_unification (tree fn,
         incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
 
       processing_template_decl += incomplete;
+      push_deduction_access_scope (fn);
       fntype = deduction_tsubst_fntype (fn, converted_args);
+      pop_deduction_access_scope (fn);
       processing_template_decl -= incomplete;
 
       if (fntype == error_mark_node)
@@ -14029,7 +14055,10 @@ fn_type_unification (tree fn,
        substitution results in an invalid type, as described above,
        type deduction fails.  */
     {
-      tree substed = deduction_tsubst_fntype (fn, targs);
+      tree substed;
+      push_deduction_access_scope (fn);
+      substed = deduction_tsubst_fntype (fn, targs);
+      pop_deduction_access_scope (fn);
       if (substed == error_mark_node)
        return 1;
 
index beee8a6..95ee33e 100644 (file)
@@ -1,3 +1,8 @@
+2011-05-24  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/template/access21.C: New.
+       * g++.dg/template/access22.C: New.
+
 2011-05-24  Michael Matz  <matz@gcc.gnu.org>
 
        PR rtl-optimization/48633
diff --git a/gcc/testsuite/g++.dg/template/access21.C b/gcc/testsuite/g++.dg/template/access21.C
new file mode 100644 (file)
index 0000000..8414c43
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/48884
+
+class X
+{
+  static const int I = 42;
+  friend struct Y;
+};
+
+template <int I> struct A { };
+
+struct Y
+{
+  template <typename T>
+  static A<T::I> f(T t)
+  {
+    return A<T::I>();
+  }
+};
+
+int main()
+{
+  Y::f(X());
+}
diff --git a/gcc/testsuite/g++.dg/template/access22.C b/gcc/testsuite/g++.dg/template/access22.C
new file mode 100644 (file)
index 0000000..9ee28a2
--- /dev/null
@@ -0,0 +1,15 @@
+template <int I> struct B { };
+
+template <class T>
+B<T::I> f();
+
+class A
+{
+  static const int I = 42;
+  template <class T> friend B<T::I> f();
+};
+
+int main()
+{
+  f<A>();
+}