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