This is the mail archive of the gcc-bugs@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]

g++.law/operators24.C and --enable-checking=gcac


g++.law/operators24.C reads

#include <stddef.h>
struct Link {
  void* operator new(size_t, int);
  friend void* __builtin_new(size_t);
};
void f() { new(2) Link; }

With GC_ALWAYS_COLLECT defined, this crashes while marking trees.  The
crash comes from lang_mark_tree:

15055             if (CAN_HAVE_FULL_LANG_DECL_P (t))
15056               {
15057                 ggc_mark_tree (ld->befriending_classes);
15058                 ggc_mark_tree (ld->saved_tree);
15059                 ggc_mark_tree (ld->cloned_function);
15060                 if (!DECL_OVERLOADED_OPERATOR_P (t))
15061  * here *         ggc_mark_tree (ld->u2.vtt_parm);

During initialization, we set up a decl node for operator new.  It
looks something like this.

 <function_decl operator new
    type <function_type
        type <pointer_type type <void_type void> ...>
        ...
        arg-types <tree_list value <integer_type unsigned int>
            chain <tree_list unsigned value <void_type void>>>
        throws <tree_list value <record_type bad_alloc>>>
    public external QI file <internal> line 0
    rtl (mem:QI (symbol_ref:SI ("__builtin_new")) 0)>

DECL_OVERLOADED_OPERATOR_P is true for this decl; that is recorded in
one of the flags of the DECL_NAME.  The lang_decl structure reads in
part

$14 = {decl_flags = { ... },
    befriending_classes = 0x0, saved_tree = 0x0, cloned_function = 0x0, 
    u = { sorted_fields = 0x0, ... }, 
    u2 = {operator_code = NEW_EXPR, vtt_parm = 0x93}}

Note that this decl has nothing to do with the local decl of operator
new in struct Link.  When we reach the declaration of __builtin_new,
we construct a decl node for that, and call pushdecl.  That node looks
like this:

<function_decl __builtin_new
    type <function_type
        type <pointer_type type <void_type void> ...>
        ...
        arg-types <tree_list value <integer_type unsigned int>
            chain <tree_list value <void_type void>>>>
    public external QI operators24.C line 12
    arguments <parm_decl
        type <integer_type size_t>
        ...>
    >

The DECL_ASSEMBLER_NAME of this decl is __builtin_new.  The
DECL_ASSEMBLER_NAME of the original decl of operator new is also
__builtin_new.  pushdecl therefore calls duplicate_decls (indirectly).
duplicate_decls decides that the two decls are almost the same, and
clobbers the original decl with the new one.  It does *not* change the
lang_decl when it does that.  We are therefore left with a function_decl
whose DECL_NAME does not have the OVERLOADED_OPERATOR_P flag set, but 
whose lang_decl does have an operator code.  lang_mark_tree tries to
dereference 0x93 and crashes.

I do not know the appropriate fix.  It seems to me that pushdecl
should not consider the user's declaration of __builtin_new to have
anything to do with the automatic default declaration of operator
new.  But that might have other undesirable effects.  Failing that,
perhaps duplicate_decls should notice that one of these has
DECL_OVERLOADED_OPERATOR_P and one doesn't, and not regard them as
almost the same.

zw


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