diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ae93e66..b3f92d6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4560,6 +4560,8 @@ extern bool template_parameter_pack_p (const_tree); extern tree make_pack_expansion (tree); extern bool check_for_bare_parameter_packs (tree); extern tree get_template_info (tree); +extern tree get_spec_template_info (tree); +extern tree get_spec_template (tree); extern int template_class_depth (tree); extern int is_specialization_of (tree, tree); extern bool is_specialization_of_friend (tree, tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index adea7eb..90a8a67 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -287,6 +287,60 @@ get_template_info (tree t) return tinfo; } +/* Get the most specific template info of T. + "Most specific" means the template info of T, even + if T is a template specialization. It is not the template info + of the most general template of T. + For instance, if we have: + template struct S {}; //#1 + template struct S {}; //#2 + + Calling this function on the RECORD_TYPE representing #2 yields + the template info of S template, not of S. + + Note that if T is a class template, get_template_info + returns the template info of the most general template of T. */ +tree +get_spec_template_info (tree t) +{ + if (!t || t == error_mark_node) + return t; + + if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) + return DECL_TEMPLATE_INFO (t); + + /* For RECORD_TYPE nodes we don't use CLASSTYPE_TEMPLATE_INFO + because it actually points to the template info of the most + general template of T. + Rather, the DECL_TEMPLATE_INFO property of the + implicit typedef associated to the RECORD_TYPE + points to the template info of the specific TEMPLATE_DECL of T. */ + if (TREE_CODE (t) == RECORD_TYPE) + { + tree node = TYPE_FIELDS (t); + while (!DECL_SELF_REFERENCE_P (node)) + node = TREE_CHAIN (node); + if (TREE_CODE (node) == TYPE_DECL + && DECL_LANG_SPECIFIC (node)) + return DECL_TEMPLATE_INFO (node); + } + else if (TAGGED_TYPE_P (t)) + return TYPE_TEMPLATE_INFO (t); + + return NULL_TREE; +} + +/* Returns the most specific template T. */ + +tree +get_spec_template (tree t) +{ + tree ti = get_spec_template_info (t); + if (ti) + return TI_TEMPLATE (ti); + return NULL_TREE; +} + /* Returns the template nesting level of the indicated class TYPE. For example, in: @@ -6964,7 +7018,7 @@ perform_typedefs_access_check (tree tmpl, tree targs) tree instantiate_class_template (tree type) { - tree templ, args, pattern, t, member; + tree templ, args, pattern, t, member, spec_templ; tree typedecl; tree pbinfo; tree base_list; @@ -7439,8 +7493,13 @@ instantiate_class_template (tree type) /* 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); + the access checks then. Note that we need to use the TEMPLATE_DECL + for which TYPE is an instantiation, even if that TEMPLATE_DECL is + a specialization of a more generic template. We do not want to + use the most generic TEMPLATE_DECL. */ + spec_templ = get_spec_template (type); + gcc_assert (spec_templ); + perform_typedefs_access_check (spec_templ, args); perform_deferred_access_checks (); pop_nested_class (); pop_from_top_level (); @@ -17163,13 +17222,9 @@ append_type_to_template_for_access_check (tree templ, { 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)); + gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL)); - templ_decl = TI_TEMPLATE (get_template_info (templ)); + templ_decl = get_spec_template (templ); gcc_assert (templ_decl); /* Make sure we don't append the type to the template twice. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index dd84891..7f234de 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1543,7 +1543,7 @@ check_accessibility_of_qualified_id (tree decl, tree cs = current_scope (); if (cs && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)) - templ_info = get_template_info (cs); + templ_info = get_spec_template_info (cs); if (templ_info && TI_TEMPLATE (templ_info)