C++ PATCH: extern "C" structs

Mark Mitchell mark@codesourcery.com
Tue Apr 18 13:23:00 GMT 2000


This patch fixes a crash on a struct declared in an extern "C" clause.

The cause, indirectly, was that DECL_DESTRUCTOR_P was implemented in a
complicated way involving running `strcmp' on the mangled name of the
function.  That's requires an unncessary breach of the abstraction
layer between C++ and name-mangling, plus it's slow.  Fixed thus.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-04-18  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (lang_decl_flags): Remove const_memfunc and
	volatile_memfunc.  Add destructor_attr.  Adjust dummy.
	(DECL_DESTRUCTOR_P): Use destructor_attr.
	(DECL_CONST_MEMFUNC_P): Reimplement.
	(DECL_VOLATILE_MEMFUNC_P): Remove.
	* class.c (finish_struct_methods): Use CLASSTYPE_DESTRUCTORS.
	(overrides): Use DECL_DESTRUCTOR_P.
	(check_for_override): Likewise.
	* decl.c (start_function): Likewise.
	* decl2.c (grokfclassfn): Likewise.
	(check_classfn): Likewise.
	(grok_function_init): Likewise.

Index: testsuite/g++.old-deja/g++.other/externC1.C
===================================================================
RCS file: externC1.C
diff -N externC1.C
*** /dev/null	Tue May  5 13:32:27 1998
--- externC1.C	Tue Apr 18 13:16:04 2000
***************
*** 0 ****
--- 1,22 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mitchell@codesourcery.com>
+ 
+ extern "C"
+ {
+   struct T
+   {
+     ~T ();
+   };
+ 
+   struct S
+   {
+     T t;
+   };
+ }
+ 
+ S* s;
+ 
+ void f ()
+ {
+   delete s;
+ }
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.294
diff -c -p -r1.294 class.c
*** class.c	2000/04/17 04:03:48	1.294
--- class.c	2000/04/18 20:16:08
*************** finish_struct_methods (t)
*** 2155,2161 ****
      /* Clear out this flag.  */
      DECL_IN_AGGR_P (fn_fields) = 0;
  
!   if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
      /* We thought there was a destructor, but there wasn't.  Some
         parse errors cause this anomalous situation.  */
      TYPE_HAS_DESTRUCTOR (t) = 0;
--- 2155,2161 ----
      /* Clear out this flag.  */
      DECL_IN_AGGR_P (fn_fields) = 0;
  
!   if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t))
      /* We thought there was a destructor, but there wasn't.  Some
         parse errors cause this anomalous situation.  */
      TYPE_HAS_DESTRUCTOR (t) = 0;
*************** overrides (fndecl, base_fndecl)
*** 2285,2295 ****
       tree fndecl, base_fndecl;
  {
    /* Destructors have special names.  */
!   if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
!       && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
      return 1;
!   if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
!       || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
      return 0;
    if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
      {
--- 2285,2293 ----
       tree fndecl, base_fndecl;
  {
    /* Destructors have special names.  */
!   if (DECL_DESTRUCTOR_P (base_fndecl) && DECL_DESTRUCTOR_P (fndecl))
      return 1;
!   if (DECL_DESTRUCTOR_P (base_fndecl) || DECL_DESTRUCTOR_P (fndecl))
      return 0;
    if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
      {
*************** check_for_override (decl, ctype)
*** 2744,2751 ****
        if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
  	{
  	  tree tmp = get_matching_virtual
! 	    (base_binfo, decl,
! 	     DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
  
  	  if (tmp && !found_overriden_fn)
  	    {
--- 2742,2748 ----
        if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
  	{
  	  tree tmp = get_matching_virtual
! 	    (base_binfo, decl, DECL_DESTRUCTOR_P (decl));
  
  	  if (tmp && !found_overriden_fn)
  	    {
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.443
diff -c -p -r1.443 cp-tree.h
*** cp-tree.h	2000/04/16 19:45:32	1.443
--- cp-tree.h	2000/04/18 20:16:12
*************** struct lang_decl_flags
*** 1861,1872 ****
  
    unsigned operator_attr : 1;
    unsigned constructor_attr : 1;
    unsigned friend_attr : 1;
    unsigned static_function : 1;
-   unsigned const_memfunc : 1;
-   unsigned volatile_memfunc : 1;
    unsigned pure_virtual : 1;
    unsigned has_in_charge_parm_p : 1;
  
    unsigned mutable_flag : 1;
    unsigned deferred : 1;
--- 1861,1872 ----
  
    unsigned operator_attr : 1;
    unsigned constructor_attr : 1;
+   unsigned destructor_attr : 1;
    unsigned friend_attr : 1;
    unsigned static_function : 1;
    unsigned pure_virtual : 1;
    unsigned has_in_charge_parm_p : 1;
+   unsigned pretty_function_p : 1;
  
    unsigned mutable_flag : 1;
    unsigned deferred : 1;
*************** struct lang_decl_flags
*** 1881,1888 ****
    unsigned pending_inline_p : 1;
    unsigned global_ctor_p : 1;
    unsigned global_dtor_p : 1;
!   unsigned pretty_function_p : 1;
!   unsigned dummy : 2;
  
    tree context;
  
--- 1881,1887 ----
    unsigned pending_inline_p : 1;
    unsigned global_ctor_p : 1;
    unsigned global_dtor_p : 1;
!   unsigned dummy : 3;
  
    tree context;
  
*************** struct lang_decl
*** 1969,1976 ****
  /* There ought to be a better way to find out whether or not something is
     a destructor.  */
  #define DECL_DESTRUCTOR_P(NODE)				\
!   (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE))	\
!    && DECL_LANGUAGE (NODE) == lang_cplusplus)
  
  /* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the
     specialized in-charge constructor, in-charge deleting constructor,
--- 1968,1974 ----
  /* There ought to be a better way to find out whether or not something is
     a destructor.  */
  #define DECL_DESTRUCTOR_P(NODE)				\
!   (DECL_LANG_SPECIFIC (NODE)->decl_flags.destructor_attr)
  
  /* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the
     specialized in-charge constructor, in-charge deleting constructor,
*************** struct lang_decl
*** 2078,2088 ****
  
  /* Nonzero for FUNCTION_DECL means that this member function
     has `this' as const X *const.  */
