diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c-common.c | 72 | ||||
-rw-r--r-- | gcc/c-common.h | 2 | ||||
-rw-r--r-- | gcc/c-decl.c | 63 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/cp/class.c | 24 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 6 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 16 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 30 | ||||
-rw-r--r-- | gcc/cp/pt.c | 99 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/access11.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/sfinae3.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef11.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef12.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef13.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef14.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef15.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef16.C | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename8.C | 6 | ||||
-rw-r--r-- | libstdc++-v3/ChangeLog | 15 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/bitmap_allocator.h | 2 |
24 files changed, 449 insertions, 123 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8305ab11a55..e50c34ceb08 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2009-04-02 Dodji Seketeli <dodji@redhat.com> + + PR c++/26693 + * c-decl.c: (clone_underlying_type): Move this ... + * c-common.c (set_underlying_type): ... here. + Also, make sure the function properly sets TYPE_STUB_DECL() on + the newly created typedef variant type. + * c-common.h (is_typedef_decl, set_underlying_type): Declare ... + * c-common.c (is_typedef_decl, set_underlying_type): ... new entry points. + 2009-04-02 Richard Guenther <rguenther@suse.de> PR tree-optimization/37221 diff --git a/gcc/c-common.c b/gcc/c-common.c index d102b6ef4c2..9886cdf3668 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -9172,4 +9172,76 @@ warn_for_sign_compare (location_t location, } } +/* Setup a TYPE_DECL node as a typedef representation. + + X is a TYPE_DECL for a typedef statement. Create a brand new + ..._TYPE node (which will be just a variant of the existing + ..._TYPE node with identical properties) and then install X + as the TYPE_NAME of this brand new (duplicate) ..._TYPE node. + + The whole point here is to end up with a situation where each + and every ..._TYPE node the compiler creates will be uniquely + associated with AT MOST one node representing a typedef name. + This way, even though the compiler substitutes corresponding + ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very + early on, later parts of the compiler can always do the reverse + translation and get back the corresponding typedef name. For + example, given: + + typedef struct S MY_TYPE; + MY_TYPE object; + + Later parts of the compiler might only know that `object' was of + type `struct S' if it were not for code just below. With this + code however, later parts of the compiler see something like: + + struct S' == struct S + typedef struct S' MY_TYPE; + struct S' object; + + And they can then deduce (from the node for type struct S') that + the original object declaration was: + + MY_TYPE object; + + Being able to do this is important for proper support of protoize, + and also for generating precise symbolic debugging information + which takes full account of the programmer's (typedef) vocabulary. + + Obviously, we don't want to generate a duplicate ..._TYPE node if + the TYPE_DECL node that we are now processing really represents a + standard built-in type. */ + +void +set_underlying_type (tree x) +{ + if (x == error_mark_node) + return; + if (DECL_IS_BUILTIN (x)) + { + if (TYPE_NAME (TREE_TYPE (x)) == 0) + TYPE_NAME (TREE_TYPE (x)) = x; + } + else if (TREE_TYPE (x) != error_mark_node + && DECL_ORIGINAL_TYPE (x) == NULL_TREE) + { + tree tt = TREE_TYPE (x); + DECL_ORIGINAL_TYPE (x) = tt; + tt = build_variant_type_copy (tt); + TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x)); + TYPE_NAME (tt) = x; + TREE_USED (tt) = TREE_USED (x); + TREE_TYPE (x) = tt; + } +} + +/* Returns true if X is a typedef decl. */ + +bool +is_typedef_decl (tree x) +{ + return (x && TREE_CODE (x) == TYPE_DECL + && DECL_ORIGINAL_TYPE (x) != NULL_TREE); +} + #include "gt-c-common.h" diff --git a/gcc/c-common.h b/gcc/c-common.h index 26423a8cc9e..f5c755b22bf 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -1009,6 +1009,8 @@ extern void warn_for_sign_compare (location_t, tree op0, tree op1, tree result_type, enum tree_code resultcode); +extern void set_underlying_type (tree x); +extern bool is_typedef_decl (tree x); /* In c-gimplify.c */ extern void c_genericize (tree); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 9202feb4b94..8930d93c0cd 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2002,67 +2002,6 @@ warn_if_shadowing (tree new_decl) } } - -/* Subroutine of pushdecl. - - X is a TYPE_DECL for a typedef statement. Create a brand new - ..._TYPE node (which will be just a variant of the existing - ..._TYPE node with identical properties) and then install X - as the TYPE_NAME of this brand new (duplicate) ..._TYPE node. - - The whole point here is to end up with a situation where each - and every ..._TYPE node the compiler creates will be uniquely - associated with AT MOST one node representing a typedef name. - This way, even though the compiler substitutes corresponding - ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very - early on, later parts of the compiler can always do the reverse - translation and get back the corresponding typedef name. For - example, given: - - typedef struct S MY_TYPE; - MY_TYPE object; - - Later parts of the compiler might only know that `object' was of - type `struct S' if it were not for code just below. With this - code however, later parts of the compiler see something like: - - struct S' == struct S - typedef struct S' MY_TYPE; - struct S' object; - - And they can then deduce (from the node for type struct S') that - the original object declaration was: - - MY_TYPE object; - - Being able to do this is important for proper support of protoize, - and also for generating precise symbolic debugging information - which takes full account of the programmer's (typedef) vocabulary. - - Obviously, we don't want to generate a duplicate ..._TYPE node if - the TYPE_DECL node that we are now processing really represents a - standard built-in type. */ - -static void -clone_underlying_type (tree x) -{ - if (DECL_IS_BUILTIN (x)) - { - if (TYPE_NAME (TREE_TYPE (x)) == 0) - TYPE_NAME (TREE_TYPE (x)) = x; - } - else if (TREE_TYPE (x) != error_mark_node - && DECL_ORIGINAL_TYPE (x) == NULL_TREE) - { - tree tt = TREE_TYPE (x); - DECL_ORIGINAL_TYPE (x) = tt; - tt = build_variant_type_copy (tt); - TYPE_NAME (tt) = x; - TREE_USED (tt) = TREE_USED (x); - TREE_TYPE (x) = tt; - } -} - /* Record a decl-node X as belonging to the current lexical scope. Check for errors (such as an incompatible declaration for the same name already seen in the same scope). @@ -2288,7 +2227,7 @@ pushdecl (tree x) skip_external_and_shadow_checks: if (TREE_CODE (x) == TYPE_DECL) - clone_underlying_type (x); + set_underlying_type (x); bind (name, x, scope, /*invisible=*/false, nested, locus); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5b5268157e3..63d5c0762bb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,36 @@ +2009-04-02 Dodji Seketeli <dodji@redhat.com> + + PR c++/26693 + * decl2.c (grokfield): when a typedef appears in a + class, create the typedef variant type node for it. + (save_template_attributes): Creating typedef variant type node + here is now useless. + * decl.c (grokdeclarator): If the typedef'ed struct/class was + anonymous, set the proper type name to all its type variants. + (xref_basetypes) : Fixup the variant types after setting + TYPE_BINFO on REF. + * name-lookup.c (pushdecl_maybe_friend): Reuse the + set_underlying_type function to install typedef variant types. + * cp-tree.h (MEMBER_TYPES_NEEDING_ACCESS_CHECK): New template accessor + macro. + (append_type_to_template_for_access_check): New entry points. + * semantics.c (check_accessibility_of_qualified_id): + When a typedef that is a member of a class appears in a template, + add it to the template. It will be ... + * class.c (finish_struct_bits): Split type variant fixup into ... + (fixup_type_variants): A new entry point. + * pt.c (instantiate_class_template, instantiate_template ): ... access + checked at template instantiation time. + (resolve_type_name_type): The type name should be the name of the + main type variant. + (retrieve_specialization): Specializations of template typedefs aren't + to looked up in DECL_TEMPLATE_INSTANTIATIONS (tmpl). + (append_type_to_template_for_access_check): New entry point. + (tsubst_decl): For typedefs, build the variant type from the correct + original type. + (get_class_bindings): Fix function comment. + (perform_typedefs_access_check): New entry point. + 2009-03-31 Jason Merrill <jason@redhat.com> PR c++/34691 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b8553effc03..c1885be2e77 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1439,16 +1439,17 @@ determine_primary_bases (tree t) BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary); } } - -/* Set memoizing fields and bits of T (and its variants) for later - use. */ -static void -finish_struct_bits (tree t) +/* Update the variant types of T. */ + +void +fixup_type_variants (tree t) { tree variants; - /* Fix up variants (if any). */ + if (!t) + return; + for (variants = TYPE_NEXT_VARIANT (t); variants; variants = TYPE_NEXT_VARIANT (variants)) @@ -1472,6 +1473,17 @@ finish_struct_bits (tree t) /* All variants of a class have the same attributes. */ TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t); } +} + + +/* Set memoizing fields and bits of T (and its variants) for later + use. */ + +static void +finish_struct_bits (tree t) +{ + /* Fix up variants (if any). */ + fixup_type_variants (t); if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t)) /* For a class w/o baseclasses, 'finish_struct' has set diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9878d9d29a0..f28cfc6353a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3181,6 +3181,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \ && !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE)) +/* The chained list of typedefs that are referenced in templates. + These typedefs need to be access checked at template instantiation time. + There are put here at parsing time. */ +#define MEMBER_TYPES_NEEDING_ACCESS_CHECK(NODE) DECL_ACCESS (NODE) + /* Nonzero if NODE which declares a type. */ #define DECL_DECLARES_TYPE_P(NODE) \ (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE)) @@ -4278,6 +4283,7 @@ extern bool type_has_user_nondefault_constructor (tree); extern bool type_has_user_provided_constructor (tree); extern bool type_has_user_provided_default_constructor (tree); extern bool defaultable_fn_p (tree); +extern void fixup_type_variants (tree); /* in cvt.c */ extern tree convert_to_reference (tree, tree, int, int, tree); @@ -4548,6 +4554,7 @@ extern tree check_explicit_specialization (tree, tree, int, int); extern tree make_auto (void); 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); extern tree splice_late_return_type (tree, tree); extern bool is_auto (const_tree); extern tree process_template_parm (tree, tree, bool, bool); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6537c50409f..6e122a542b4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8823,12 +8823,11 @@ grokdeclarator (const cp_declarator *declarator, && TYPE_ANONYMOUS_P (type) && cp_type_quals (type) == TYPE_UNQUALIFIED) { - tree oldname = TYPE_NAME (type); tree t; /* Replace the anonymous name with the real name everywhere. */ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) - if (TYPE_NAME (t) == oldname) + if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) TYPE_NAME (t) = decl; if (TYPE_LANG_SPECIFIC (type)) @@ -10787,6 +10786,9 @@ xref_basetypes (tree ref, tree base_list) BINFO_OFFSET (binfo) = size_zero_node; BINFO_TYPE (binfo) = ref; + /* Apply base-class info set up to the variants of this type. */ + fixup_type_variants (ref); + if (max_bases) { BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, gc, max_bases); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2be621da7c5..91c707d7b69 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -820,6 +820,9 @@ grokfield (const cp_declarator *declarator, cplus_decl_attributes (&value, attrlist, attrflags); } + if (declspecs->specs[(int)ds_typedef]) + set_underlying_type (value); + return value; } @@ -1125,19 +1128,6 @@ save_template_attributes (tree *attr_p, tree *decl_p) if (!late_attrs) return; - /* Give this type a name so we know to look it up again at instantiation - time. */ - if (TREE_CODE (*decl_p) == TYPE_DECL - && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE) - { - tree oldt = TREE_TYPE (*decl_p); - tree newt = build_variant_type_copy (oldt); - DECL_ORIGINAL_TYPE (*decl_p) = oldt; - TREE_TYPE (*decl_p) = newt; - TYPE_NAME (newt) = *decl_p; - TREE_USED (newt) = TREE_USED (*decl_p); - } - if (DECL_P (*decl_p)) q = &DECL_ATTRIBUTES (*decl_p); else diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 277de78b420..f02605f5ae0 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -862,28 +862,20 @@ pushdecl_maybe_friend (tree x, bool is_friend) /* If declaring a type as a typedef, copy the type (unless we're at line 0), and install this TYPE_DECL as the new type's typedef - name. See the extensive comment in ../c-decl.c (pushdecl). */ + name. See the extensive comment of set_underlying_type (). */ if (TREE_CODE (x) == TYPE_DECL) { tree type = TREE_TYPE (x); - if (DECL_IS_BUILTIN (x)) - { - if (TYPE_NAME (type) == 0) - TYPE_NAME (type) = x; - } - else if (type != error_mark_node && TYPE_NAME (type) != x - /* We don't want to copy the type when all we're - doing is making a TYPE_DECL for the purposes of - inlining. */ - && (!TYPE_NAME (type) - || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))) - { - DECL_ORIGINAL_TYPE (x) = type; - type = build_variant_type_copy (type); - TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x)); - TYPE_NAME (type) = x; - TREE_TYPE (x) = type; - } + + if (DECL_IS_BUILTIN (x) + || (TREE_TYPE (x) != error_mark_node + && TYPE_NAME (type) != x + /* We don't want to copy the type when all we're + doing is making a TYPE_DECL for the purposes of + inlining. */ + && (!TYPE_NAME (type) + || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))) + set_underlying_type (x); if (type != error_mark_node && TYPE_NAME (type) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c3873cd7ea3..58a4d3f77ea 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -175,6 +175,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); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function @@ -949,6 +950,7 @@ retrieve_specialization (tree tmpl, tree args, 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 @@ -6928,6 +6930,37 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, } } +/* 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) { @@ -7403,6 +7436,12 @@ 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 (); @@ -12024,6 +12063,12 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) /* 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 (); @@ -14404,7 +14449,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) /* 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: @@ -16722,7 +16767,15 @@ resolve_typename_type (tree type, bool only_current_p) 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. */ @@ -17047,4 +17100,46 @@ type_uses_auto (tree type) 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" diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 038715ba2b1..ee8c0ccfafa 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1528,6 +1528,32 @@ 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, + add it to a list tied to the template. + At template instantiation time, that list will be walked and + access check performed. */ + if (is_typedef_decl (decl)) + { + /* This the scope through which type_decl is accessed. + It will be useful information later to do access check for + type_decl usage. */ + tree scope = nested_name_specifier + ? nested_name_specifier + : DECL_CONTEXT (decl); + tree templ_info = NULL; + tree cs = current_scope (); + + if (cs && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)) + templ_info = get_template_info (cs); + + if (templ_info + && TI_TEMPLATE (templ_info) + && scope + && CLASS_TYPE_P (scope) + && !currently_open_class (scope)) + append_type_to_template_for_access_check (current_scope (), decl, scope); + } + /* If we're not checking, return immediately. */ if (deferred_access_no_check) return; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 48b2e9d3f65..3081d43219a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2009-04-02 Dodji Seketeli <dodji@redhat.com> + + PR c++/26693 + * g++.dg/template/typedef11.C: New test. + * g++.dg/template/typedef12.C: Likewise. + * g++.dg/template/typedef13.C: Likewise. + * g++.dg/template/typedef14.C: Likewise. + * g++.dg/template/typedef15.C: Likewise. + * g++.dg/template/typedef16.C: Likewise. + * g++.dg/template/sfinae3.C: Compile this pedantically. + The only errors expected should be the one saying the typedef is ill + formed. + * g++.old-deja/g++.pt/typename8.C: Likewise. + * g++.dg/template/access11.C: Update this. + 2009-04-02 Richard Guenther <rguenther@suse.de> PR tree-optimization/37221 diff --git a/gcc/testsuite/g++.dg/template/access11.C b/gcc/testsuite/g++.dg/template/access11.C index 4c8dce521a8..38bd5155f65 100644 --- a/gcc/testsuite/g++.dg/template/access11.C +++ b/gcc/testsuite/g++.dg/template/access11.C @@ -17,8 +17,8 @@ template <> struct X::Y<int> { A::X x; // { dg-error "this context" } }; -template <typename T> struct X::Y { +template <typename T> struct X::Y { // { dg-error "this context" } typename T::X x; // { dg-error "this context" } }; -template struct X::Y<A>; // { dg-message "instantiated" } +template struct X::Y<A>; // { dg-message "instantiated from here" } diff --git a/gcc/testsuite/g++.dg/template/sfinae3.C b/gcc/testsuite/g++.dg/template/sfinae3.C index 5799a364e42..349463d95fe 100644 --- a/gcc/testsuite/g++.dg/template/sfinae3.C +++ b/gcc/testsuite/g++.dg/template/sfinae3.C @@ -1,5 +1,5 @@ // PR c++/24671 -// { dg-options "" } +// { dg-do compile } template<typename> struct A { @@ -9,9 +9,9 @@ template<typename> struct A template<typename> struct B { - B(const B&); // { dg-message "candidate" } - typedef typename A<char[A<B>::i]>::X Y; - template<typename T> B(T, Y); // { dg-error "call" } + B(const B&); + typedef typename A<char[A<B>::i]>::X Y; // { dg-error "forbids zero-size array" } + template<typename T> B(T, Y); }; -B<int> b(0,0); +B<int> b(0,0); // { dg-message "instantiated from here" } diff --git a/gcc/testsuite/g++.dg/template/typedef11.C b/gcc/testsuite/g++.dg/template/typedef11.C new file mode 100644 index 00000000000..c7c7c989f72 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef11.C @@ -0,0 +1,25 @@ +// Author: Dodji Seketeli <dodji@redhat.com> +// Origin: PR c++/26693 +// { dg-do compile } + + +class Alpha +{ + typedef int X; // { dg-error "'typedef int Alpha::X' is private" } +}; + +template<int> +class Beta +{ + typedef int Y; // { dg-error "'typedef int Beta<0>::Y' is private" } +}; + +template <int> +int +bar () +{ + Beta<0>::Y i = 0; + return Alpha::X (); +} + +int i = bar<0> (); // { dg-error "within this context" } diff --git a/gcc/testsuite/g++.dg/template/typedef12.C b/gcc/testsuite/g++.dg/template/typedef12.C new file mode 100644 index 00000000000..30605044f6f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef12.C @@ -0,0 +1,23 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// Origin: Jason Merrill <jason@redhat.com>, PR c++/26693 +// { dg-do compile } + +class A +{ + protected: + typedef int mytype; +}; + +template <class T> class B; + +class C: public A +{ + template <class T> friend class B; +}; + +template <class T> class B +{ + C::mytype mem; +}; + +B<int> b; diff --git a/gcc/testsuite/g++.dg/template/typedef13.C b/gcc/testsuite/g++.dg/template/typedef13.C new file mode 100644 index 00000000000..aa8bb326829 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef13.C @@ -0,0 +1,16 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// Origin: PR c++/26693 +// { dg-do compile } + +class A +{ + typedef int mytype; // { dg-error "typedef int A::mytype' is private" } +}; + +template <class T> class B : public A +{ // { dg-error "within this context" } + mytype mem; +}; + +B<int> b; // { dg-message "instantiated from here" } + diff --git a/gcc/testsuite/g++.dg/template/typedef14.C b/gcc/testsuite/g++.dg/template/typedef14.C new file mode 100644 index 00000000000..caa565a08cd --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef14.C @@ -0,0 +1,16 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// Origin: PR c++/26693 +// { dg-do compile } + +template <class T> +struct A +{ + typedef int mytype; + + void + foo () + { + mytype v = ~static_cast<mytype> (0); + } +}; + diff --git a/gcc/testsuite/g++.dg/template/typedef15.C b/gcc/testsuite/g++.dg/template/typedef15.C new file mode 100644 index 00000000000..e9e3d94ff2e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef15.C @@ -0,0 +1,25 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// Origin: PR c++/26693 +// { dg-do compile } + +template<class T> struct C0; + +struct Foo { + typedef int TypedefedFoo; + typedef C0<Foo> TypedefedC0; +}; + +template<class T> +struct C0 +{ + typedef Foo TypedefedFoo; + typename T::TypedefedC0::TypedefedFoo m; +}; + +template<class U> +struct C1 +{ + typedef C0<Foo> TypedefedC0; +}; + +C0<C1<int> > c; diff --git a/gcc/testsuite/g++.dg/template/typedef16.C b/gcc/testsuite/g++.dg/template/typedef16.C new file mode 100644 index 00000000000..29870605a62 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef16.C @@ -0,0 +1,27 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// Origin PR c++/26693 +// { dg-do compile } + +struct C0 +{ +}; + +template<class T, class U> +struct C1 +{ + typedef C0 TypedefedC0; + + template<class W> + void foo (TypedefedC0 *, W) + { + } + + template<class W> C1 (W w) + { + TypedefedC0 c; + foo (&c, w); + } + +}; +C0 c0; +C1<int, char> c1 (&c0); diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C index 6eb818b3947..4861cf301ed 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C @@ -5,14 +5,14 @@ template < class T > class A public: typedef typename T::myT anotherT; // { dg-error "" } undefined type - anotherT t; // { dg-error "" } undefined type + anotherT t; A() { } - A(anotherT _t) { // { dg-error "" } undefined type + A(anotherT _t) { t=_t; } - anotherT getT() { // { dg-error "" } undefined type + anotherT getT() { return t; } }; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 997f960b59e..61b2c0594a2 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2009-04-02 Dodji Seketeli <dodji@redhat.com> + + * include/ext/bitmap_allocator.h: the typedefs should be made public + if we want them to be accessible. This has been revealed by the patch + that fixes PR c++/26693 in g++. + 2009-04-02 Jakub Jelinek <jakub@redhat.com> * config/abi/post/powerpc64-linux-gnu/32/baseline_symbols.txt: @@ -785,11 +791,6 @@ on HPUX. * configure: Regenerate. -2009-01-22 Dodji Seketeli <dodji@redhat.com> - - * include/ext/bitmap_allocator.h: Reverting changes related to PR - c++/26693. - 2009-01-21 Benjamin Kosnik <bkoz@redhat.com> * testsuite/29_atomics/headers/stdatomic.h/functions.c: Remove @@ -797,10 +798,6 @@ 2009-01-21 Dodji Seketeli <dodji@redhat.com> - * include/ext/bitmap_allocator.h: the typedefs should be made public - if we want them to be accessible. This has been revealed by the patch - that fixes PR c++/26693 in g++. - 2009-01-20 Benjamin Kosnik <bkoz@redhat.com> Uros Bizjak <ubizjak@gmail.com> diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h index 69f8a9d02ea..b7ff6fd4070 100644 --- a/libstdc++-v3/include/ext/bitmap_allocator.h +++ b/libstdc++-v3/include/ext/bitmap_allocator.h @@ -550,11 +550,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) */ class free_list { + public: typedef size_t* value_type; typedef __detail::__mini_vector<value_type> vector_type; typedef vector_type::iterator iterator; typedef __mutex __mutex_type; + private: struct _LT_pointer_compare { bool |