This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PR c++/26693


Jason Merrill a Ãcrit :
Dodji Seketeli wrote:
Jason Merrill a Ãcrit :
Dodji Seketeli wrote:
-      && uses_template_parms (DECL_CONTEXT (decl)))
+      && uses_template_parms (DECL_CONTEXT (decl))
+      && uses_template_parms (decl))

This seems wrong. Why wouldn't we want to re-use typedefs with non-dependent types?

Ah, I did this as a stop gap measure because otherwise for a non-dependent typedef variant, the compiler was crashing in tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);


I should have investigated. Earlier. Now it seems it is crashing eventualy in tsusbt () because of the assert gcc_assert (TREE_VEC_LENGTH (args) > 0); around line 9060. This is because we are trying to tsubst a TEMPLATE_PARM_INDEX with a NULL args parameter.

A non-dependent typedef doesn't have the same template args as its containing class? Why isn't the call to push_template_decl from grokfield setting that up properly?



I think it's because the chain of calls was triggered by a fold_non_dependent_expr that calls tsubst_copy_and_build with a NULL args argument. I am not sure but I'd say that given that we are calling tsubst_copy_and_build with a NULL args, all the tsubst_* routines should be able to handle the case of args == NULL somewhat gracefully. Shouldn't we ?


The attached patch is an updated version of the earlier one that takes the case of a NULL arg in account in tsusbt, for TEMPLATE_PARM_INDEX at least. Please tell me if that could be an acceptable approach. I consider the patch to be work in progress.

[...]

Now I guess in this particular case, the right TYPE_BINFO to pass to enforce_access() would be the one of the C type, in C::mytype. If that is correct then how can I have access to that C type from within tsubst() when I am tsubsting mytype, which TYPE_DECL points to the declaration "typedef int mytype;" from class A ?

The issue is that we need to remember how the name was accessed, not just which name was used. Perhaps using TYPENAME_TYPE to express this would work.

Okay. So as discussed on IRC I tried in the attached patch to store typedef types referenced in template code into the template itself, at parsing time. Doing it at parsing time allows to also store the scope through which the typedef type is accessed.


Later at template instantiation time, the list stored of typedef types is walked and each typedef is "access-checked". The access check then takes in account the scope through which the typedef is accessed.

The patch applies to trunk, compiles libstdc++ and passes regtests.
Would this approach be worthwhile ?

Thanks,

Dodji.
gcc/ChangeLog:
2008-11-29  Dodji Seketeli  <dodji@redhat.com>
	PR c++/26693
	* c-decl.c: (clone_underlying_type): Move this  ...
	* tree.c: ... here so that it can be re-used by other front ends.
	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.
	(clone_underlying_type): New entry point.
	(is_typedef_type): Likewise.

gcc/cp/ChangeLog:
2008-11-28  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.
	* 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
	clone_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.
	* parser.c (cp_parser_nonclass_name): 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): There is a FIXME to investigate here ...
	(append_type_to_template_for_access_check): New entry point.
	* search.c (is_class_nested): New entry point.

gcc/testsuite/ChangeLog:
2008-11-29  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/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-11-28  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++.

diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 6f88f62..86ad1a9 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).
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9f10ed1..9574f44 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -444,6 +444,15 @@ typedef enum cp_id_kind
 #define IDENTIFIER_REPO_CHOSEN(NAME) \
   (TREE_LANG_FLAG_6 (NAME))
 
+/* 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_NON_COMMON_CHECK (NODE)->decl_non_common.member_types_needing_access_check
+
 /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
 #define C_TYPE_FIELDS_READONLY(TYPE) \
   (LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly)
@@ -4231,6 +4240,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 +4542,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..6f5aa10 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])
+	clone_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..65b9dcd 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 clone_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))))
+	    clone_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..515aeb6 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11367,7 +11367,39 @@ 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);
-  
+
+  /* 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.  */
+  {
+    /* 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 = parser->scope ? parser->scope : DECL_CONTEXT (type_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)
+	&& is_typedef_type (type_decl)
+	&& 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))
+	  append_type_to_template_for_access_check (templ_type,
+						    type_decl,
+						    scope);
+  }
   return type_decl;
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 127d37c..37ab921 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7320,6 +7320,30 @@ 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);
+
+      gcc_assert (type_decl && type_scope);
+
+      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 ();
@@ -8922,12 +8946,15 @@ 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)))
 	{
 	  tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+	  /* FIXME: investigate why this call crashes for some
+	   * non-dependent typedefs called with NULL args.  This eventually
+	     crashes in tsubst, for the TEMPLATE_PARM_INDEX case.  */
 	  tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
 	  r = retrieve_specialization (tmpl, gen_args, false);
 	}
@@ -9039,11 +9066,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
 	r = NULL_TREE;
 
-	gcc_assert (TREE_VEC_LENGTH (args) > 0);
+	/* FIXME: understand why we are hitting this assert.
+	   This comes from when tsubst is called with a non-dependent typedef
+	   with NULL args.  */
+	/*gcc_assert (TREE_VEC_LENGTH (args) > 0);*/
 	template_parm_level_and_index (t, &level, &idx); 
 
 	levels = TMPL_ARGS_DEPTH (args);
-	if (level <= levels)
+	if (args && level <= levels)
 	  {
 	    arg = TMPL_ARG (args, level, idx);
 
@@ -11763,6 +11793,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 +11872,23 @@ 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);
+
+      gcc_assert (type_decl && type_scope);
+
+      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 +16575,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 +16909,28 @@ type_uses_auto (tree type)
   return NULL_TREE;
 }
 
+/* Append TYPE_DECL to the template TYPE.
+   At TYPE 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 type,
+                                          tree type_decl,
+					  tree scope)
+{
+  tree node, templ;
+
+  gcc_assert (type
+	      && get_template_info (type)
+	      && TI_TEMPLATE (get_template_info (type))
+	      && type_decl
+	      && (TREE_CODE (type_decl) == TYPE_DECL));
+
+  templ = TI_TEMPLATE (get_template_info (type));
+  gcc_assert (templ);
+
+  node = build_tree_list (type_decl, scope);
+  MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ) =
+    chainon (node, MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ));
+}
+
 #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/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++.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.c b/gcc/tree.c
index e74b779..1a1a13c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9199,4 +9199,76 @@ build_target_option_node (void)
   return t;
 }
 
+/* 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
+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_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
+	  && TREE_CODE (x) == TYPE_DECL
+	  && TYPE_NAME (TREE_TYPE (x))
+	  && TYPE_NAME (TREE_TYPE (x))
+	    != TYPE_STUB_DECL (TYPE_MAIN_VARIANT (TREE_TYPE (x))));
+}
+
 #include "gt-tree.h"
diff --git a/gcc/tree.h b/gcc/tree.h
index d85918f..7882314 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3160,6 +3160,8 @@ struct tree_decl_non_common GTY(())
   tree result;
   /* C++ uses this in namespaces.  */
   tree vindex;
+  /* C++ uses this in templates.  */
+  tree member_types_needing_access_check;
 };
 
 /* In FUNCTION_DECL, holds the decl for the return value.  */
@@ -3405,6 +3407,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 clone_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<value_type> vector_type;
     typedef vector_type::iterator 		iterator;
     typedef __mutex				__mutex_type;
 
+  private:
     struct _LT_pointer_compare
     {
       bool

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]