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 :

[...]

I think this is the behavior we want; if as an extension we allow B<int> to be instantiated at all, we should also allow the use of the Y typedef in this situation. The zero-length array is not coming from argument deduction in this case, so it isn't a substitution failure.

Pedantically, the testcase is ill-formed because B<int>::Y is ill-formed. If we allow B<int>::Y, we should also allow it to be used.

Okay. So that attached updated patch removes the extra tsubsting of the main type variant.
As a result, the patch modifies the two tests that were expecting the use the the typedef to be considered erratic. Now only the definition of the typedef is considered to be erratic.


The passes passes regtest on trunk for the x86_64 architecture.

Dodji.
gcc/ChangeLog:
2008-10-30  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.

gcc/cp/ChangeLog:
2008-10-29  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.
	* pt.c (tsubst): If we are accessing a typdefe'd type defined in a
	class, make sure that typedef is accessible.

gcc/testsuite/ChangeLog:
2008-10-29  Dodji Seketeli  <dodji@redhat.com>

	PR c++/26693
	* g++.dg/template/typedef11.C: New test.
	* 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.

libstdc++-v3/ChangeLog:
2008-10-29  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 eba6161..2226928 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/decl.c b/gcc/cp/decl.c
index b0b03a5..8ddae96 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8680,6 +8680,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;
@@ -8714,12 +8715,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 b326752..17b3460 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -799,6 +799,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);
 
@@ -1110,19 +1113,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/pt.c b/gcc/cp/pt.c
index 13a2361..3604801 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8921,22 +8921,41 @@ 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)))
+	  && uses_template_parms (DECL_CONTEXT (decl))
+	  && uses_template_parms (decl))
 	{
 	  tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
 	  tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
 	  r = retrieve_specialization (tmpl, gen_args, false);
+	  if (r && !enforce_access (TYPE_BINFO (DECL_CONTEXT (r)), r, r))
+		return error_mark_node;
 	}
       else if (DECL_FUNCTION_SCOPE_P (decl)
 	       && DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
 	       && uses_template_parms (DECL_TI_ARGS (DECL_CONTEXT (decl))))
 	r = retrieve_local_specialization (decl);
       else
-	/* The typedef is from a non-template context.  */
-	return t;
+	{
+	  /* The typedef is from a non-template context.  */
+
+	  if (DECL_CONTEXT (decl)
+	      && AGGREGATE_TYPE_P (DECL_CONTEXT (decl))
+	      && !uses_template_parms (DECL_CONTEXT (decl)))
+	    {
+	      /* t has been lowered from a typedef'ed type (namely decl) that is
+		 a member of a class/struct. E.g:
+		 class Foo {
+		  typedef t X;
+		 };
+		 In that example, we need to make sure X is accessible from here.  */
+	      if (!enforce_access (TYPE_BINFO (DECL_CONTEXT (decl)), decl, decl))
+		return error_mark_node;
+	    }
+	  return t;
+	}
 
       if (r)
 	{
@@ -16525,7 +16544,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 (TREE_TYPE (TYPE_MAIN_DECL (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.  */
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..6e71729
--- /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; // { dg-error "within this context" }
+  return Alpha::X (); // { dg-error "within this context" }
+}
+
+int i = bar<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.c b/gcc/tree.c
index 10b50d1..4b9e793 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9167,4 +9167,65 @@ 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;
+    }
+}
+
 #include "gt-tree.h"
diff --git a/gcc/tree.h b/gcc/tree.h
index a85b4c6..2b3b128 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3405,6 +3405,8 @@ 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);
+
 
 /* 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]