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]

(C++) Patch to elaborated-type-specifier handling


This patch:

  1) Generates a diagnostic for 'friend T' where T is looked up to be an
     implicit typename.
  2) Generates a warning for 'friend struct T', since the user probably
     wanted the inherited type, not some global type.
  3) Causes 'struct B::T' where B is the current (template) class
     to generate a TYPENAME_TYPE, as per core issue 180, so that
     'friend struct B::T' is well-formed.

Test in g++.pt/inherit2.C.

2000-09-12  Jason Merrill  <jason@redhat.com>

	* decl.c (grokdeclarator): Complain about 'friend T' for implicit
	typenames, too.  Downgrade complaint to pedwarn.
	(xref_tag): Warn about surprising behavior of 'friend struct T'.
	* decl2.c (handle_class_head): Generate a TYPENAME_TYPE for
	'class This::Inherited'.

Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.688
diff -c -p -r1.688 decl.c
*** decl.c	2000/09/11 01:50:48	1.688
--- decl.c	2000/09/13 00:49:15
*************** grokdeclarator (declarator, declspecs, d
*** 11411,11422 ****
  	      cp_error ("`inline' specified for friend class declaration");
  	      inlinep = 0;
  	    }
! 	  if (!current_aggr && TREE_CODE (type) != TYPENAME_TYPE)
  	    {
  	      if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
! 	        cp_error ("template parameters cannot be friends");
  	      else
! 	        cp_error ("friend declaration requires `%#T'", type);
  	    }
  
  	  /* Only try to do this stuff if we didn't already give up.  */
--- 11408,11430 ----
  	      cp_error ("`inline' specified for friend class declaration");
  	      inlinep = 0;
  	    }
! 
! 	  /* Until core issue 180 is resolved, allow 'friend typename A::B'.
! 	     But don't allow implicit typenames.  */
! 	  if (!current_aggr && (TREE_CODE (type) != TYPENAME_TYPE
! 				|| IMPLICIT_TYPENAME_P (type)))
  	    {
  	      if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
! 	        cp_pedwarn ("template parameters cannot be friends");
! 	      else if (TREE_CODE (type) == TYPENAME_TYPE)
! 	        cp_pedwarn ("\
! friend declaration requires class-key, i.e. `friend class %T::%T'",
! 			    constructor_name (current_class_type),
! 			    TYPE_IDENTIFIER (type));
  	      else
! 	        cp_pedwarn ("\
! friend declaration requires class-key, i.e. `friend %#T'",
! 			    type);
  	    }
  
  	  /* Only try to do this stuff if we didn't already give up.  */
*************** xref_tag (code_type_node, name, globaliz
*** 12925,12930 ****
--- 12933,12954 ----
      }
    else
      t = IDENTIFIER_TYPE_VALUE (name);
+ 
+   /* Warn about 'friend struct Inherited;' doing the wrong thing.  */
+   if (t && globalize && TREE_CODE (t) == TYPENAME_TYPE)
+     {
+       static int explained;
+ 
+       cp_warning ("`%s %T' declares a new type at namespace scope;\n\
+ to refer to the inherited type, say `%s %T::%T'%s",
+ 		  tag_name (tag_code), name, tag_name (tag_code),
+ 		  constructor_name (current_class_type), TYPE_IDENTIFIER (t),
+ 		  (!explained ? "\n\
+ (names from dependent base classes are not visible to unqualified name lookup)"
+ 		   : ""));
+ 
+       explained = 1;
+     }
  
    if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
        && TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.395
diff -c -p -r1.395 decl2.c
*** decl2.c	2000/09/10 21:34:40	1.395
--- decl2.c	2000/09/13 00:49:17
*************** tree
*** 5436,5442 ****
  handle_class_head (aggr, scope, id)
       tree aggr, scope, id;
  {
!   tree decl;
  
    if (TREE_CODE (id) == TYPE_DECL)
      /* We must bash typedefs back to the main decl of the type. Otherwise
--- 5436,5442 ----
  handle_class_head (aggr, scope, id)
       tree aggr, scope, id;
  {
!   tree decl = NULL_TREE;
  
    if (TREE_CODE (id) == TYPE_DECL)
      /* We must bash typedefs back to the main decl of the type. Otherwise
*************** handle_class_head (aggr, scope, id)
*** 5446,5452 ****
      decl = DECL_TEMPLATE_RESULT (id);
    else 
      {
!       tree current = current_scope();
    
        if (current == NULL_TREE)
          current = current_namespace;
--- 5446,5452 ----
      decl = DECL_TEMPLATE_RESULT (id);
    else 
      {
!       tree current = current_scope ();
    
        if (current == NULL_TREE)
          current = current_namespace;
*************** handle_class_head (aggr, scope, id)
*** 5454,5460 ****
          scope = global_namespace;
        if (scope == NULL_TREE)
          scope = global_namespace;
!       if (scope == current)
          {
            /* We've been given AGGR SCOPE::ID, when we're already inside SCOPE.
               Be nice about it.  */
--- 5454,5470 ----
          scope = global_namespace;
        if (scope == NULL_TREE)
          scope = global_namespace;
! 
!       if (TYPE_P (scope))
! 	{
! 	  /* According to the suggested resolution of core issue 180,
! 	     'typename' is assumed after a class-key.  */
! 	  decl = make_typename_type (scope, id, 1);
! 	  if (decl == error_mark_node)
! 	    return error_mark_node;
! 	  decl = TYPE_MAIN_DECL (decl);
! 	}
!       else if (scope == current)
          {
            /* We've been given AGGR SCOPE::ID, when we're already inside SCOPE.
               Be nice about it.  */
*************** handle_class_head (aggr, scope, id)
*** 5468,5474 ****
  	cp_error ("no file-scope type named `%D'", id);
        
        /* Inject it at the current scope.  */
!       decl = TYPE_MAIN_DECL (xref_tag (aggr, id, 1));
      }
   
    /* Enter the SCOPE.  If this turns out not to be a definition, the
--- 5478,5485 ----
  	cp_error ("no file-scope type named `%D'", id);
        
        /* Inject it at the current scope.  */
!       if (!decl)
! 	decl = TYPE_MAIN_DECL (xref_tag (aggr, id, 1));
      }
   
    /* Enter the SCOPE.  If this turns out not to be a definition, the

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