This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH, committed] Clean up push/pop_access_scope
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 13 Jul 2003 22:33:46 +0700 (ICT)
- Subject: [C++ PATCH, committed] Clean up push/pop_access_scope
- Reply-to: <lerdsuwa at users dot sourceforge dot net>
Hi
This patch is final piece of my access checking deferring/disabling
work. The functions push/pop_access_scope are cleaned up and the ugly
bits in 'push_access_scope_real' are removed. This was previously
used to get around a chicken-and-egg problem during function
template instantiation (see the comment in 'instantiate_template'
below for details). 'regenerate_decl_from_template' is also
cleaned up because there is no more bad interaction between that
ugly bits and 'unregister_specialization'.
Tested on i686-pc-linux-gnu. Committed to trunk as obvious.
--Kriang
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.
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Sun Jul 13 00:07:19 2003
--- gcc-main-new/gcc/cp/pt.c Sun Jul 13 20:55:53 2003
*************** static htab_t local_specializations;
*** 88,94 ****
#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,
--- 88,93 ----
*************** static tree tsubst_copy (tree, tree, tsu
*** 173,221 ****
/* 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. */
static void
! push_access_scope_real (tree t, tree args, tree context)
{
! 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;
! }
! }
! if (!context)
! context = DECL_CONTEXT (t);
! if (context && TYPE_P (context))
! push_nested_class (context);
else
push_to_top_level ();
! if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
{
saved_access_scope = tree_cons
(NULL_TREE, current_function_decl, saved_access_scope);
--- 172,193 ----
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
! template, or VAR_DECL for static member variable (need by
! instantiate_decl). */
static void
! push_access_scope (tree t)
{
! my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
! || TREE_CODE (t) == VAR_DECL,
! 0);
! if (DECL_CLASS_SCOPE_P (t))
! push_nested_class (DECL_CONTEXT (t));
else
push_to_top_level ();
! if (TREE_CODE (t) == FUNCTION_DECL)
{
saved_access_scope = tree_cons
(NULL_TREE, current_function_decl, saved_access_scope);
*************** push_access_scope_real (tree t, tree arg
*** 223,243 ****
}
}
- /* 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))
{
current_function_decl = TREE_VALUE (saved_access_scope);
saved_access_scope = TREE_CHAIN (saved_access_scope);
--- 195,207 ----
}
}
/* 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)
{
current_function_decl = TREE_VALUE (saved_access_scope);
saved_access_scope = TREE_CHAIN (saved_access_scope);
*************** instantiate_template (tree tmpl, tree ta
*** 8498,8515 ****
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));
/* substitute template parameters */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, complain, gen_tmpl);
! pop_access_scope (gen_tmpl);
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
--- 8462,8484 ----
complain))
return error_mark_node;
! /* 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);
! /* 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. */
*************** regenerate_decl_from_template (tree decl
*** 10610,10616 ****
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
--- 10579,10584 ----
*************** regenerate_decl_from_template (tree decl
*** 10618,10623 ****
--- 10586,10595 ----
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);