gcc/ChangeLog: 2008-12-04 Dodji Seketeli 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. (is_typedef_type ): New entry point. * tree.h: Added a new member member_types_needing_access_check to struct tree_decl_non_common. (set_underlying_type): New entry point. (is_typedef_type): Likewise. gcc/cp/ChangeLog: 2008-12-04 Dodji Seketeli PR c++/26693 * decl2.c (grokfield): when a typedef appears in a class, create the typedef variant type node for it. * decl.c (grokdeclarator): If the typedef'ed struct/class was anonymous, set the proper type name to all its type variants. * 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. (is_class_nested, 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 ... * pt.c (instantiate_class_template, instantiate_template ): ... access checked at template instantiation time. (tsubst): Handle the case of being called with NULL args. (append_type_to_template_for_access_check): New entry point. * search.c (is_class_nested): New entry point. gcc/testsuite/ChangeLog: 2008-12-04 Dodji Seketeli 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/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. libstdc++-v3/ChangeLog: 2008-12-04 Dodji Seketeli * 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++. diff --git a/gcc/c-common.c b/gcc/c-common.c index e83b58e..1b605e3 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -8360,4 +8360,81 @@ 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 (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 type. */ +bool +is_typedef_type (tree x) +{ + return (x + && x != error_mark_node + && TREE_CODE (x) == TYPE_DECL + && TREE_TYPE (x) + && TREE_TYPE (x) != error_mark_node + && TYPE_NAME (TREE_TYPE (x)) + && TYPE_MAIN_VARIANT (TREE_TYPE (x)) + && TYPE_NAME (TREE_TYPE (x)) + != TYPE_STUB_DECL (TYPE_MAIN_VARIANT (TREE_TYPE (x)))); +} + #include "gt-c-common.h" diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 6f88f62..3a96195 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1971,67 +1971,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). @@ -2254,7 +2193,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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9f10ed1..23ef874 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3178,6 +3178,14 @@ 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 some types that are referenced in templates. + These types are those which need to be access checked at + template instantiation time. For the time being, only typedef-ed types defined + as class members are put here at parsing time. + Other types for which access check could be required at template instantiation + time could be added later. */ +#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)) @@ -4231,6 +4239,7 @@ extern void pushclass (tree); extern void popclass (void); extern void push_nested_class (tree); extern void pop_nested_class (void); +extern bool is_class_nested (tree, tree); extern int current_lang_depth (void); extern void push_lang_context (tree); extern void pop_lang_context (void); @@ -4532,6 +4541,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 997c580..92df629 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8725,6 +8725,7 @@ grokdeclarator (const cp_declarator *declarator, decl = build_lang_decl (TYPE_DECL, unqualified_id, type); else decl = build_decl (TYPE_DECL, unqualified_id, type); + if (id_declarator && declarator->u.id.qualifying_scope) { error ("%Jtypedef name may not be a nested-name-specifier", decl); TREE_TYPE (decl) = error_mark_node; @@ -8759,12 +8760,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)) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index da9201e..4d92e4b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -804,6 +804,9 @@ grokfield (const cp_declarator *declarator, DECL_NONLOCAL (value) = 1; DECL_CONTEXT (value) = current_class_type; + if (declspecs->specs[(int)ds_typedef]) + set_underlying_type (value); + if (processing_template_decl) value = push_template_decl (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 0da373c..d9ea96d 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -847,28 +847,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/parser.c b/gcc/cp/parser.c index 8fdd58c..aa2fad5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11367,7 +11367,7 @@ cp_parser_nonclass_name (cp_parser* parser) else if (type_decl != error_mark_node && !parser->scope) maybe_note_name_used_in_class (identifier, type_decl); - + return type_decl; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 127d37c..163d8db 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7320,6 +7320,31 @@ instantiate_class_template (tree type) && DECL_TEMPLATE_INFO (t)) tsubst_default_arguments (t); + /* Some types 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. */ + for (t = MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ); 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, args, tf_error, NULL_TREE); + + if (uses_template_parms (type_scope)) + type_scope = tsubst (type_scope, args, tf_error, NULL_TREE); + + gcc_assert (type_decl && type_decl != error_mark_node + && type_scope && type_scope != error_mark_node); + + perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl); + } + + perform_deferred_access_checks (); pop_nested_class (); pop_from_top_level (); pop_deferring_access_checks (); @@ -8902,7 +8927,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) || t == void_type_node || t == char_type_node || t == unknown_type_node - || TREE_CODE (t) == NAMESPACE_DECL) + || TREE_CODE (t) == NAMESPACE_DECL + || args == NULL) return t; if (DECL_P (t)) @@ -8922,7 +8948,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) && TYPE_NAME (t) != TYPE_MAIN_DECL (t)) { tree decl = TYPE_NAME (t); - + if (DECL_CLASS_SCOPE_P (decl) && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl)) && uses_template_parms (DECL_CONTEXT (decl))) @@ -9040,7 +9066,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) r = NULL_TREE; gcc_assert (TREE_VEC_LENGTH (args) > 0); - template_parm_level_and_index (t, &level, &idx); + template_parm_level_and_index (t, &level, &idx); levels = TMPL_ARGS_DEPTH (args); if (level <= levels) @@ -11763,6 +11789,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) tree fndecl; tree gen_tmpl; tree spec; + tree t; HOST_WIDE_INT saved_processing_template_decl; if (tmpl == error_mark_node) @@ -11841,6 +11868,24 @@ 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 types 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. */ + 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, targ_ptr, tf_error, NULL_TREE); + + perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl); + } perform_deferred_access_checks (); pop_access_scope (fndecl); pop_deferring_access_checks (); @@ -16527,7 +16572,16 @@ 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 (TREE_TYPE (TYPE_MAIN_DECL (type)));*/ + 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. */ @@ -16852,4 +16906,45 @@ type_uses_auto (tree type) return NULL_TREE; } +/* Append TYPE_DECL to the template TMPL. + TMPL is eiter a class type or a FUNCTION_DECL associated + to a TEMPLATE_DECL. + At TMPL 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; + } + + node = build_tree_list (type_decl, scope); + MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl) = + chainon (node, MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl)); +} + #include "gt-cp-pt.h" diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 7fc040b..1cce251 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2623,3 +2623,20 @@ original_binfo (tree binfo, tree here) return result; } +/* Returns true if NESTED is a nested class of BASE, false otherwise. */ +bool +is_class_nested (tree base, tree nested) +{ + tree t; + + if (!base || !nested + || !CLASS_TYPE_P (base) + || !CLASS_TYPE_P (nested)) + return false; + + for (t = TYPE_CONTEXT (nested); t && TYPE_P (t); t = TYPE_CONTEXT (t)) + if (same_type_p (t, base)) + return true; + return false; +} + diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e0ae6ff..5ed41c1 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1524,6 +1524,38 @@ 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_type (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 templ_type = NULL; + + if (current_function_decl) + templ_type = current_function_decl; + else if (current_class_type) + templ_type = current_class_type; + if (templ_type) + templ_info = get_template_info (templ_type); + + if (templ_info + && TI_TEMPLATE (templ_info) + && scope + && CLASS_TYPE_P (scope) + && ((current_class_type + && !same_type_p (scope, current_class_type) + && !is_class_nested (scope, current_class_type)) + || (current_function_decl + && !DECL_FUNCTION_MEMBER_P (current_function_decl)))) + append_type_to_template_for_access_check (templ_type, decl, scope); + } + /* If we're not checking, return immediately. */ if (deferred_access_no_check) return; diff --git a/gcc/testsuite/g++.dg/template/access11.C b/gcc/testsuite/g++.dg/template/access11.C index 4c8dce5..38bd515 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 { A::X x; // { dg-error "this context" } }; -template struct X::Y { +template struct X::Y { // { dg-error "this context" } typename T::X x; // { dg-error "this context" } }; -template struct X::Y; // { dg-message "instantiated" } +template struct X::Y; // { dg-message "instantiated from here" } diff --git a/gcc/testsuite/g++.dg/template/sfinae3.C b/gcc/testsuite/g++.dg/template/sfinae3.C index 5799a36..349463d 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 struct A { @@ -9,9 +9,9 @@ template struct A template struct B { - B(const B&); // { dg-message "candidate" } - typedef typename A::i]>::X Y; - template B(T, Y); // { dg-error "call" } + B(const B&); + typedef typename A::i]>::X Y; // { dg-error "forbids zero-size array" } + template B(T, Y); }; -B b(0,0); +B 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 0000000..c7c7c98 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef11.C @@ -0,0 +1,25 @@ +// Author: Dodji Seketeli +// Origin: PR c++/26693 +// { dg-do compile } + + +class Alpha +{ + typedef int X; // { dg-error "'typedef int Alpha::X' is private" } +}; + +template +class Beta +{ + typedef int Y; // { dg-error "'typedef int Beta<0>::Y' is private" } +}; + +template +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 0000000..3060504 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef12.C @@ -0,0 +1,23 @@ +// Contributed by Dodji Seketeli +// Origin: Jason Merrill , PR c++/26693 +// { dg-do compile } + +class A +{ + protected: + typedef int mytype; +}; + +template class B; + +class C: public A +{ + template friend class B; +}; + +template class B +{ + C::mytype mem; +}; + +B b; diff --git a/gcc/testsuite/g++.dg/template/typedef13.C b/gcc/testsuite/g++.dg/template/typedef13.C new file mode 100644 index 0000000..aa8bb32 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef13.C @@ -0,0 +1,16 @@ +// Contributed by Dodji Seketeli +// Origin: PR c++/26693 +// { dg-do compile } + +class A +{ + typedef int mytype; // { dg-error "typedef int A::mytype' is private" } +}; + +template class B : public A +{ // { dg-error "within this context" } + mytype mem; +}; + +B 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 0000000..caa565a --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef14.C @@ -0,0 +1,16 @@ +// Contributed by Dodji Seketeli +// Origin: PR c++/26693 +// { dg-do compile } + +template +struct A +{ + typedef int mytype; + + void + foo () + { + mytype v = ~static_cast (0); + } +}; + diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C index 6eb818b..4861cf3 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/gcc/tree.h b/gcc/tree.h index d85918f..a1d814c 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3405,6 +3405,9 @@ struct tree_target_option GTY(()) /* Return a tree node that encapsulates the current target options. */ extern tree build_target_option_node (void); +extern void set_underlying_type (tree x); + +extern bool is_typedef_type (tree x); /* Define the overall contents of a tree node. It may be any of the structures declared above diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h index 7f5466a..7768bd2 100644 --- a/libstdc++-v3/include/ext/bitmap_allocator.h +++ b/libstdc++-v3/include/ext/bitmap_allocator.h @@ -549,11 +549,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) */ class free_list { + public: typedef size_t* value_type; typedef __detail::__mini_vector vector_type; typedef vector_type::iterator iterator; typedef __mutex __mutex_type; + private: struct _LT_pointer_compare { bool