OSDN Git Service

gcc/ChangeLog:
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 2 Apr 2009 09:24:19 +0000 (09:24 +0000)
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 2 Apr 2009 09:24:19 +0000 (09:24 +0000)
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.

gcc/cp/ChangeLog:
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 be 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.

gcc/testsuite/ChangeLog:
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.

libstdc++-v3/ChangeLog:
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++.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145440 138bc75d-0d04-0410-961f-82ee72b054a4

24 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/access11.C
gcc/testsuite/g++.dg/template/sfinae3.C
gcc/testsuite/g++.dg/template/typedef11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typedef12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typedef13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typedef14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typedef15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typedef16.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/typename8.C
libstdc++-v3/ChangeLog
libstdc++-v3/include/ext/bitmap_allocator.h

index 8305ab1..e50c34c 100644 (file)
@@ -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
index d102b6e..9886cdf 100644 (file)
@@ -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"
index 26423a8..f5c755b 100644 (file)
@@ -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);
index 9202feb..8930d93 100644 (file)
@@ -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);
 
index 5b52681..63d5c07 100644 (file)
@@ -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
index b8553ef..c1885be 100644 (file)
@@ -1439,16 +1439,17 @@ determine_primary_bases (tree t)
       BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
     }
 }
-\f
-/* 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);
     }
+}
+
+\f
+/* 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
index 9878d9d..f28cfc6 100644 (file)
@@ -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);
index 6537c50..6e122a5 100644 (file)
@@ -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);
index 2be621d..91c707d 100644 (file)
@@ -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
index 277de78..f02605f 100644 (file)
@@ -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)
index c3873cd..58a4d3f 100644 (file)
@@ -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"
index 038715b..ee8c0cc 100644 (file)
@@ -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;
index 48b2e9d..3081d43 100644 (file)
@@ -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
index 4c8dce5..38bd515 100644 (file)
@@ -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" }
index 5799a36..349463d 100644 (file)
@@ -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 (file)
index 0000000..c7c7c98
--- /dev/null
@@ -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 (file)
index 0000000..3060504
--- /dev/null
@@ -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 (file)
index 0000000..aa8bb32
--- /dev/null
@@ -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 (file)
index 0000000..caa565a
--- /dev/null
@@ -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 (file)
index 0000000..e9e3d94
--- /dev/null
@@ -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 (file)
index 0000000..2987060
--- /dev/null
@@ -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);
index 6eb818b..4861cf3 100644 (file)
@@ -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;
   }
 };
index 997f960..61b2c05 100644 (file)
@@ -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:
        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
 
 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>
 
index 69f8a9d..b7ff6fd 100644 (file)
@@ -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