d: Fix SEGV in hash_table<odr_name_hasher, false, xcallocator>::find_slot_with_hash
authorIain Buclaw <ibuclaw@gdcproject.org>
Fri, 20 Mar 2020 16:26:29 +0000 (17:26 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Fri, 20 Mar 2020 16:26:29 +0000 (17:26 +0100)
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.

gcc/d/ChangeLog
gcc/d/d-tree.h
gcc/d/decl.cc
gcc/d/types.cc

index 32856f17504631c587d6cd0c8c38f4ca8264500f..407dc148fc4107999c37e1f4da2adbabcb91ce6e 100644 (file)
@@ -1,3 +1,16 @@
+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
index 4e9c0b7395e2580ae0f8662bf66cecf082f392bc..0f831c754c042003932fef9d1ae79f3d281417e1 100644 (file)
@@ -204,6 +204,7 @@ struct GTY(()) lang_identifier
 
   /* The frontend Declaration associated with this identifier.  */
   Declaration * GTY((skip)) dsymbol;
+  AggregateDeclaration * GTY((skip)) daggregate;
 };
 
 #define IDENTIFIER_LANG_SPECIFIC(NODE) \
@@ -218,6 +219,9 @@ struct GTY(()) lang_identifier
 #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
@@ -600,6 +604,7 @@ extern tree d_signed_type (tree);
 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 *);
index 7afb1aa029239e2d7ebff4bb7b259d09339327bb..053d5537f4e6ce46e56f8e52c46b882f541b2abd 100644 (file)
@@ -59,8 +59,8 @@ along with GCC; see the file COPYING3.  If not see
 
 /* 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);
@@ -78,7 +78,7 @@ mangle_decl (Dsymbol *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);
@@ -1145,7 +1145,7 @@ get_symbol_decl (Declaration *decl)
       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);
@@ -2333,7 +2333,7 @@ build_type_decl (tree type, Dsymbol *dsym)
 
   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);
index 866da965b406a7af0da12d0207323fc4cec8ec9c..025285205ebfdce4aa9bdb5b00780de8d7c2f908 100644 (file)
@@ -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
    Type AST classes emitted from the D Front-end, where CTYPE holds
@@ -857,12 +891,19 @@ public:
 
   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)
       {
@@ -903,17 +944,24 @@ public:
 
   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);