Commit b5446d0c by Iain Buclaw

d: Fix SEGV in hash_table<odr_name_hasher, false, xcallocator>::find_slot_with_hash

This patch fixes LTO bug with the D front-end.  As DECL_ASSEMBLER_NAME
is set on the TYPE_DECL, so TYPE_CXX_ODR_P must also be set on the type.

The addition of merge_aggregate_types is not strictly needed now, but it
fixes a problem introduced in newer versions of the dmd front-end where
templated types could be sent more than once to the D code generator.

gcc/d/ChangeLog:

2020-03-20  Iain Buclaw  <ibuclaw@gdcproject.org>

	PR lto/91027
	* d-tree.h (struct GTY): Add daggregate field.
	(IDENTIFIER_DAGGREGATE): Define.
	(d_mangle_decl): Add declaration.
	* decl.cc (mangle_decl): Remove static linkage, rename to...
	(d_mangle_decl): ...this, update all callers.
	* types.cc (merge_aggregate_types): New function.
	(TypeVisitor::visit (TypeStruct *)): Call merge_aggregate_types, set
	IDENTIFIER_DAGGREGATE and TYPE_CXX_ODR_P.
	(TypeVisitor::visit (TypeClass *)): Likewise.
parent 1aa22b19
2020-03-20 Iain Buclaw <ibuclaw@gdcproject.org>
PR lto/91027
* d-tree.h (struct GTY): Add daggregate field.
(IDENTIFIER_DAGGREGATE): Define.
(d_mangle_decl): Add declaration.
* decl.cc (mangle_decl): Remove static linkage, rename to...
(d_mangle_decl): ...this, update all callers.
* types.cc (merge_aggregate_types): New function.
(TypeVisitor::visit (TypeStruct *)): Call merge_aggregate_types, set
IDENTIFIER_DAGGREGATE and TYPE_CXX_ODR_P.
(TypeVisitor::visit (TypeClass *)): Likewise.
2020-03-18 Jakub Jelinek <jakub@redhat.com> 2020-03-18 Jakub Jelinek <jakub@redhat.com>
* expr.cc (ExprVisitor::visit (CatAssignExp *)): Fix up duplicated * expr.cc (ExprVisitor::visit (CatAssignExp *)): Fix up duplicated
......
...@@ -204,6 +204,7 @@ struct GTY(()) lang_identifier ...@@ -204,6 +204,7 @@ struct GTY(()) lang_identifier
/* The frontend Declaration associated with this identifier. */ /* The frontend Declaration associated with this identifier. */
Declaration * GTY((skip)) dsymbol; Declaration * GTY((skip)) dsymbol;
AggregateDeclaration * GTY((skip)) daggregate;
}; };
#define IDENTIFIER_LANG_SPECIFIC(NODE) \ #define IDENTIFIER_LANG_SPECIFIC(NODE) \
...@@ -218,6 +219,9 @@ struct GTY(()) lang_identifier ...@@ -218,6 +219,9 @@ struct GTY(()) lang_identifier
#define IDENTIFIER_DSYMBOL(NODE) \ #define IDENTIFIER_DSYMBOL(NODE) \
(IDENTIFIER_LANG_SPECIFIC (NODE)->dsymbol) (IDENTIFIER_LANG_SPECIFIC (NODE)->dsymbol)
#define IDENTIFIER_DAGGREGATE(NODE) \
(IDENTIFIER_LANG_SPECIFIC (NODE)->daggregate)
/* Global state pertinent to the current function. */ /* Global state pertinent to the current function. */
struct GTY(()) language_function struct GTY(()) language_function
...@@ -600,6 +604,7 @@ extern tree d_signed_type (tree); ...@@ -600,6 +604,7 @@ extern tree d_signed_type (tree);
extern void d_keep (tree); extern void d_keep (tree);
/* In decl.cc. */ /* In decl.cc. */
extern const char *d_mangle_decl (Dsymbol *);
extern tree mangle_internal_decl (Dsymbol *, const char *, const char *); extern tree mangle_internal_decl (Dsymbol *, const char *, const char *);
extern void build_decl_tree (Dsymbol *); extern void build_decl_tree (Dsymbol *);
extern tree get_symbol_decl (Declaration *); extern tree get_symbol_decl (Declaration *);
......
...@@ -59,8 +59,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -59,8 +59,8 @@ along with GCC; see the file COPYING3. If not see
/* Return identifier for the external mangled name of DECL. */ /* Return identifier for the external mangled name of DECL. */
static const char * const char *
mangle_decl (Dsymbol *decl) d_mangle_decl (Dsymbol *decl)
{ {
if (decl->isFuncDeclaration ()) if (decl->isFuncDeclaration ())
return mangleExact ((FuncDeclaration *)decl); return mangleExact ((FuncDeclaration *)decl);
...@@ -78,7 +78,7 @@ mangle_decl (Dsymbol *decl) ...@@ -78,7 +78,7 @@ mangle_decl (Dsymbol *decl)
tree tree
mangle_internal_decl (Dsymbol *decl, const char *name, const char *suffix) mangle_internal_decl (Dsymbol *decl, const char *name, const char *suffix)
{ {
const char *prefix = mangle_decl (decl); const char *prefix = d_mangle_decl (decl);
unsigned namelen = strlen (name); unsigned namelen = strlen (name);
unsigned buflen = (2 + strlen (prefix) + namelen + strlen (suffix)) * 2; unsigned buflen = (2 + strlen (prefix) + namelen + strlen (suffix)) * 2;
char *buf = (char *) alloca (buflen); char *buf = (char *) alloca (buflen);
...@@ -1145,7 +1145,7 @@ get_symbol_decl (Declaration *decl) ...@@ -1145,7 +1145,7 @@ get_symbol_decl (Declaration *decl)
if (decl->mangleOverride) if (decl->mangleOverride)
mangled_name = get_identifier (decl->mangleOverride); mangled_name = get_identifier (decl->mangleOverride);
else else
mangled_name = get_identifier (mangle_decl (decl)); mangled_name = get_identifier (d_mangle_decl (decl));
mangled_name = targetm.mangle_decl_assembler_name (decl->csym, mangled_name = targetm.mangle_decl_assembler_name (decl->csym,
mangled_name); mangled_name);
...@@ -2333,7 +2333,7 @@ build_type_decl (tree type, Dsymbol *dsym) ...@@ -2333,7 +2333,7 @@ build_type_decl (tree type, Dsymbol *dsym)
tree decl = build_decl (make_location_t (dsym->loc), TYPE_DECL, tree decl = build_decl (make_location_t (dsym->loc), TYPE_DECL,
get_identifier (name), type); get_identifier (name), type);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (mangle_decl (dsym))); SET_DECL_ASSEMBLER_NAME (decl, get_identifier (d_mangle_decl (dsym)));
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
DECL_ARTIFICIAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1;
DECL_CONTEXT (decl) = d_decl_context (dsym); DECL_CONTEXT (decl) = d_decl_context (dsym);
......
...@@ -498,6 +498,40 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize, ...@@ -498,6 +498,40 @@ finish_aggregate_type (unsigned structsize, unsigned alignsize,
} }
} }
/* Returns true if the class or struct type TYPE has already been layed out by
the lowering of another front-end AST type. In which case, there will either
be a reuse of the back-end type, or a multiple definition error.
DECO is the uniquely mangled decoration for the type. */
static bool
merge_aggregate_types (Type *type, tree deco)
{
AggregateDeclaration *sym;
if (type->ty == Tstruct)
sym = ((TypeStruct *) type)->sym;
else if (type->ty == Tclass)
sym = ((TypeClass *) type)->sym;
else
gcc_unreachable ();
if (IDENTIFIER_DAGGREGATE (deco))
{
AggregateDeclaration *ad = IDENTIFIER_DAGGREGATE (deco);
/* There should never be a class/struct mismatch in mangled names. */
gcc_assert ((sym->isStructDeclaration () && ad->isStructDeclaration ())
|| (sym->isClassDeclaration () && ad->isClassDeclaration ()));
/* Non-templated variables shouldn't be defined twice. */
if (!sym->isInstantiated ())
ScopeDsymbol::multiplyDefined (sym->loc, sym, ad);
type->ctype = build_ctype (ad->type);
return true;
}
return false;
}
/* Implements the visitor interface to build the GCC trees of all /* Implements the visitor interface to build the GCC trees of all
Type AST classes emitted from the D Front-end, where CTYPE holds Type AST classes emitted from the D Front-end, where CTYPE holds
...@@ -857,12 +891,19 @@ public: ...@@ -857,12 +891,19 @@ public:
void visit (TypeStruct *t) void visit (TypeStruct *t)
{ {
/* Merge types in the back-end if the front-end did not itself do so. */
tree deco = get_identifier (d_mangle_decl (t->sym));
if (merge_aggregate_types (t, deco))
return;
/* Need to set this right away in case of self-references. */ /* Need to set this right away in case of self-references. */
t->ctype = make_node (t->sym->isUnionDeclaration () t->ctype = make_node (t->sym->isUnionDeclaration ()
? UNION_TYPE : RECORD_TYPE); ? UNION_TYPE : RECORD_TYPE);
d_keep (t->ctype); d_keep (t->ctype);
IDENTIFIER_DAGGREGATE (deco) = t->sym;
TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t); TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
TYPE_CXX_ODR_P (t->ctype) = 1;
if (t->sym->members) if (t->sym->members)
{ {
...@@ -903,17 +944,24 @@ public: ...@@ -903,17 +944,24 @@ public:
void visit (TypeClass *t) void visit (TypeClass *t)
{ {
/* Merge types in the back-end if the front-end did not itself do so. */
tree deco = get_identifier (d_mangle_decl (t->sym));
if (merge_aggregate_types (t, deco))
return;
/* Need to set ctype right away in case of self-references to /* Need to set ctype right away in case of self-references to
the type during this call. */ the type during this call. */
tree basetype = make_node (RECORD_TYPE); tree basetype = make_node (RECORD_TYPE);
t->ctype = build_pointer_type (basetype); t->ctype = build_pointer_type (basetype);
d_keep (t->ctype); d_keep (t->ctype);
IDENTIFIER_DAGGREGATE (deco) = t->sym;
/* Note that lang_specific data is assigned to both the reference /* Note that lang_specific data is assigned to both the reference
and the underlying record type. */ and the underlying record type. */
TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t); TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
TYPE_LANG_SPECIFIC (basetype) = TYPE_LANG_SPECIFIC (t->ctype); TYPE_LANG_SPECIFIC (basetype) = TYPE_LANG_SPECIFIC (t->ctype);
CLASS_TYPE_P (basetype) = 1; CLASS_TYPE_P (basetype) = 1;
TYPE_CXX_ODR_P (basetype) = 1;
/* Put out all fields, including from each base class. */ /* Put out all fields, including from each base class. */
layout_aggregate_type (t->sym, basetype, t->sym); layout_aggregate_type (t->sym, basetype, t->sym);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment