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: Diagnose use of unnamed classes in extern fns


We were letting things like $_1 into public mangled names in some cases,
because we were being fooled by typedef TYPE_NAMEs.  This patch fixes that.

Applied to trunk and branch, as this is an ABI issue, and is inconsistent
with 2.95, which used the typedef name for mangling.

Tested on i686-pc-linux-gnu.

2001-04-11  Jason Merrill  <jason_merrill@redhat.com>

	* cp-tree.h (TYPE_LINKAGE_IDENTIFIER): New macro.
	(TYPE_ANONYMOUS_P): New macro.
	(TAGGED_TYPE_P): New macro.
	* decl.c (check_tag_decl): Use TYPE_ANONYMOUS_P.
	(grokfndecl, grokvardecl, grokdeclarator): Likewise.
	* tree.c (no_linkage_helper): Likewise.
	* semantics.c (begin_class_definition): Likewise.
	* pt.c (convert_template_argument): Likewise.
	* lex.c (check_for_missing_semicolon): Likewise.

*** cp-tree.h.~1~	Wed Apr 11 11:24:50 2001
--- cp-tree.h	Tue Apr 10 16:55:49 2001
*************** enum languages { lang_c, lang_cplusplus,
*** 1163,1174 ****
--- 1163,1180 ----
  
  /* Macros to make error reporting functions' lives easier.  */
  #define TYPE_IDENTIFIER(NODE) (DECL_NAME (TYPE_NAME (NODE)))
+ #define TYPE_LINKAGE_IDENTIFIER(NODE) \
+   (TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (NODE)))
  #define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE)))
  #define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE)))
  
  #define TYPE_ASSEMBLER_NAME_STRING(NODE) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME  (NODE))))
  #define TYPE_ASSEMBLER_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (TYPE_NAME (NODE))))
  
+ /* Nonzero if NODE has no name for linkage purposes.  */
+ #define TYPE_ANONYMOUS_P(NODE) \
+   (TAGGED_TYPE_P (NODE) && ANON_AGGRNAME_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
+ 
  /* The _DECL for this _TYPE.  */
  #define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
  
*************** enum languages { lang_c, lang_cplusplus,
*** 1198,1205 ****
  #define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
    (TREE_CODE (TYPE1) == TREE_CODE (TYPE2)	\
     && IS_AGGR_TYPE (TYPE1) && IS_AGGR_TYPE (TYPE2))
! #define IS_OVERLOAD_TYPE(t) \
!   (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
  
  /* In a *_TYPE, nonzero means a built-in type.  */
  #define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6(NODE)
--- 1204,1212 ----
  #define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
    (TREE_CODE (TYPE1) == TREE_CODE (TYPE2)	\
     && IS_AGGR_TYPE (TYPE1) && IS_AGGR_TYPE (TYPE2))
! #define TAGGED_TYPE_P(t) \
!   (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE)
! #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T)
  
  /* In a *_TYPE, nonzero means a built-in type.  */
  #define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6(NODE)
*** decl.c.~1~	Wed Apr 11 11:24:50 2001
--- decl.c	Wed Apr 11 11:50:13 2001
*************** pushtag (name, type, globalize)
*** 2873,2878 ****
--- 2873,2879 ----
  	  else
  	    d = pushdecl_with_scope (d, b);
  
+ 	  /* FIXME what if it gets a name from typedef?  */
  	  if (ANON_AGGRNAME_P (name))
  	    DECL_IGNORED_P (d) = 1;
  
*************** check_tag_decl (declspecs)
*** 6972,6983 ****
    if (t == NULL_TREE && ! saw_friend)
      pedwarn ("declaration does not declare anything");
  
!   /* Check for an anonymous union.  We're careful
!      accessing TYPE_IDENTIFIER because some built-in types, like
!      pointer-to-member types, do not have TYPE_NAME.  */
    else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t))
! 	   && TYPE_NAME (t)
! 	   && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
      {
        /* 7/3 In a simple-declaration, the optional init-declarator-list
           can be omitted only when declaring a class (clause 9) or
--- 6973,6981 ----
    if (t == NULL_TREE && ! saw_friend)
      pedwarn ("declaration does not declare anything");
  
!   /* Check for an anonymous union.  */
    else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t))
