+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>
* expr.cc (ExprVisitor::visit (CatAssignExp *)): Fix up duplicated
/* The frontend Declaration associated with this identifier. */
Declaration * GTY((skip)) dsymbol;
+ AggregateDeclaration * GTY((skip)) daggregate;
};
#define IDENTIFIER_LANG_SPECIFIC(NODE) \
#define IDENTIFIER_DSYMBOL(NODE) \
(IDENTIFIER_LANG_SPECIFIC (NODE)->dsymbol)
+#define IDENTIFIER_DAGGREGATE(NODE) \
+ (IDENTIFIER_LANG_SPECIFIC (NODE)->daggregate)
+
/* Global state pertinent to the current function. */
struct GTY(()) language_function
extern void d_keep (tree);
/* In decl.cc. */
+extern const char *d_mangle_decl (Dsymbol *);
extern tree mangle_internal_decl (Dsymbol *, const char *, const char *);
extern void build_decl_tree (Dsymbol *);
extern tree get_symbol_decl (Declaration *);
/* Return identifier for the external mangled name of DECL. */
-static const char *
-mangle_decl (Dsymbol *decl)
+const char *
+d_mangle_decl (Dsymbol *decl)
{
if (decl->isFuncDeclaration ())
return mangleExact ((FuncDeclaration *)decl);
tree
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 buflen = (2 + strlen (prefix) + namelen + strlen (suffix)) * 2;
char *buf = (char *) alloca (buflen);
if (decl->mangleOverride)
mangled_name = get_identifier (decl->mangleOverride);
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);
tree decl = build_decl (make_location_t (dsym->loc), TYPE_DECL,
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;
DECL_ARTIFICIAL (decl) = 1;
DECL_CONTEXT (decl) = d_decl_context (dsym);
}
}
+/* 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
Type AST classes emitted from the D Front-end, where CTYPE holds
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. */
t->ctype = make_node (t->sym->isUnionDeclaration ()
? UNION_TYPE : RECORD_TYPE);
d_keep (t->ctype);
+ IDENTIFIER_DAGGREGATE (deco) = t->sym;
TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
+ TYPE_CXX_ODR_P (t->ctype) = 1;
if (t->sym->members)
{
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
the type during this call. */
tree basetype = make_node (RECORD_TYPE);
t->ctype = build_pointer_type (basetype);
d_keep (t->ctype);
+ IDENTIFIER_DAGGREGATE (deco) = t->sym;
/* Note that lang_specific data is assigned to both the reference
and the underlying record type. */
TYPE_LANG_SPECIFIC (t->ctype) = build_lang_type (t);
TYPE_LANG_SPECIFIC (basetype) = TYPE_LANG_SPECIFIC (t->ctype);
CLASS_TYPE_P (basetype) = 1;
+ TYPE_CXX_ODR_P (basetype) = 1;
/* Put out all fields, including from each base class. */
layout_aggregate_type (t->sym, basetype, t->sym);