static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t);
+static void perform_typedefs_access_check (tree tmpl, tree targs);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
DECL_TEMPLATE_SPECIALIZATIONS list. */
if (!class_specializations_p
&& TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL
+ && !is_typedef_decl (DECL_TEMPLATE_RESULT (tmpl))
&& TAGGED_TYPE_P (TREE_TYPE (tmpl)))
sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
else
}
}
+/* Perform (or defer) access check for typedefs that were referenced
+ from within the template TMPL code.
+ This is a subroutine of instantiate_template and instantiate_class_template.
+ TMPL is the template to consider and TARGS is the list of arguments of
+ that template. */
+
+static void
+perform_typedefs_access_check (tree tmpl, tree targs)
+{
+ tree t;
+
+ if (!tmpl || TREE_CODE (tmpl) != TEMPLATE_DECL)
+ return;
+
+ for (t = MEMBER_TYPES_NEEDING_ACCESS_CHECK (tmpl); t; t = TREE_CHAIN (t))
+ {
+ tree type_decl = TREE_PURPOSE (t);
+ tree type_scope = TREE_VALUE (t);
+
+ if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
+ continue;
+
+ if (uses_template_parms (type_decl))
+ type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
+ if (uses_template_parms (type_scope))
+ type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+
+ perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl);
+ }
+}
+
tree
instantiate_class_template (tree type)
{
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
+ /* Some typedefs referenced from within the template code need to be access
+ checked at template instantiation time, i.e now. These types were
+ added to the template at parsing time. Let's get those and perform
+ the acces checks then. */
+ perform_typedefs_access_check (templ, args);
+ perform_deferred_access_checks ();
pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
/* Now we know the specialization, compute access previously
deferred. */
push_access_scope (fndecl);
+
+ /* Some typedefs referenced from within the template code need to be access
+ checked at template instantiation time, i.e now. These types were
+ added to the template at parsing time. Let's get those and perfom
+ the acces checks then. */
+ perform_typedefs_access_check (tmpl, targ_ptr);
perform_deferred_access_checks ();
pop_access_scope (fndecl);
pop_deferring_access_checks ();
/* Return the innermost template arguments that, when applied to a
template specialization whose innermost template parameters are
- TPARMS, and whose specialization arguments are PARMS, yield the
+ TPARMS, and whose specialization arguments are SPEC_ARGS, yield the
ARGS.
For example, suppose we have:
gcc_assert (TREE_CODE (type) == TYPENAME_TYPE);
scope = TYPE_CONTEXT (type);
- name = TYPE_IDENTIFIER (type);
+ /* Usually the non-qualified identifier of a TYPENAME_TYPE is
+ TYPE_IDENTIFIER (type). But when 'type' is a typedef variant of
+ a TYPENAME_TYPE node, then TYPE_NAME (type) is set to the TYPE_DECL representing
+ the typedef. In that case TYPE_IDENTIFIER (type) is not the non-qualified
+ identifier of the TYPENAME_TYPE anymore.
+ So by getting the TYPE_IDENTIFIER of the _main declaration_ of the
+ TYPENAME_TYPE instead, we avoid messing up with a possible
+ typedef variant case. */
+ name = TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type));
/* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
it first before we can figure out what NAME refers to. */
return NULL_TREE;
}
+/* Append TYPE_DECL to the template TEMPL.
+ TEMPL is either a class type or a FUNCTION_DECL associated
+ to a TEMPLATE_DECL.
+ At TEMPL instanciation time, TYPE_DECL will be checked to see
+ if it can be accessed through SCOPE. */
+
+void
+append_type_to_template_for_access_check (tree templ,
+ tree type_decl,
+ tree scope)
+{
+ tree node, templ_decl;
+
+ gcc_assert (templ
+ && get_template_info (templ)
+ && TI_TEMPLATE (get_template_info (templ))
+ && type_decl
+ && (TREE_CODE (type_decl) == TYPE_DECL));
+
+ templ_decl = TI_TEMPLATE (get_template_info (templ));
+ gcc_assert (templ_decl);
+
+ /* Make sure we don't append the type to the template twice.
+ If this appears to be too slow, the
+ MEMBER_TYPE_NEEDING_ACCESS_CHECK property
+ of templ should be a hash table instead. */
+ for (node = MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl);
+ node;
+ node = TREE_CHAIN (node))
+ {
+ tree decl = TREE_PURPOSE (node);
+ tree type_scope = TREE_VALUE (node);
+
+ if (decl == type_decl && type_scope == scope)
+ return;
+ }
+
+ MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl) =
+ tree_cons (type_decl, scope,
+ MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl));
+}
+
#include "gt-cp-pt.h"