! 	   && TYPE_ANONYMOUS_P (t))
      {
        /* 7/3 In a simple-declaration, the optional init-declarator-list
           can be omitted only when declaring a class (clause 9) or
*************** grokfndecl (ctype, type, declarator, ori
*** 8733,8749 ****
       int check, friendp, publicp, inlinep, funcdef_flag, template_count;
       tree in_namespace;
  {
!   tree cname, decl;
    int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
    int has_default_arg = 0;
    tree t;
  
-   if (ctype)
-     cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
-       ? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype);
-   else
-     cname = NULL_TREE;
- 
    if (raises)
      {
        type = build_exception_variant (type, raises);
--- 8731,8741 ----
       int check, friendp, publicp, inlinep, funcdef_flag, template_count;
       tree in_namespace;
  {
!   tree decl;
    int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
    int has_default_arg = 0;
    tree t;
  
    if (raises)
      {
        type = build_exception_variant (type, raises);
*************** grokfndecl (ctype, type, declarator, ori
*** 8799,8805 ****
  
    /* Members of anonymous types and local classes have no linkage; make
       them internal.  */
!   if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
  		|| decl_function_context (TYPE_MAIN_DECL (ctype))))
      publicp = 0;
  
--- 8791,8798 ----
  
    /* Members of anonymous types and local classes have no linkage; make
       them internal.  */
!   /* FIXME what if it gets a name from typedef?  */
!   if (ctype && (TYPE_ANONYMOUS_P (ctype)
  		|| decl_function_context (TYPE_MAIN_DECL (ctype))))
      publicp = 0;
  
