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]

[C++ PATCH] Fix friend class name lookup part 1/n


Hi

This patch is the first of a series of patches to get friend class name 
lookup right.  There are several bugs in this area, PR c++/1016, 4403, 
13830, 14513, 15410.  This one converts the 'xref_tag' function to use 
the new 'lookup_type_scope' rather than 'lookup_tag'.  No PR is fixed 
by the patch yet.  But later ones will address the mentioned bugs above.


There is a major flaw with the current 'lookup_tag' approach, it cannot 
find typedef, nor template type parameter required to catch invalid codes.
Here is the way how 'lookup_tag' works now for the following invalid code:

     typedef int X;
     class X;       // We are doing name lookup here

1. We lookup 'X' with 'lookup_tag'.  It cannot find any name besides
   enum/struct/class/union tag names.  So it fails and returns NULL_TREE.
2. 'push_tag' is called to push the name 'class X'.  It fails because of
   the conflict, i.e. the declaration 'typedef int X;' is in the same scope.

The above scheme cannot be extended later to work with code like

     class C {
       typedef int X;
       friend class X;
     };

because we can't find the name 'X' and then want to push the name 'class X'
in the scope enclosing 'class C'.  Since the typedef is in a different scope,
there is no conflict there, and therefore no error detected.


The patch introduces the new 'lookup_type_scope' which works similar to
'lookup_name_real' but with several differences I prefer to keep them
separate functions.  (It only lookup name in current scope now, but will
be expanded to handle case like 'class C' example above in later patches.)  
The differences are documented in the comment before the new function.  

'lookup_type_scope' together with 'lookup_and_check_tag' do name lookup 
for type and dianose immediately rather then delaying until 'push_tag'.
I also added an error message displaying the location of conflicted name
because calling 'push_tag' show this information.  As a result, the
expected error message in some testcases in the g++ testsuite need to
be adjusted.

Another small change introduced by the patch is changing the function
'lookup_name_current_level' to a more correct name
'lookup_name_innermost_nonclass_level'.


The patch is tested by building libstdc++, running libstdc++ and g++
testsuited with assertion test comparing the result of 'lookup_type_scope' 
with 'lookup_tag'.  The old functions will be eventually removed.
Bootstrapped is also done.   No regression is found.

OK to committed to the mainline?

--Kriang


2004-10-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* decl.c (lookup_and_check_tag): New function.
	(xref_tag, start_enum): Use it.
	(check_elaborated_type_specifier): Move TEMPLATE_TYPE_PARM check
	before !DECL_IMPLICIT_TYPEDEF_P.  Also display previously declared
	location.
	* name-lookup.c (lookup_name_current_level): Rename to ...
	(lookup_name_innermost_nonclass_level): ... this.
	(lookup_type_scope): New function.
	* name-lookup.h (lookup_name_current_level): Rename to ...
	(lookup_name_innermost_nonclass_level): ... this.
	(lookup_type_scope): Add declaration.

2004-10-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* g++.dg/lookup/struct1.C: Adjust expected error.
	* g++.dg/parse/elab1.C: Likewise.
	* g++.dg/parse/elab2.C: Likewise.
	* g++.dg/parse/int-as-enum1.C: Likewise.
	* g++.dg/parse/struct-as-enum1.C: Likewise.
	* g++.dg/parse/typedef1.C: Likewise.
	* g++.dg/parse/typedef3.C: Likewise.
	* g++.dg/parse/typedef4.C: Likewise.
	* g++.dg/parse/typedef5.C: Likewise.
	* g++.dg/template/nontype4.C: Likewise.
	* g++.old-deja/g++.benjamin/typedef01.C: Likewise.
	* g++.old-deja/g++.other/elab1.C: Likewise.
	* g++.old-deja/g++.other/syntax4.C: Likewise.


