pt.c (push_access_scope_real): Remove.
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Sun, 13 Jul 2003 15:20:58 +0000 (15:20 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Sun, 13 Jul 2003 15:20:58 +0000 (15:20 +0000)
* pt.c (push_access_scope_real): Remove.
(push_access_scope): Move code from push_access_scope_real.
(pop_access_scope): Don't check for TEMPLATE_DECL.
(instantiate_template): Defer access checking during template
substitution.
(regenerate_decl_from_template): Tidy.

From-SVN: r69291

gcc/cp/ChangeLog
gcc/cp/pt.c

index 281f21684e77d977a2c0817484ef6cbb0220d03d..b275e8090d0330157a597be0a7ab9c45b4533353 100644 (file)
@@ -1,3 +1,12 @@
+2003-07-13  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       * pt.c (push_access_scope_real): Remove.
+       (push_access_scope): Move code from push_access_scope_real.
+       (pop_access_scope): Don't check for TEMPLATE_DECL.
+       (instantiate_template): Defer access checking during template
+       substitution.
+       (regenerate_decl_from_template): Tidy.
+
 2003-07-11  Nathanael Nerode  <neroden@gcc.gnu.org>
 
        PR c++/11437
index b9c64acea4f87fda0ce7a5409c7903dfda88fa95..d7c56a2d557ae88c3f926a22589928b813a911ed 100644 (file)
@@ -88,7 +88,6 @@ static htab_t local_specializations;
 #define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
                             type with the desired type.  */
 
-static void push_access_scope_real (tree, tree, tree);
 static void push_access_scope (tree);
 static void pop_access_scope (tree);
 static int resolve_overloaded_unification (tree, tree, tree, tree,
@@ -173,49 +172,22 @@ static tree tsubst_copy   (tree, tree, tsubst_flags_t, tree);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
-   template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
-   static member variable (need by instantiate_decl).  ARGS is the 
-   template argument for TEMPLATE_DECL.  If CONTEXT is not NULL_TREE, 
-   this is used instead of the context of T.  */
+   template, or VAR_DECL for static member variable (need by
+   instantiate_decl).  */
 
 static void
-push_access_scope_real (tree t, tree args, tree context)
+push_access_scope (tree t)
 {
-  if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
-    {
-      /* When we are processing specialization `foo<Outer>' for code like
-
-          template <class U> typename U::Inner foo ();
-          class Outer {
-            struct Inner {};
-            friend Outer::Inner foo<Outer> ();
-          };
-
-        `T' is a TEMPLATE_DECL, but `Outer' is only a friend of one of
-        its specialization.  We can get the FUNCTION_DECL with the right
-        information because this specialization has already been
-        registered by the friend declaration above.  */
-
-      if (DECL_FUNCTION_TEMPLATE_P (t) && args)
-       {
-         tree full_args = tsubst_template_arg_vector
-           (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t)), args, tf_none);
-         tree spec = NULL_TREE;
-         if (full_args != error_mark_node)
-           spec = retrieve_specialization (t, full_args);
-         if (spec)
-           t = spec;
-       }
-    }
+  my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
+                     || TREE_CODE (t) == VAR_DECL,
+                     0);
 
-  if (!context)
-    context = DECL_CONTEXT (t);
-  if (context && TYPE_P (context))
-    push_nested_class (context);
+  if (DECL_CLASS_SCOPE_P (t))
+    push_nested_class (DECL_CONTEXT (t));
   else
     push_to_top_level ();
     
-  if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+  if (TREE_CODE (t) == FUNCTION_DECL)
     {
       saved_access_scope = tree_cons
        (NULL_TREE, current_function_decl, saved_access_scope);
@@ -223,21 +195,13 @@ push_access_scope_real (tree t, tree args, tree context)
     }
 }
 
-/* Like push_access_scope_real, but always uses DECL_CONTEXT.  */
-
-static void
-push_access_scope (tree t)
-{
-  push_access_scope_real (t, NULL_TREE, NULL_TREE);
-}
-
 /* Restore the scope set up by push_access_scope.  T is the node we
    are processing.  */
 
 static void
 pop_access_scope (tree t)
 {
-  if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+  if (TREE_CODE (t) == FUNCTION_DECL)
     {
       current_function_decl = TREE_VALUE (saved_access_scope);
       saved_access_scope = TREE_CHAIN (saved_access_scope);
@@ -8509,18 +8473,23 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
                               complain))
     return error_mark_node;
   
-  /* Make sure that we can see identifiers, and compute access
-     correctly.  The desired FUNCTION_DECL for FNDECL may or may not be
-     created earlier.  Let push_access_scope_real figure that out.  */
-  push_access_scope_real
-    (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr, 
-                                complain, gen_tmpl));
+  /* We are building a FUNCTION_DECL, during which the access of its
+     parameters and return types have to be checked.  However this
+     FUNCTION_DECL which is the desired context for access checking
+     is not built yet.  We solve this chicken-and-egg problem by
+     deferring all checks until we have the FUNCTION_DECL.  */
+  push_deferring_access_checks (dk_deferred);
 
   /* substitute template parameters */
   fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
                   targ_ptr, complain, gen_tmpl);
 
-  pop_access_scope (gen_tmpl);
+  /* Now we know the specialization, compute access previously
+     deferred.  */
+  push_access_scope (fndecl);
+  perform_deferred_access_checks ();
+  pop_access_scope (fndecl);
+  pop_deferring_access_checks ();
 
   /* The DECL_TI_TEMPLATE should always be the immediate parent
      template, not the most general template.  */
@@ -10618,7 +10587,6 @@ regenerate_decl_from_template (tree decl, tree tmpl)
      instantiation of a specialization, which it isn't: it's a full
      instantiation.  */
   gen_tmpl = most_general_template (tmpl);
-  push_access_scope_real (gen_tmpl, args, DECL_CONTEXT (decl));
   unregistered = unregister_specialization (decl, gen_tmpl);
 
   /* If the DECL was not unregistered then something peculiar is
@@ -10626,6 +10594,10 @@ regenerate_decl_from_template (tree decl, tree tmpl)
      register_specialization for it.  */
   my_friendly_assert (unregistered, 0);
 
+  /* Make sure that we can see identifiers, and compute access
+     correctly.  */
+  push_access_scope (decl);
+
   /* Do the substitution to get the new declaration.  */
   new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);