*************** grokfndecl (ctype, type, declarator, ori
*** 8813,8825 ****
        t = no_linkage_check (TREE_TYPE (decl));
        if (t)
  	{
! 	  if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
  	    {
  	      if (DECL_EXTERN_C_P (decl))
  		/* Allow this; it's pretty common in C.  */;
  	      else
! 		cp_pedwarn ("non-local function `%#D' uses anonymous type",
! 			    decl);
  	    }
  	  else
  	    cp_pedwarn ("non-local function `%#D' uses local type `%T'",
--- 8806,8824 ----
        t = no_linkage_check (TREE_TYPE (decl));
        if (t)
  	{
! 	  if (TYPE_ANONYMOUS_P (t))
  	    {
  	      if (DECL_EXTERN_C_P (decl))
  		/* Allow this; it's pretty common in C.  */;
  	      else
! 		{
! 		  cp_pedwarn ("non-local function `%#D' uses anonymous type",
! 			      decl);
! 		  if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
! 		    cp_pedwarn_at ("\
! `%#D' does not refer to the unqualified type, so it is not used for linkage",
! 				TYPE_NAME (t));
! 		}
  	    }
  	  else
  	    cp_pedwarn ("non-local function `%#D' uses local type `%T'",
*************** grokfndecl (ctype, type, declarator, ori
*** 8931,8937 ****
    if (check < 0)
      return decl;
  
!   if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
      DECL_CONSTRUCTOR_P (decl) = 1;
  
    /* Function gets the ugly name, field gets the nice one.  This call
--- 8930,8936 ----
    if (check < 0)
      return decl;
  
!   if (flags == NO_SPECIAL && ctype && constructor_name (ctype) == declarator)
      DECL_CONSTRUCTOR_P (decl) = 1;
  
    /* Function gets the ugly name, field gets the nice one.  This call
*************** grokvardecl (type, declarator, specbits_
*** 9095,9101 ****
        tree t = no_linkage_check (TREE_TYPE (decl));
        if (t)
  	{
! 	  if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
  	    /* Ignore for now; `enum { foo } e' is pretty common.  */;
  	  else
  	    cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
--- 9094,9100 ----
        tree t = no_linkage_check (TREE_TYPE (decl));
        if (t)
  	{
! 	  if (TYPE_ANONYMOUS_P (t))
  	    /* Ignore for now; `enum { foo } e' is pretty common.  */;
  	  else
  	    cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
*************** grokdeclarator (declarator, declspecs, d
*** 11037,11043 ****
  	  && declarator
  	  && TYPE_NAME (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
! 	  && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))
  	  && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED)
  	{
  	  tree oldname = TYPE_NAME (type);
--- 11036,11042 ----
  	  && declarator
  	  && TYPE_NAME (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
! 	  && TYPE_ANONYMOUS_P (type)
  	  && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED)
  	{
  	  tree oldname = TYPE_NAME (type);
*** lex.c.~1~	Wed Apr 11 11:24:50 2001
--- lex.c	Mon Apr  9 18:00:36 2001
*************** check_for_missing_semicolon (type)
*** 1011,1017 ****
         && yychar != SELFNAME)
        || yychar == 0  /* EOF */)
      {
!       if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
  	error ("semicolon missing after %s declaration",
  	       TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
        else
--- 1011,1017 ----
         && yychar != SELFNAME)
        || yychar == 0  /* EOF */)
      {
!       if (TYPE_ANONYMOUS_P (type))
  	error ("semicolon missing after %s declaration",
  	       TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
        else
*** pt.c.~1~	Wed Apr 11 11:24:50 2001
--- pt.c	Mon Apr  9 18:00:00 2001
*************** convert_template_argument (parm, arg, ar
*** 3389,3395 ****
  	      tree t = no_linkage_check (val);
  	      if (t)
  		{
! 		  if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
  		    cp_pedwarn
  		      ("template-argument `%T' uses anonymous type", val);
  		  else
--- 3389,3395 ----
  	      tree t = no_linkage_check (val);
  	      if (t)
  		{
! 		  if (TYPE_ANONYMOUS_P (t))
  		    cp_pedwarn
  		      ("template-argument `%T' uses anonymous type", val);
  		  else
*** semantics.c.~1~	Wed Apr 11 11:24:50 2001
--- semantics.c	Mon Apr  9 17:59:43 2001
*************** begin_class_definition (t)
*** 1859,1874 ****
    /* Reset the interface data, at the earliest possible
       moment, as it might have been set via a class foo;
       before.  */
!   {
!     tree name = TYPE_IDENTIFIER (t);
!     
!     if (! ANON_AGGRNAME_P (name))
!       {
! 	CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
! 	SET_CLASSTYPE_INTERFACE_UNKNOWN_X
! 	  (t, interface_unknown);
!       }
!   }
    reset_specialization();
    
    /* Make a declaration for this class in its own scope.  */
--- 1859,1870 ----
    /* Reset the interface data, at the earliest possible
       moment, as it might have been set via a class foo;
       before.  */
!   if (! TYPE_ANONYMOUS_P (t))
!     {
!       CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
!       SET_CLASSTYPE_INTERFACE_UNKNOWN_X
! 	(t, interface_unknown);
!     }
    reset_specialization();
    
    /* Make a declaration for this class in its own scope.  */
*** tree.c.~1~	Wed Apr 11 11:24:51 2001
--- tree.c	Tue Apr 10 00:15:33 2001
*************** no_linkage_helper (tp, walk_subtrees, da
*** 1502,1508 ****
    if (TYPE_P (t)
        && (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE)
        && (decl_function_context (TYPE_MAIN_DECL (t))
! 	  || ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
      return t;
    return NULL_TREE;
  }
--- 1502,1508 ----
    if (TYPE_P (t)
        && (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE)
        && (decl_function_context (TYPE_MAIN_DECL (t))
! 	  || TYPE_ANONYMOUS_P (t)))
      return t;
    return NULL_TREE;
  }
// Test that we properly diagnose an attempt to use an anonymous class
// in declaring an external function.

typedef const struct { int i; } T; // ERROR - referenced below
void f (T* t);			// ERROR - uses unnamed type

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