@@ -696,18 +696,18 @@ struct GTY (()) tree_lambda_expr
In bar, the triplet will be (myint, foo, #1).
*/
-struct GTY(()) qualified_typedef_usage_s {
- tree typedef_decl;
+struct GTY(()) qualified_type_usage_s {
+ tree type_decl;
tree context;
location_t locus;
};
-typedef struct qualified_typedef_usage_s qualified_typedef_usage_t;
-DEF_VEC_O (qualified_typedef_usage_t);
-DEF_VEC_ALLOC_O (qualified_typedef_usage_t,gc);
+typedef struct qualified_type_usage_s qualified_type_usage_t;
+DEF_VEC_O (qualified_type_usage_t);
+DEF_VEC_ALLOC_O (qualified_type_usage_t,gc);
struct GTY(()) tree_template_info {
struct tree_common common;
- VEC(qualified_typedef_usage_t,gc) *typedefs_needing_access_checking;
+ VEC(qualified_type_usage_t,gc) *types_needing_access_checking;
};
enum cp_tree_node_structure_enum {
@@ -2609,9 +2609,9 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#endif
/* The list of typedefs - used in the template - that need
access checking at template instantiation time. */
-#define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \
+#define TI_TYPES_NEEDING_ACCESS_CHECKING(NODE) \
((struct tree_template_info*)TEMPLATE_INFO_CHECK \
- (NODE))->typedefs_needing_access_checking
+ (NODE))->types_needing_access_checking
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -4093,6 +4093,9 @@ extern int function_depth;
sizeof can be nested. */
extern int cp_unevaluated_operand;
+extern int cp_parsing_class_head;
+extern bool cp_no_type_access_check_p;
+
extern tree cp_convert_range_for (tree, tree, tree);
/* in pt.c */
@@ -5142,6 +5145,8 @@ extern tree do_auto_deduction (tree, tree, tree);
extern tree type_uses_auto (tree);
extern void append_type_to_template_for_access_check (tree, tree, tree,
location_t);
+extern void defer_type_access_check_for_cur_template (tree, tree, location_t);
+extern void schedule_deferred_access_check_types_for_template (tree);
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
extern tree process_template_parm (tree, location_t, tree,
@@ -5181,7 +5186,7 @@ extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (tree);
extern tree build_template_info (tree, tree);
extern tree get_template_info (const_tree);
-extern VEC(qualified_typedef_usage_t,gc)* get_types_needing_access_check (tree);
+extern VEC(qualified_type_usage_t,gc)* get_types_needing_access_check (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
@@ -5436,8 +5441,8 @@ extern void finish_mem_initializers (tree);
extern tree check_template_template_default_arg (tree);
extern bool expand_or_defer_fn_1 (tree);
extern void expand_or_defer_fn (tree);
-extern void add_typedef_to_current_template_for_access_check (tree, tree,
- location_t);
+extern void add_type_decl_to_current_template_for_access_check (tree, tree,
+ location_t);
extern void check_accessibility_of_qualified_id (tree, tree, tree);
extern tree finish_qualified_id_expr (tree, tree, bool, bool,
bool, bool);
@@ -3251,10 +3251,10 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t, t);
- /* If we are currently parsing a template and if T is a typedef accessed
+ /* If we are currently parsing a template and if T is accessed
through CONTEXT then we need to remember and check access of T at
template instantiation time. */
- add_typedef_to_current_template_for_access_check (t, context, input_location);
+ add_type_decl_to_current_template_for_access_check (t, context, input_location);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
@@ -254,6 +254,9 @@ int cp_unevaluated_operand;
/* Dump up to NUM tokens in BUFFER to FILE. If NUM is 0, dump all the
tokens. */
+int cp_parsing_class_head = 0;
+bool cp_no_type_access_check_p = false;
+
void
cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
{
@@ -13243,7 +13246,14 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
{
tree decl;
tree ambiguous_decls;
-
+ bool saved_cp_no_type_access_check_p = cp_no_type_access_check_p;
+
+ /* So if we are parsing a friend template declaration, then
+ we should make sure that looking up the name of the
+ declaration doesn't schedule it for type access checking
+ at the time of instantiation of the current containing
+ template class, if any. */
+ cp_no_type_access_check_p = is_friend;
decl = cp_parser_lookup_name (parser, identifier,
tag_type,
/*is_template=*/false,
@@ -13251,6 +13261,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/*check_dependency=*/true,
&ambiguous_decls,
token->location);
+ cp_no_type_access_check_p = saved_cp_no_type_access_check_p;
/* If the lookup was ambiguous, an error will already have been
issued. */
@@ -17071,6 +17082,13 @@ cp_parser_class_specifier_1 (cp_parser* parser)
&nested_name_specifier_p,
&attributes,
&bases);
+ /* We have parsed the class head, so now we have the resulting TYPE.
+ If TYPE is a template, then we can stuff if with the type
+ references that need access checking at its instantiation time.
+ These access checks were deferred in cp_parser_class_head because
+ TYPE was not available yet. */
+ schedule_deferred_access_check_types_for_template (type);
+
/* If the class-head was a semantic disaster, skip the entire body
of the class. */
if (!type)
@@ -17389,13 +17407,17 @@ cp_parser_class_head (cp_parser* parser,
type. */
num_templates = 0;
parser->colon_corrects_to_scope_p = false;
+ cp_parsing_class_head++;
*bases = NULL_TREE;
/* Look for the class-key. */
class_key = cp_parser_class_key (parser);
if (class_key == none_type)
- return error_mark_node;
+ {
+ type = error_mark_node;
+ goto out;
+ }
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
@@ -17764,6 +17786,7 @@ cp_parser_class_head (cp_parser* parser,
if (type && (virt_specifiers & VIRT_SPEC_FINAL))
CLASSTYPE_FINAL (type) = 1;
out:
+ cp_parsing_class_head--;
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
return type;
}
@@ -94,6 +94,10 @@ static GTY ((param_is (spec_entry)))
static GTY ((param_is (spec_entry)))
htab_t type_specializations;
+/* A vector of types that needs to be scheduled for access check when
+ the current template being parsed becomes available. */
+static GTY (()) VEC(qualified_type_usage_t,gc) *cur_template_deferred_types_to_access_check;
+
/* Contains canonical template parameter types. The vector is indexed by
the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
TREE_LIST, whose TREE_VALUEs contain the canonical template
@@ -197,7 +201,7 @@ static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool);
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);
+static void perform_types_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree,
location_t);
static tree listify (tree);
@@ -8376,18 +8380,18 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
}
}
-/* Perform (or defer) access check for typedefs that were referenced
+/* Perform (or defer) access check for types 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)
+perform_types_access_check (tree tmpl, tree targs)
{
location_t saved_location;
int i;
- qualified_typedef_usage_t *iter;
+ qualified_type_usage_t *iter;
if (!tmpl
|| (!CLASS_TYPE_P (tmpl)
@@ -8395,11 +8399,11 @@ perform_typedefs_access_check (tree tmpl, tree targs)
return;
saved_location = input_location;
- FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
+ FOR_EACH_VEC_ELT (qualified_type_usage_t,
get_types_needing_access_check (tmpl),
i, iter)
{
- tree type_decl = iter->typedef_decl;
+ tree type_decl = iter->type_decl;
tree type_scope = iter->context;
if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
@@ -8905,7 +8909,7 @@ instantiate_class_template_1 (tree type)
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 access checks then. */
- perform_typedefs_access_check (pattern, args);
+ perform_types_access_check (pattern, args);
perform_deferred_access_checks ();
pop_nested_class ();
maximum_field_alignment = saved_maximum_field_alignment;
@@ -14159,7 +14163,7 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
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 (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
+ perform_types_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
perform_deferred_access_checks ();
pop_access_scope (fndecl);
pop_deferring_access_checks ();
@@ -19912,11 +19916,11 @@ type_uses_auto (tree type)
Those typedefs were added to T by the function
append_type_to_template_for_access_check. */
-VEC(qualified_typedef_usage_t,gc)*
+VEC(qualified_type_usage_t,gc)*
get_types_needing_access_check (tree t)
{
tree ti;
- VEC(qualified_typedef_usage_t,gc) *result = NULL;
+ VEC(qualified_type_usage_t,gc) *result = NULL;
if (!t || t == error_mark_node)
return NULL;
@@ -19930,7 +19934,7 @@ get_types_needing_access_check (tree t)
if (!TI_TEMPLATE (ti))
return NULL;
- result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
+ result = TI_TYPES_NEEDING_ACCESS_CHECKING (ti);
}
return result;
@@ -19953,7 +19957,7 @@ append_type_to_template_for_access_check_1 (tree t,
tree scope,
location_t location)
{
- qualified_typedef_usage_t typedef_usage;
+ qualified_type_usage_t type_usage;
tree ti;
if (!t || t == error_mark_node)
@@ -19970,13 +19974,13 @@ append_type_to_template_for_access_check_1 (tree t,
gcc_assert (TI_TEMPLATE (ti));
- typedef_usage.typedef_decl = type_decl;
- typedef_usage.context = scope;
- typedef_usage.locus = location;
+ type_usage.type_decl = type_decl;
+ type_usage.context = scope;
+ type_usage.locus = location;
- VEC_safe_push (qualified_typedef_usage_t, gc,
- TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti),
- &typedef_usage);
+ VEC_safe_push (qualified_type_usage_t, gc,
+ TI_TYPES_NEEDING_ACCESS_CHECKING (ti),
+ &type_usage);
}
/* Append TYPE_DECL to the template TEMPL.
@@ -20014,16 +20018,16 @@ append_type_to_template_for_access_check (tree templ,
tree scope,
location_t location)
{
- qualified_typedef_usage_t *iter;
+ qualified_type_usage_t *iter;
int i;
gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
/* Make sure we don't append the type to the template twice. */
- FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
+ FOR_EACH_VEC_ELT (qualified_type_usage_t,
get_types_needing_access_check (templ),
i, iter)
- if (iter->typedef_decl == type_decl && scope == iter->context)
+ if (iter->type_decl == type_decl && scope == iter->context)
return;
append_type_to_template_for_access_check_1 (templ, type_decl,
@@ -20060,4 +20064,50 @@ print_template_statistics (void)
htab_collisions (type_specializations));
}
+/* Save the type access check of T through SCOPE, so that it can be
+ scheduled later when
+ schedule_deferred_access_check_types_for_template is called. */
+
+void
+defer_type_access_check_for_cur_template (tree t, tree scope, location_t location)
+{
+ qualified_type_usage_t type_usage;
+
+ if (t == NULL_TREE || TREE_CODE (t) != TYPE_DECL)
+ return;
+
+ type_usage.type_decl = t;
+ type_usage.context = scope;
+ type_usage.locus = location;
+
+ VEC_safe_push (qualified_type_usage_t, gc,
+ cur_template_deferred_types_to_access_check,
+ &type_usage);
+}
+
+/* Add the type access checks stashed away by
+ defer_type_access_check_for_cur_template to the list of type
+ access checks to be done at the instantiation time of TEMPL. */
+
+void
+schedule_deferred_access_check_types_for_template (tree templ)
+{
+ int i;
+ qualified_type_usage_t *type_usage;
+
+ FOR_EACH_VEC_ELT (qualified_type_usage_t,
+ cur_template_deferred_types_to_access_check,
+ i, type_usage)
+ append_type_to_template_for_access_check (templ, type_usage->type_decl,
+ type_usage->context,
+ type_usage->locus);
+
+ if (cur_template_deferred_types_to_access_check != NULL)
+ {
+ VEC_free (qualified_type_usage_t, gc,
+ cur_template_deferred_types_to_access_check);
+ cur_template_deferred_types_to_access_check = NULL;
+ }
+}
+
#include "gt-cp-pt.h"
@@ -1606,35 +1606,52 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
}
}
-/* If we are currently parsing a template and we encountered a typedef
- TYPEDEF_DECL that is being accessed though CONTEXT, this function
- adds the typedef to a list tied to the current template.
- At tempate instantiatin time, that list is walked and access check
- performed for each typedef.
- LOCATION is the location of the usage point of TYPEDEF_DECL. */
+/* If we are currently parsing a template and we encountered a type
+ decl DECL that is being accessed though CONTEXT, this function adds
+ that DECL to a list tied to the current template. At template
+ instantiatin time, that list is walked and access check performed
+ for each DECL.
+
+ Note that if we are parsing a class head or a list
+ of template parameters, there is no "current template" defined yet.
+ In that case, the function stashes DECL away, until the "current
+ template" is built and
+ schedule_deferred_access_check_types_for_template is called.
+
+ LOCATION is the location of the usage point of DECL. */
void
-add_typedef_to_current_template_for_access_check (tree typedef_decl,
- tree context,
- location_t location)
+add_type_decl_to_current_template_for_access_check (tree decl,
+ tree context,
+ location_t location)
{
tree template_info = NULL;
tree cs = current_scope ();
- if (!is_typedef_decl (typedef_decl)
+ if (decl == NULL_TREE
+ || TREE_CODE (decl) != TYPE_DECL
|| !context
|| !CLASS_TYPE_P (context)
- || !cs)
+ || cp_no_type_access_check_p
+ || (at_namespace_scope_p ()
+ && !cp_parsing_class_head)
+ || currently_open_class (context)
+ || currently_open_class (TREE_TYPE (decl)))
return;
+ if ((cp_parsing_class_head && processing_template_decl)
+ || processing_template_parmlist)
+ {
+ defer_type_access_check_for_cur_template (decl, context, location);
+ return;
+ }
+
if (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)
template_info = get_template_info (cs);
if (template_info
- && TI_TEMPLATE (template_info)
- && !currently_open_class (context))
- append_type_to_template_for_access_check (cs, typedef_decl,
- context, location);
+ && TI_TEMPLATE (template_info))
+ append_type_to_template_for_access_check (cs, decl, context, location);
}
/* DECL was the declaration to which a qualified-id resolved. Issue
@@ -1651,15 +1668,15 @@ check_accessibility_of_qualified_id (tree decl,
tree scope;
tree qualifying_type = NULL_TREE;
- /* If we are parsing a template declaration and if decl is a typedef,
+ /* If we are parsing a template declaration and if decl is a TYPE_DECL,
add it to a list tied to the template.
At template instantiation time, that list will be walked and
access check performed. */
- add_typedef_to_current_template_for_access_check (decl,
- nested_name_specifier
- ? nested_name_specifier
- : DECL_CONTEXT (decl),
- input_location);
+ add_type_decl_to_current_template_for_access_check (decl,
+ nested_name_specifier
+ ? nested_name_specifier
+ : DECL_CONTEXT (decl),
+ input_location);
/* If we're not checking, return immediately. */
if (deferred_access_no_check)
@@ -9,6 +9,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
typedef int *__c_locale;
class locale
{
+ public:
class facet;
};
class locale::facet
@@ -14,6 +14,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
class num_get;
class locale {
+ public:
class facet;
};
class locale::facet {
new file mode 100644
@@ -0,0 +1,33 @@
+class C
+{
+ struct Private { }; // { dg-error "is private" }
+};
+
+template<typename T>
+struct exploit1
+{
+ typedef C::Private type; // { dg-error "in this context" }
+};
+
+template<typename T>
+struct exploit2 : C::Private // { dg-error "in this context" }
+{
+};
+
+template<typename T>
+struct exploit3
+{
+ C::Private a; // { dg-error "in this context" }
+};
+
+template<typename T>
+struct exploit4
+{
+ template<class U = C::Private> // { dg-error "in this context" }
+ struct E {};
+};
+
+exploit1<int>::type x1;
+exploit2<int> x2;
+exploit3<int> x3;
+exploit4<int>::E<> x4;