diff options
author | Dodji Seketeli <dodji@redhat.com> | 2009-01-21 16:14:49 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2009-01-21 17:14:49 +0100 |
commit | d597b3ce68d904078ca38bca09c5e8984d934364 (patch) | |
tree | 9c26f4fbfa6128e66099ace4205d1bd99cc4c3a3 /gcc | |
parent | 210879b85b09194934eabcf5777cf2cff6e8dedc (diff) | |
download | gcc-d597b3ce68d904078ca38bca09c5e8984d934364.zip gcc-d597b3ce68d904078ca38bca09c5e8984d934364.tar.gz gcc-d597b3ce68d904078ca38bca09c5e8984d934364.tar.bz2 |
re PR c++/26693 (Access checks not performed for types in templates)
gcc/ChangeLog:
2009-01-21 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.
(is_typedef_decl ): 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/
2009-01-21 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.
* 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 ...
* pt.c (instantiate_class_template, instantiate_template ): ... access
checked at template instantiation time.
(tsubst): Handle the case of being called with NULL args.
(resolve_type_name_type): The type name should be the name of the
main type variant.
(append_type_to_template_for_access_check): New entry point.
gcc/testsuite/ChangeLog
2009-01-21 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/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:
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++.
From-SVN: r143546
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/c-common.c | 69 | ||||
-rw-r--r-- | gcc/c-decl.c | 63 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 9 | ||||
-rw-r--r-- | gcc/cp/decl.c | 4 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 16 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 30 | ||||
-rw-r--r-- | gcc/cp/pt.c | 95 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 24 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 13 | ||||
-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++.old-deja/g++.pt/typename8.C | 6 | ||||
-rw-r--r-- | gcc/tree.h | 3 |
19 files changed, 356 insertions, 107 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 35de52a..bc4c361 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2009-01-21 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. + (is_typedef_decl ): 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. + 2009-01-21 Bingfeng Mei <bmei@broadcom.com> * alias.c (walk_mems_1, walk_mems_2, insn_alias_sets_conflict_p): diff --git a/gcc/c-common.c b/gcc/c-common.c index 5eed1dc..f398cf8 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -8363,4 +8363,73 @@ 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_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-decl.c b/gcc/c-decl.c index 7f7f2b0..8b444d4 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/ChangeLog b/gcc/cp/ChangeLog index 5808ee5f..b2ca4cf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2009-01-21 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. + * 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 ... + * pt.c (instantiate_class_template, instantiate_template ): ... access + checked at template instantiation time. + (tsubst): Handle the case of being called with NULL args. + (resolve_type_name_type): The type name should be the name of the + main type variant. + (append_type_to_template_for_access_check): New entry point. + 2009-01-19 Jason Merrill <jason@redhat.com> PR c++/23287 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 186ec9a..b740700 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3179,6 +3179,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)) @@ -4539,6 +4547,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 8476959..2163e39 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8729,6 +8729,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; @@ -8763,12 +8764,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 c888725..22192a0 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 f8d0204..2c69cfe 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/pt.c b/gcc/cp/pt.c index f6809f2..36edb44 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7387,6 +7387,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 (); @@ -11869,6 +11894,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) @@ -11947,6 +11973,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 (); @@ -16633,7 +16677,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. */ @@ -16958,4 +17010,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; + } + + 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 c9f0641..528a0c5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1529,6 +1529,30 @@ 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 cffbad4..91b8d8a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2009-01-21 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/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-01-21 Daniel Kraft <d@domob.eu> PR fortran/38887 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<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 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<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 0000000..c7c7c98 --- /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 0000000..3060504 --- /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 0000000..aa8bb32 --- /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 0000000..caa565a --- /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++.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; } }; @@ -3412,6 +3412,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_decl (tree x); /* Define the overall contents of a tree node. It may be any of the structures declared above |