! #define DECL_CONST_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.const_memfunc)
! 
! /* Nonzero for FUNCTION_DECL means that this member function
!    has `this' as volatile X *const.  */
! #define DECL_VOLATILE_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.volatile_memfunc)
  
  /* Nonzero for a DECL means that this member is a non-static member.  */
  #define DECL_NONSTATIC_MEMBER_P(NODE) 		\
--- 2076,2085 ----
  
  /* Nonzero for FUNCTION_DECL means that this member function
     has `this' as const X *const.  */
! #define DECL_CONST_MEMFUNC_P(NODE)					 \
!   (DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)				 \
!    && CP_TYPE_CONST_P (TREE_TYPE (TREE_VALUE 				 \
! 				  (TYPE_ARG_TYPES (TREE_TYPE (NODE))))))
  
  /* Nonzero for a DECL means that this member is a non-static member.  */
  #define DECL_NONSTATIC_MEMBER_P(NODE) 		\
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.592
diff -c -p -r1.592 decl.c
*** decl.c	2000/04/17 02:00:23	1.592
--- decl.c	2000/04/18 20:16:20
*************** start_function (declspecs, declarator, a
*** 13551,13558 ****
  
    ++function_depth;
  
!   if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
!       && DECL_LANGUAGE (decl1) == lang_cplusplus)
      {
        dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
        DECL_CONTEXT (dtor_label) = current_function_decl;
--- 13551,13557 ----
  
    ++function_depth;
  
!   if (DECL_DESTRUCTOR_P (decl1))
      {
        dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
        DECL_CONTEXT (dtor_label) = current_function_decl;
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.335
diff -c -p -r1.335 decl2.c
*** decl2.c	2000/04/18 01:30:21	1.335
--- decl2.c	2000/04/18 20:16:24
*************** grokclassfn (ctype, function, flags, qua
*** 1037,1042 ****
--- 1037,1043 ----
  
    if (flags == DTOR_FLAG)
      {
+       DECL_DESTRUCTOR_P (function) = 1;
        DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
        TYPE_HAS_DESTRUCTOR (ctype) = 1;
      }
*************** check_classfn (ctype, function)
*** 1389,1395 ****
  	  && DECL_CONSTRUCTOR_P (function))
  	goto got_it;
        if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
! 	  && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
  	goto got_it;
  
        while (++methods != end && *methods)
--- 1390,1396 ----
  	  && DECL_CONSTRUCTOR_P (function))
  	goto got_it;
        if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
! 	  && DECL_DESTRUCTOR_P (function))
  	goto got_it;
  
        while (++methods != end && *methods)
*************** check_classfn (ctype, function)
*** 1410,1416 ****
  		     we can't use this short-cut for them, either.
  		     (It's not legal to declare arguments for a
  		     destructor, but some people try.)  */
! 		  if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
  		      && (DECL_ASSEMBLER_NAME (function)
  			  != DECL_NAME (function))
  		      && (DECL_ASSEMBLER_NAME (fndecl)
--- 1411,1417 ----
  		     we can't use this short-cut for them, either.
  		     (It's not legal to declare arguments for a
  		     destructor, but some people try.)  */
! 		  if (!DECL_DESTRUCTOR_P (function)
  		      && (DECL_ASSEMBLER_NAME (function)
  			  != DECL_NAME (function))
  		      && (DECL_ASSEMBLER_NAME (fndecl)
*************** grok_function_init (decl, init)
*** 1909,1915 ****
        /* pure virtual destructors must be defined.  */
        /* pure virtual needs to be defined (as abort) only when put in 
  	 vtbl. For wellformed call, it should be itself. pr4737 */
!       if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
  	{
  	  /* Give this node rtl from `abort'.  */
  	  DECL_RTL (decl) = DECL_RTL (abort_fndecl);
--- 1910,1916 ----
        /* pure virtual destructors must be defined.  */
        /* pure virtual needs to be defined (as abort) only when put in 
  	 vtbl. For wellformed call, it should be itself. pr4737 */
!       if (!DECL_DESTRUCTOR_P (decl)))
  	{
  	  /* Give this node rtl from `abort'.  */
  	  DECL_RTL (decl) = DECL_RTL (abort_fndecl);


More information about the Gcc-patches mailing list