diff -cprN gcc-main-save/gcc/cp/decl.c gcc-main-new/gcc/cp/decl.c
*** gcc-main-save/gcc/cp/decl.c	Tue Oct 12 22:48:26 2004
--- gcc-main-new/gcc/cp/decl.c	Fri Oct 15 21:51:29 2004
*************** static hashval_t typename_hash (const vo
*** 81,87 ****
  static int typename_compare (const void *, const void *);
  static tree local_variable_p_walkfn (tree *, int *, void *);
  static tree record_builtin_java_type (const char *, int);
! static const char *tag_name (enum tag_types code);
  static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
  static int walk_globals_r (tree, void*);
  static int walk_vtables_r (tree, void*);
--- 81,88 ----
  static int typename_compare (const void *, const void *);
  static tree local_variable_p_walkfn (tree *, int *, void *);
  static tree record_builtin_java_type (const char *, int);
! static const char *tag_name (enum tag_types);
! static tree lookup_and_check_tag (enum tag_types, tree, bool globalize, bool);
  static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
  static int walk_globals_r (tree, void*);
  static int walk_vtables_r (tree, void*);
*************** check_elaborated_type_specifier (enum ta
*** 9016,9021 ****
--- 9017,9030 ----
  
    type = TREE_TYPE (decl);
  
+   /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
+      is false for this case as well.  */
+   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+     {
+       error ("using template type parameter %qT after %qs",
+ 	     type, tag_name (tag_code));
+       return error_mark_node;
+     }
    /*   [dcl.type.elab]
  
         If the identifier resolves to a typedef-name or a template
*************** check_elaborated_type_specifier (enum ta
*** 9024,9039 ****
       In other words, the only legitimate declaration to use in the
       elaborated type specifier is the implicit typedef created when
       the type is declared.  */
!   if (!DECL_IMPLICIT_TYPEDEF_P (decl))
      {
        error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
!       return IS_AGGR_TYPE (type) ? type : error_mark_node;
!     }
! 
!   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
!     {
!       error ("using template type parameter %qT after %qs",
! 	     type, tag_name (tag_code));
        return error_mark_node;
      }
    else if (TREE_CODE (type) != RECORD_TYPE
--- 9033,9042 ----
       In other words, the only legitimate declaration to use in the
       elaborated type specifier is the implicit typedef created when
       the type is declared.  */
!   else if (!DECL_IMPLICIT_TYPEDEF_P (decl))
      {
        error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
!       cp_error_at ("%qD has a previous declaration here", decl);
        return error_mark_node;
      }
    else if (TREE_CODE (type) != RECORD_TYPE
*************** check_elaborated_type_specifier (enum ta
*** 9041,9052 ****
--- 9044,9057 ----
  	   && tag_code != enum_type)
      {
        error ("%qT referred to as %qs", type, tag_name (tag_code));
+       cp_error_at ("%qT has a previous declaration here", type);
        return error_mark_node;
      }
    else if (TREE_CODE (type) != ENUMERAL_TYPE
  	   && tag_code == enum_type)
      {
        error ("%qT referred to as enum", type);
+       cp_error_at ("%qT has a previous declaration here", type);
        return error_mark_node;
      }
    else if (!allow_template_p
*************** check_elaborated_type_specifier (enum ta
*** 9070,9075 ****
--- 9075,9127 ----
    return type;
  }
  
+ /* Lookup NAME in elaborate type specifier in scope according to
+    GLOBALIZE and issue diagnostics if necessary.
+    Return *_TYPE node upon success, NULL_TREE when the NAME is not
+    found, and ERROR_MARK_NODE for type error.  */
+ 
+ static tree
+ lookup_and_check_tag (enum tag_types tag_code, tree name,
+ 		      bool globalize, bool template_header_p)
+ {
+   tree t;
+   tree decl;
+   if (globalize)
+     decl = lookup_name (name, 2);
+   else
+     decl = lookup_type_scope (name);
+ 
+   if (decl && DECL_CLASS_TEMPLATE_P (decl))
+     decl = DECL_TEMPLATE_RESULT (decl);
+ 
+   if (decl && TREE_CODE (decl) == TYPE_DECL)
+     {
+       /* Two cases we need to consider when deciding if a class
+ 	 template is allowed as an elaborated type specifier:
+ 	 1. It is a self reference to its own class.
+ 	 2. It comes with a template header.
+ 
+ 	 For example:
+ 
+ 	   template <class T> class C {
+ 	     class C *c1;		// DECL_SELF_REFERENCE_P is true
+ 	     class D;
+ 	   };
+ 	   template <class U> class C; // template_header_p is true
+ 	   template <class T> class C<T>::D {
+ 	     class C *c2;		// DECL_SELF_REFERENCE_P is true
+ 	   };  */
+ 
+       t = check_elaborated_type_specifier (tag_code,
+ 					   decl,
+ 					   template_header_p
+ 					   | DECL_SELF_REFERENCE_P (decl));
+       return t;
+     }
+   else
+     return NULL_TREE;
+ }
+ 
  /* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
     Define the tag as a forward-reference if it is not defined.
  
*************** xref_tag (enum tag_types tag_code, tree 
*** 9089,9095 ****
  {
    enum tree_code code;
    tree t;
-   struct cp_binding_level *b = current_binding_level;
    tree context = NULL_TREE;
  
    timevar_push (TV_NAME_LOOKUP);
--- 9141,9146 ----
*************** xref_tag (enum tag_types tag_code, tree 
*** 9112,9201 ****
        gcc_unreachable ();
      }
  
!   if (! globalize)
!     {
!       /* If we know we are defining this tag, only look it up in
! 	 this scope and don't try to find it as a type.  */
!       t = lookup_tag (code, name, b, 1);
!     }
    else
!     {
!       tree decl = lookup_name (name, 2);
  
!       if (decl && DECL_CLASS_TEMPLATE_P (decl))
! 	decl = DECL_TEMPLATE_RESULT (decl);
  
!       if (decl && TREE_CODE (decl) == TYPE_DECL)
! 	{
! 	  /* Two cases we need to consider when deciding if a class
! 	     template is allowed as an elaborated type specifier:
! 	     1. It is a self reference to its own class.
! 	     2. It comes with a template header.
! 
! 	     For example:
! 
! 	       template <class T> class C {
! 		 class C *c1;		// DECL_SELF_REFERENCE_P is true
! 	 	 class D;
! 	       };
! 	       template <class U> class C; // template_header_p is true
! 	       template <class T> class C<T>::D {
! 		 class C *c2;		// DECL_SELF_REFERENCE_P is true
! 	       };  */
! 
! 	  t = check_elaborated_type_specifier (tag_code,
! 					       decl,
! 					       template_header_p
! 					       | DECL_SELF_REFERENCE_P (decl));
! 	  if (t == error_mark_node)
! 	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
! 	}
!       else
! 	t = NULL_TREE;
! 
!       if (t && current_class_type
! 	  && template_class_depth (current_class_type)
! 	  && template_header_p)
! 	{
! 	  /* Since GLOBALIZE is nonzero, we are not looking at a
! 	     definition of this tag.  Since, in addition, we are currently
! 	     processing a (member) template declaration of a template
! 	     class, we must be very careful; consider:
! 
! 	       template <class X>
! 	       struct S1
! 
! 	       template <class U>
! 	       struct S2
! 	       { template <class V>
! 	       friend struct S1; };
! 
! 	     Here, the S2::S1 declaration should not be confused with the
! 	     outer declaration.  In particular, the inner version should
! 	     have a template parameter of level 2, not level 1.  This
! 	     would be particularly important if the member declaration
! 	     were instead:
! 
! 	       template <class V = U> friend struct S1;
! 
! 	     say, when we should tsubst into `U' when instantiating
! 	     S2.  On the other hand, when presented with:
! 
! 	         template <class T>
! 	         struct S1 {
! 		   template <class U>
! 	           struct S2 {};
! 		   template <class U>
! 		   friend struct S2;
! 		 };
! 
!               we must find the inner binding eventually.  We
! 	      accomplish this by making sure that the new type we
! 	      create to represent this declaration has the right
! 	      TYPE_CONTEXT.  */
! 	  context = TYPE_CONTEXT (t);
! 	  t = NULL_TREE;
! 	}
      }
  
    if (! t)
--- 9163,9221 ----
        gcc_unreachable ();
      }
  
!   /* In case of anonymous name, xref_tag is only called to
!      make type node and push name.  Name lookup is not required.  */
!   if (ANON_AGGRNAME_P (name))
!     t = NULL_TREE;
    else
!     t = lookup_and_check_tag  (tag_code, name,
! 			       globalize, template_header_p);
  
!   if (t == error_mark_node)
!     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
  
!   if (globalize && t && current_class_type
!       && template_class_depth (current_class_type)
!       && template_header_p)
!     {
!       /* Since GLOBALIZE is nonzero, we are not looking at a
! 	 definition of this tag.  Since, in addition, we are currently
! 	 processing a (member) template declaration of a template
! 	 class, we must be very careful; consider:
! 
! 	   template <class X>
! 	   struct S1
! 
! 	   template <class U>
! 	   struct S2
! 	   { template <class V>
! 	   friend struct S1; };
! 
! 	 Here, the S2::S1 declaration should not be confused with the
! 	 outer declaration.  In particular, the inner version should
! 	 have a template parameter of level 2, not level 1.  This
! 	 would be particularly important if the member declaration
! 	 were instead:
! 
! 	   template <class V = U> friend struct S1;
! 
! 	 say, when we should tsubst into `U' when instantiating
! 	 S2.  On the other hand, when presented with:
! 
! 	   template <class T>
! 	   struct S1 {
! 	     template <class U>
! 	     struct S2 {};
! 	     template <class U>
! 	     friend struct S2;
! 	   };
! 
! 	 we must find the inner binding eventually.  We
! 	 accomplish this by making sure that the new type we
! 	 create to represent this declaration has the right
! 	 TYPE_CONTEXT.  */
!       context = TYPE_CONTEXT (t);
!       t = NULL_TREE;
      }
  
    if (! t)
*************** tree
*** 9442,9455 ****
  start_enum (tree name)
  {
    tree enumtype = NULL_TREE;
-   struct cp_binding_level *b = current_binding_level;
  
    /* If this is the real definition for a previous forward reference,
       fill in the contents in the same object that used to be the
       forward reference.  */
  
    if (name != NULL_TREE)
!     enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
  
    if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
      {
--- 9462,9474 ----
  start_enum (tree name)
  {
    tree enumtype = NULL_TREE;
  
    /* If this is the real definition for a previous forward reference,
       fill in the contents in the same object that used to be the
       forward reference.  */
  
    if (name != NULL_TREE)
!     enumtype = lookup_and_check_tag (enum_type, name, 0, 0);
  
    if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
      {
diff -cprN gcc-main-save/gcc/cp/name-lookup.c gcc-main-new/gcc/cp/name-lookup.c
*** gcc-main-save/gcc/cp/name-lookup.c	Tue Oct 12 22:48:26 2004
--- gcc-main-new/gcc/cp/name-lookup.c	Wed Oct 13 23:39:24 2004
*************** struct scope_binding {
*** 43,49 ****
  static cxx_scope *innermost_nonclass_level (void);
  static tree select_decl (const struct scope_binding *, int);
  static cxx_binding *binding_for_name (cxx_scope *, tree);
! static tree lookup_name_current_level (tree);
  static tree push_overloaded_decl (tree, int);
  static bool lookup_using_namespace (tree, struct scope_binding *, tree,
                                      tree, int);
--- 43,49 ----
  static cxx_scope *innermost_nonclass_level (void);
  static tree select_decl (const struct scope_binding *, int);
  static cxx_binding *binding_for_name (cxx_scope *, tree);
! static tree lookup_name_innermost_nonclass_level (tree);
  static tree push_overloaded_decl (tree, int);
  static bool lookup_using_namespace (tree, struct scope_binding *, tree,
                                      tree, int);
*************** pushdecl (tree x)
*** 678,684 ****
        if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
  	t = namespace_binding (name, DECL_CONTEXT (x));
        else
! 	t = lookup_name_current_level (name);
  
        /* [basic.link] If there is a visible declaration of an entity
  	 with linkage having the same name and type, ignoring entities
--- 678,684 ----
        if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
  	t = namespace_binding (name, DECL_CONTEXT (x));
        else
! 	t = lookup_name_innermost_nonclass_level (name);
  
        /* [basic.link] If there is a visible declaration of an entity
  	 with linkage having the same name and type, ignoring entities
*************** push_local_binding (tree id, tree decl, 
*** 1111,1117 ****
       push_local_binding with a friend decl of a local class.  */
    b = innermost_nonclass_level ();
  
!   if (lookup_name_current_level (id))
      {
        /* Supplement the existing binding.  */
        if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
--- 1111,1117 ----
       push_local_binding with a friend decl of a local class.  */
    b = innermost_nonclass_level ();
  
!   if (lookup_name_innermost_nonclass_level (id))
      {
        /* Supplement the existing binding.  */
        if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
*************** push_overloaded_decl (tree decl, int fla
*** 1998,2004 ****
    if (doing_global)
      old = namespace_binding (name, DECL_CONTEXT (decl));
    else
!     old = lookup_name_current_level (name);
  
    if (old)
      {
--- 1998,2004 ----
    if (doing_global)
      old = namespace_binding (name, DECL_CONTEXT (decl));
    else
!     old = lookup_name_innermost_nonclass_level (name);
  
    if (old)
      {
*************** do_local_using_decl (tree decl, tree sco
*** 2286,2292 ****
        && at_function_scope_p ())
      add_decl_expr (decl);
  
!   oldval = lookup_name_current_level (name);
    oldtype = lookup_type_current_level (name);
  
    do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
--- 2286,2292 ----
        && at_function_scope_p ())
      add_decl_expr (decl);
  
!   oldval = lookup_name_innermost_nonclass_level (name);
    oldtype = lookup_type_current_level (name);
  
    do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
*************** lookup_name (tree name, int prefer_type)
*** 4121,4131 ****
  			   0, LOOKUP_COMPLAIN);
  }
  
  /* Similar to `lookup_name' but look only in the innermost non-class
     binding level.  */
  
  static tree
! lookup_name_current_level (tree name)
  {
    struct cp_binding_level *b;
    tree t = NULL_TREE;
--- 4121,4210 ----
  			   0, LOOKUP_COMPLAIN);
  }
  
+ /* Look up NAME for type used in elaborated name specifier in
+    the current scope (possibly more if cleanup or template parameter
+    scope is encounter).  Unlike lookup_name_real, we make sure that
+    NAME is actually declared in the desired scope, not from inheritance,
+    using declaration, nor using directive.  A TYPE_DECL best matching
+    the NAME is returned.  Catching error and issuing diagnostics are
+    caller's responsibility.  */
+ 
+ tree
+ lookup_type_scope (tree name)
+ {
+   cxx_binding *iter = NULL;
+   tree val = NULL_TREE;
+ 
+   timevar_push (TV_NAME_LOOKUP);
+ 
+   /* Look in non-namespace scope first.  */
+   if (current_binding_level->kind != sk_namespace)
+     iter = outer_binding (name, NULL, /*class_p=*/ true);
+   for (; iter; iter = outer_binding (name, iter, /*class_p=*/ true))
+     {
+       /* Check if this is the kind of thing we're looking for.
+ 	 Make sure it doesn't come from base class.  For ITER->VALUE,
+ 	 we can simply use INHERITED_VALUE_BINDING_P.  For ITER->TYPE,
+ 	 we have to use our own check.
+ 
+ 	 We check ITER->TYPE before ITER->VALUE in order to handle
+ 	   typedef struct C {} C;
+ 	 correctly.  */
+ 
+       if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)
+ 	  && (LOCAL_BINDING_P (iter)
+ 	      || DECL_CONTEXT (iter->type) == iter->scope->this_entity))
+ 	val = iter->type;
+       else if (!INHERITED_VALUE_BINDING_P (iter)
+ 	       && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+ 	val = iter->value;
+ 
+       if (val)
+ 	break;
+     }
+ 
+   /* Look in namespace scope.  */
+   if (!val)
+     {
+       iter = cxx_scope_find_binding_for_name
+ 	       (NAMESPACE_LEVEL (current_decl_namespace ()), name);
+ 
+       if (iter)
+ 	{
+ 	  /* If this is the kind of thing we're looking for, we're done.  */
+ 	  if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
+ 	    val = iter->type;
+ 	  else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+ 	    val = iter->value;
+ 	}
+ 	
+     }
+ 
+   /* Type found, check if it is in the current scope, ignoring cleanup
+      and template parameter scopes.  */
+   if (val)
+     {
+       struct cp_binding_level *b = current_binding_level;
+       while (b)
+ 	{
+ 	  if (iter->scope == b)
+ 	    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ 
+ 	  if (b->kind == sk_cleanup || b->kind == sk_template_parms)
+ 	    b = b->level_chain;
+ 	  else
+ 	    break;
+ 	}
+     }
+ 
+   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
+ 
  /* Similar to `lookup_name' but look only in the innermost non-class
     binding level.  */
  
  static tree
! lookup_name_innermost_nonclass_level (tree name)
  {
    struct cp_binding_level *b;
    tree t = NULL_TREE;
*************** lookup_name_current_level (tree name)
*** 4163,4169 ****
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
  }
  
! /* Like lookup_name_current_level, but for types.  */
  
  static tree
  lookup_type_current_level (tree name)
--- 4242,4248 ----
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
  }
  
! /* Like lookup_name_innermost_nonclass_level, but for types.  */
  
  static tree
  lookup_type_current_level (tree name)
diff -cprN gcc-main-save/gcc/cp/name-lookup.h gcc-main-new/gcc/cp/name-lookup.h
*** gcc-main-save/gcc/cp/name-lookup.h	Fri Sep 24 18:53:13 2004
--- gcc-main-new/gcc/cp/name-lookup.h	Wed Oct 13 23:01:09 2004
*************** extern tree lookup_tag (enum tree_code, 
*** 303,308 ****
--- 303,309 ----
  extern tree lookup_tag_reverse (tree, tree);
  extern tree lookup_name	(tree, int);
  extern tree lookup_name_real (tree, int, int, bool, int, int);
+ extern tree lookup_type_scope (tree);
  extern tree namespace_binding (tree, tree);
  extern void set_namespace_binding (tree, tree, tree);
  extern tree lookup_namespace_name (tree, tree);
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/lookup/struct1.C gcc-main-new/gcc/testsuite/g++.dg/lookup/struct1.C
*** gcc-main-save/gcc/testsuite/g++.dg/lookup/struct1.C	Sat Sep 13 18:41:31 2003
--- gcc-main-new/gcc/testsuite/g++.dg/lookup/struct1.C	Wed Oct 13 23:01:10 2004
***************
*** 3,12 ****
  
  struct A;
  typedef struct A B;		// { dg-error "previous declaration" }
! struct B;			// { dg-error "conflicting declaration" }
  
  typedef struct { int i; } C;	// { dg-error "previous declaration" }
! struct C;			// { dg-error "conflicting declaration" }
  
  struct D;
  typedef struct D D;
--- 3,12 ----
  
  struct A;
  typedef struct A B;		// { dg-error "previous declaration" }
! struct B;			// { dg-error "using typedef-name" }
  
  typedef struct { int i; } C;	// { dg-error "previous declaration" }
! struct C;			// { dg-error "using typedef-name" }
  
  struct D;
  typedef struct D D;
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/elab1.C gcc-main-new/gcc/testsuite/g++.dg/parse/elab1.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/elab1.C	Wed Apr 23 04:05:58 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/elab1.C	Wed Oct 13 23:01:10 2004
***************
*** 1,6 ****
  namespace Name {
  
!     typedef void *(*Function)( void *, int );
  
      struct Foo {
        struct Function xyz[5]; // { dg-error "" }
--- 1,6 ----
  namespace Name {
  
!     typedef void *(*Function)( void *, int ); // { dg-error "previous declaration" }
  
      struct Foo {
        struct Function xyz[5]; // { dg-error "" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/elab2.C gcc-main-new/gcc/testsuite/g++.dg/parse/elab2.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/elab2.C	Wed Aug 20 14:06:46 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/elab2.C	Wed Oct 13 23:01:10 2004
*************** struct A {};
*** 2,7 ****
  
  struct B
  {
!   typedef A T;
    friend struct T; // { dg-error "" }
  };
--- 2,7 ----
  
  struct B
  {
!   typedef A T; // { dg-error "previous declaration" }
    friend struct T; // { dg-error "" }
  };
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/int-as-enum1.C gcc-main-new/gcc/testsuite/g++.dg/parse/int-as-enum1.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/int-as-enum1.C	Thu Jan 23 06:21:51 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/int-as-enum1.C	Wed Oct 13 23:01:10 2004
***************
*** 2,6 ****
  // Origin: <wanderer@rsu.ru>
  // { dg-do compile }
  
! typedef int A;
! enum ::A {}; // { dg-error "" }
--- 2,6 ----
  // Origin: <wanderer@rsu.ru>
  // { dg-do compile }
  
! typedef int A;	// { dg-error "previous" }
! enum ::A {};	// { dg-error "typedef-name|expected unqualified-id" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/struct-as-enum1.C gcc-main-new/gcc/testsuite/g++.dg/parse/struct-as-enum1.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/struct-as-enum1.C	Thu Jan 23 06:21:51 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/struct-as-enum1.C	Wed Oct 13 23:01:10 2004
***************
*** 4,10 ****
  
  namespace N
  {
!     struct A {};
  }
  
! typedef enum N::A B; // { dg-error "enum" }
--- 4,10 ----
  
  namespace N
  {
!     struct A {};	// { dg-error "previous declaration" }
  }
  
! typedef enum N::A B;	// { dg-error "enum" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/typedef1.C gcc-main-new/gcc/testsuite/g++.dg/parse/typedef1.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/typedef1.C	Sun Apr 27 19:11:00 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/typedef1.C	Wed Oct 13 23:01:10 2004
***************
*** 1,3 ****
  // PR c++/6477
! typedef struct A_ *A;
! typedef struct A B;	// { dg-error "" }
--- 1,3 ----
  // PR c++/6477
! typedef struct A_ *A;	// { dg-error "previous declaration" }
! typedef struct A B;	// { dg-error "typedef|invalid type" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/typedef3.C gcc-main-new/gcc/testsuite/g++.dg/parse/typedef3.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/typedef3.C	Tue Jul 22 17:54:14 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/typedef3.C	Wed Oct 13 23:01:10 2004
***************
*** 2,7 ****
  // Origin: Travis J.I. Corcoran <tjic@permabit.com>
  // { dg-do compile }
  
! struct A { typedef A* Ptr; };
  
! struct A::Ptr; // { dg-error "" }
--- 2,7 ----
  // Origin: Travis J.I. Corcoran <tjic@permabit.com>
  // { dg-do compile }
  
! struct A { typedef A* Ptr; };	// { dg-error "previous declaration" }
  
! struct A::Ptr;			// { dg-error "typedef|not declare anything" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/typedef4.C gcc-main-new/gcc/testsuite/g++.dg/parse/typedef4.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/typedef4.C	Fri Aug 22 19:47:57 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/typedef4.C	Wed Oct 13 23:01:10 2004
***************
*** 7,12 ****
  template<class T> class smart_ptr2 {
      T* real_ptr;
   public:
!     typedef typename T::subT  td;
!     friend class td; // { dg-error "typedef" }
  };
--- 7,12 ----
  template<class T> class smart_ptr2 {
      T* real_ptr;
   public:
!     typedef typename T::subT  td; // { dg-error "previous declaration" }
!     friend class td; // { dg-error "typedef|not name a class" }
  };
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/typedef5.C gcc-main-new/gcc/testsuite/g++.dg/parse/typedef5.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/typedef5.C	Wed Aug 13 05:26:25 2003
--- gcc-main-new/gcc/testsuite/g++.dg/parse/typedef5.C	Wed Oct 13 23:01:10 2004
***************
*** 1,6 ****
  namespace A
  {
!   typedef int T;
  }
  
! class A::T x; // { dg-error "" }
--- 1,6 ----
  namespace A
  {
!   typedef int T;	// { dg-error "previous declaration" }
  }
  
! class A::T x;		// { dg-error "using typedef-name" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/nontype4.C gcc-main-new/gcc/testsuite/g++.dg/template/nontype4.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/nontype4.C	Sun Jan 25 21:21:47 2004
--- gcc-main-new/gcc/testsuite/g++.dg/template/nontype4.C	Wed Oct 13 23:01:10 2004
***************
*** 7,14 ****
  
  template <int> struct A
  {
!     typedef A<0> B;		// { dg-error "not a valid type|conflict" }
!     template <B> struct B {};	// { dg-error "not a valid type|declaration" }
  };
  
! A<0> a;				// { dg-error "instantiated" }
--- 7,14 ----
  
  template <int> struct A
  {
!     typedef A<0> B;		// { dg-error "previous declaration" }
!     template <B> struct B {};	// { dg-error "not a valid type|typedef" }
  };
  
! A<0> a;
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C	Thu May  1 18:34:43 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C	Wed Oct 13 23:01:10 2004
*************** struct S {
*** 37,43 ****
    ~S();
  };
  
! typedef struct S T;
  
  S a = T();                      // OK 
  struct T * p;                   // { dg-error "" } using typedef after struct
--- 37,43 ----
    ~S();
  };
  
! typedef struct S T;		// { dg-error "previous declaration" }
  
  S a = T();                      // OK 
  struct T * p;                   // { dg-error "" } using typedef after struct
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.other/elab1.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.other/elab1.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.other/elab1.C	Thu May  1 18:35:16 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.other/elab1.C	Wed Oct 13 23:59:28 2004
***************
*** 1,5 ****
  // { dg-do assemble  }
! typedef struct {} S;
  
  S s1;
  struct S* s2; // { dg-error "" } S is a typedef name
--- 1,5 ----
  // { dg-do assemble  }
! typedef struct {} S; // { dg-error "" } Previous declaration of S
  
  S s1;
  struct S* s2; // { dg-error "" } S is a typedef name
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.other/syntax4.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.other/syntax4.C	Thu May  1 18:35:20 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.other/syntax4.C	Wed Oct 13 23:01:10 2004
*************** class X {
*** 17,23 ****
  
  class Y {
    public:
!   typedef ::X W;
    class Z;
  };
  
--- 17,23 ----
  
  class Y {
    public:
!   typedef ::X W;   // { dg-error "" } previous declaration
    class Z;
  };
  


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