{"action":"created","comment":{"url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/comments/89545865","pull_request_review_id":10091981,"id":89545865,"diff_hunk":"@@ -28,753 +28,898 @@\n #include \"dfrontend/init.h\"\n #include \"dfrontend/module.h\"\n #include \"dfrontend/statement.h\"\n+#include \"dfrontend/template.h\"\n #include \"dfrontend/ctfe.h\"\n #include \"dfrontend/target.h\"\n \n #include \"tree.h\"\n #include \"fold-const.h\"\n #include \"diagnostic.h\"\n+#include \"langhooks.h\"\n #include \"target.h\"\n+#include \"common/common-target.h\"\n+#include \"cgraph.h\"\n+#include \"toplev.h\"\n #include \"stringpool.h\"\n+#include \"varasm.h\"\n #include \"stor-layout.h\"\n+#include \"attribs.h\"\n \n #include \"d-tree.h\"\n #include \"d-codegen.h\"\n #include \"d-objfile.h\"\n #include \"id.h\"\n \n-// Create the symbol with tree for struct initialisers.\n \n-Symbol *\n-SymbolDeclaration::toSymbol()\n+/* Generate a mangled identifier using NAME and SUFFIX, prefixed by the\n+   assembler name for DSYM.  */\n+\n+tree\n+make_internal_name (Dsymbol *dsym, const char *name, const char *suffix)\n {\n-  return dsym->toInitializer();\n-}\n+  const char *prefix = mangle (dsym);\n+  unsigned namelen = strlen (name);\n+  unsigned buflen = (2 + strlen (prefix) + namelen + strlen (suffix)) * 2;\n+  char *buf = (char *) alloca (buflen);\n \n+  snprintf (buf, buflen, \"_D%s%u%s%s\", prefix, namelen, name, suffix);\n+  tree ident = get_identifier (buf);\n \n-// Helper for toSymbol.  Generate a mangled identifier for Symbol.\n-// We don't bother using sclass and t.\n+  /* Symbol is not found in user code, but generate a readable name for it\n+     anyway for debug and diagnostic reporting.  */\n+  snprintf (buf, buflen, \"%s.%s\", dsym->toPrettyChars (), name);\n+  IDENTIFIER_PRETTY_NAME (ident) = get_identifier (buf);\n+\n+  return ident;\n+}\n \n-Symbol *\n-Dsymbol::toSymbolX (const char *prefix, int, type *, const char *suffix)\n+/* Return the decl for the symbol, create it if it doesn't already exist.  */\n+\n+tree\n+get_symbol_decl (Declaration *decl)\n {\n-  const char *symbol = mangle(this);\n-  unsigned prefixlen = strlen (prefix);\n-  size_t sz = (2 + strlen (symbol) + sizeof (size_t) * 3 + prefixlen + strlen (suffix) + 1);\n-  Symbol *s = new Symbol();\n+  if (decl->csym)\n+    return decl->csym;\n \n-  s->Sident = XNEWVEC (const char, sz);\n-  snprintf (CONST_CAST (char *, s->Sident), sz, \"_D%s%u%s%s\",\n-\t    symbol, prefixlen, prefix, suffix);\n+  /* Deal with placeholder symbols immediately:\n+     SymbolDeclaration is used as a shell around an initializer symbol.  */\n+  SymbolDeclaration *sd = decl->isSymbolDeclaration ();\n+  if (sd)\n+    {\n+      decl->csym = aggregate_initializer (sd->dsym);\n+      return decl->csym;\n+    }\n \n-  s->prettyIdent = XNEWVEC (const char, sz);\n-  snprintf (CONST_CAST (char *, s->prettyIdent), sz, \"%s.%s\",\n-\t    toPrettyChars(), prefix);\n+  /* FuncAliasDeclaration is used to import functions from another scope.  */\n+  FuncAliasDeclaration *fad = decl->isFuncAliasDeclaration ();\n+  if (fad)\n+    {\n+      decl->csym = get_symbol_decl (fad->funcalias);\n+      return decl->csym;\n+    }\n \n-  return s;\n-}\n+  /* It is possible for a field declaration symbol to be requested\n+     before the parent type has been built.  */\n+  if (decl->isField ())\n+    {\n+      AggregateDeclaration *ad = decl->toParent ()->isAggregateDeclaration ();\n+      gcc_assert (ad != NULL);\n+      build_ctype (ad->type);\n+      gcc_assert (decl->csym != NULL);\n+      return decl->csym;\n+    }\n \n+  /* Build the tree for the symbol.  */\n+  FuncDeclaration *fd = decl->isFuncDeclaration ();\n+  if (fd)\n+    {\n+      /* Run full semantic on functions we need to know about.  */\n+      if (!fd->functionSemantic ())\n+\t{\n+\t  decl->csym = error_mark_node;\n+\t  return decl->csym;\n+\t}\n \n-Symbol *\n-Dsymbol::toSymbol()\n-{\n-  gcc_unreachable();          // BUG: implement\n-  return NULL;\n-}\n+      decl->csym = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,\n+\t\t\t      get_identifier (decl->ident->string), NULL_TREE);\n \n-// Create the symbol with VAR_DECL tree for static variables.\n+      /* Set function type afterwards as there could be self references.  */\n+      //gcc_assert (fd->tintro == NULL || fd->tintro == fd->type);\n+      //TREE_TYPE (decl->csym) = build_ctype (fd->tintro ? fd->tintro : fd->type);\n+      TREE_TYPE (decl->csym) = build_ctype (fd->type);\n \n-Symbol *\n-VarDeclaration::toSymbol()\n-{\n-  if (!csym)\n+      if (!fd->fbody)\n+\tDECL_EXTERNAL (decl->csym) = 1;\n+    }\n+  else\n     {\n-      // For field declaration, it is possible for toSymbol to be called\n-      // before the parent's build_ctype()\n-      if (isField())\n+      /* Build the variable declaration.  */\n+      VarDeclaration *vd = decl->isVarDeclaration ();\n+      gcc_assert (vd != NULL);\n+\n+      tree_code code = vd->isParameter () ? PARM_DECL\n+\t: !vd->canTakeAddressOf () ? CONST_DECL\n+\t: VAR_DECL;\n+      decl->csym = build_decl (UNKNOWN_LOCATION, code,\n+\t\t\t      get_identifier (decl->ident->string),\n+\t\t\t      declaration_type (vd));\n+\n+      /* If any alignment was set on the declaration.  */\n+      if (vd->alignment)\n \t{\n-\t  AggregateDeclaration *parent_decl = toParent()->isAggregateDeclaration();\n-\t  gcc_assert (parent_decl);\n-\t  build_ctype(parent_decl->type);\n-\t  gcc_assert (csym);\n-\t  return csym;\n+\t  SET_DECL_ALIGN (decl->csym, vd->alignment * BITS_PER_UNIT);\n+\t  DECL_USER_ALIGN (decl->csym) = 1;\n \t}\n \n-      // Use same symbol for VarDeclaration templates with same mangle\n-      bool local_p, template_p;\n-      get_template_storage_info(this, &local_p, &template_p);\n-      if (!this->mangleOverride && isDataseg () && !(storage_class & STCextern)\n-\t  && local_p && template_p)\n+      if (vd->storage_class & STCextern)\n+\tDECL_EXTERNAL (decl->csym) = 1;\n+    }\n+\n+  /* Set the declaration mangled identifier if static.  */\n+  if (decl->isCodeseg () || decl->isDataseg ())\n+    {\n+      tree mangled_name;\n+\n+      if (decl->mangleOverride)\n+\tmangled_name = get_identifier (decl->mangleOverride);\n+      else\n+\tmangled_name = get_identifier (fd ? mangleExact (fd) : mangle (decl));\n+\n+      mangled_name = targetm.mangle_decl_assembler_name (decl->csym,\n+\t\t\t\t\t\t\t mangled_name);\n+      /* The frontend doesn't handle duplicate definitions of unused symbols\n+\t with the same mangle.  So a check is done here instead.  */\n+      if (!DECL_EXTERNAL (decl->csym))\n \t{\n-\t  tree ident = get_identifier(mangle(this));\n-\t  if (!IDENTIFIER_DSYMBOL (ident))\n+\t  if (IDENTIFIER_DSYMBOL (mangled_name))\n \t    {\n-\t      csym = new Symbol();\n-\t      IDENTIFIER_DSYMBOL (ident) = this;\n-\t    }\n-\t  else\n-\t    {\n-\t      csym = IDENTIFIER_DSYMBOL (ident)->toSymbol();\n-\t      return csym;\n+\t      Declaration *other = IDENTIFIER_DSYMBOL (mangled_name);\n+\n+\t      /* Non-templated variables shouldn't be defined twice.  */\n+\t      if (!decl->isInstantiated ())\n+\t\tScopeDsymbol::multiplyDefined (decl->loc, decl, other);\n+\n+\t      decl->csym = get_symbol_decl (other);\n+\t      return decl->csym;\n \t    }\n+\n+\t  IDENTIFIER_PRETTY_NAME (mangled_name) =\n+\t    get_identifier (decl->toPrettyChars (true));\n+\t  IDENTIFIER_DSYMBOL (mangled_name) = decl;\n \t}\n-      else\n+\n+      SET_DECL_ASSEMBLER_NAME (decl->csym, mangled_name);\n+    }\n+\n+  DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (decl);\n+  DECL_CONTEXT (decl->csym) = d_decl_context (decl);\n+  set_decl_location (decl->csym, decl);\n+\n+  if (TREE_CODE (decl->csym) == PARM_DECL)\n+    {\n+      /* Pass non-trivial structs by invisible reference.  */\n+      if (TREE_ADDRESSABLE (TREE_TYPE (decl->csym)))\n \t{\n-\t  csym = new Symbol();\n+\t  tree argtype = build_reference_type (TREE_TYPE (decl->csym));\n+\t  argtype = build_qualified_type (argtype, TYPE_QUAL_RESTRICT);\n+\t  gcc_assert (!DECL_BY_REFERENCE (decl->csym));\n+\t  TREE_TYPE (decl->csym) = argtype;\n+\t  DECL_BY_REFERENCE (decl->csym) = 1;\n+\t  TREE_ADDRESSABLE (decl->csym) = 0;\n+\t  relayout_decl (decl->csym);\n+\t  decl->storage_class |= STCref;\n \t}\n \n-      csym->Salignment = alignment;\n+      DECL_ARG_TYPE (decl->csym) = TREE_TYPE (decl->csym);\n+      gcc_assert (TREE_CODE (DECL_CONTEXT (decl->csym)) == FUNCTION_DECL);\n+    }\n+  else if (TREE_CODE (decl->csym) == CONST_DECL)\n+    {\n+      /* Manifest constants have no address in memory.  */\n+      TREE_CONSTANT (decl->csym) = 1;\n+      TREE_READONLY (decl->csym) = 1;\n+    }\n+  else if (TREE_CODE (decl->csym) == FUNCTION_DECL)\n+    {\n+      /* The real function type may differ from it's declaration.  */\n+      tree fntype = TREE_TYPE (decl->csym);\n+      tree newfntype = NULL_TREE;\n \n-      if (isDataseg())\n+      if (fd->isNested ())\n \t{\n-\t  csym->Sident = mangle(this);\n-\t  csym->prettyIdent = toPrettyChars(true);\n+\t  /* Add an extra argument for the frame/closure pointer, this is also\n+\t     required to be compatible with D delegates.  */\n+\t  newfntype = build_vthis_type (void_type_node, fntype);\n \t}\n-      else\n-\tcsym->Sident = ident->string;\n-\n-      tree_code code = isParameter() ? PARM_DECL\n-\t: !canTakeAddressOf() ? CONST_DECL\n-\t: VAR_DECL;\n+      else if (fd->isThis ())\n+\t{\n+\t  /* Add an extra argument for the 'this' parameter.  The handle type is\n+\t     used even if there is no debug info.  It is needed to make sure\n+\t     virtual member functions are not called statically.  */\n+\t  AggregateDeclaration *ad = fd->isMember2 ();\n+\t  tree handle = build_ctype (ad->handleType ());\n+\n+\t  /* If handle is a pointer type, get record type.  */\n+\t  if (!ad->isStructDeclaration ())\n+\t    handle = TREE_TYPE (handle);\n \n-      tree decl = build_decl (UNKNOWN_LOCATION, code,\n-\t\t\t      get_identifier (ident->string),\n-\t\t\t      declaration_type (this));\n-      DECL_CONTEXT (decl) = d_decl_context (this);\n-      set_decl_location (decl, this);\n+\t  newfntype = build_vthis_type (handle, fntype);\n \n-      if (isParameter())\n-\t{\n-\t  // Pass non-trivial structs by invisible reference.\n-\t  if (TREE_ADDRESSABLE (TREE_TYPE (decl)))\n+\t  /* Set the vindex on virtual functions.  */\n+\t  if (fd->isVirtual () && fd->vtblIndex != -1)\n \t    {\n-\t      tree argtype = build_reference_type(TREE_TYPE (decl));\n-\t      argtype = build_qualified_type(argtype, TYPE_QUAL_RESTRICT);\n-\t      gcc_assert (!DECL_BY_REFERENCE (decl));\n-\t      TREE_TYPE (decl) = argtype;\n-\t      DECL_BY_REFERENCE (decl) = 1;\n-\t      TREE_ADDRESSABLE (decl) = 0;\n-\t      relayout_decl (decl);\n-\t      this->storage_class |= STCref;\n+\t      DECL_VINDEX (decl->csym) = size_int (fd->vtblIndex);\n+\t      DECL_VIRTUAL_P (decl->csym) = 1;\n \t    }\n-\n-\t  DECL_ARG_TYPE (decl) = TREE_TYPE (decl);\n-\t  gcc_assert (TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL);\n \t}\n-      else if (!canTakeAddressOf())\n+      else if (fd->isMain ())\n \t{\n-\t  // Manifest constants have no address in memory.\n-\t  TREE_CONSTANT (decl) = 1;\n-\t  TREE_READONLY (decl) = 1;\n-\t  TREE_STATIC (decl) = 0;\n+\t  /* The main function is named 'D main' to distinguish from C main.  */\n+\t  DECL_NAME (decl->csym) = get_identifier (fd->toPrettyChars (true));\n+\n+\t  /* 'void main' is implicitly converted to returning an int.  */\n+\t  newfntype = build_function_type (int_type_node,\n+\t\t\t\t\t   TYPE_ARG_TYPES (fntype));\n \t}\n-      else if (isDataseg())\n-\t{\n-\t  if (this->mangleOverride)\n-            {\n-              tree mangle = get_identifier (this->mangleOverride);\n-              SET_DECL_ASSEMBLER_NAME (decl, mangle);\n-            }\n-\t  else\n-\t    {\n-\t      tree mangle = get_identifier (csym->Sident);\n \n-\t      if (protection == PROTpublic || storage_class & (STCstatic | STCextern))\n-\t\tmangle = targetm.mangle_decl_assembler_name (decl, mangle);\n+      if (newfntype != NULL_TREE)\n+\t{\n+\t  /* Copy the old attributes from the original type.  */\n+\t  TYPE_ATTRIBUTES (newfntype) = TYPE_ATTRIBUTES (fntype);\n+\t  TYPE_LANG_SPECIFIC (newfntype) = TYPE_LANG_SPECIFIC (fntype);\n+\t  TREE_ADDRESSABLE (newfntype) = TREE_ADDRESSABLE (fntype);\n+\t  TREE_TYPE (decl->csym) = newfntype;\n+\t  d_keep (newfntype);\n+\t}\n \n-\t      SET_DECL_ASSEMBLER_NAME (decl, mangle);\n-\t    }\n+      /* Miscellaneous function flags.  */\n+      if (fd->isMember2() || fd->isFuncLiteralDeclaration())\n+\t{\n+\t  /* See grokmethod in cp/decl.c.  Maybe we shouldn't be setting inline\n+\t     flags without reason or proper handling.  */\n+\t  DECL_DECLARED_INLINE_P (decl->csym) = 1;\n+\t  DECL_NO_INLINE_WARNING_P (decl->csym) = 1;\n+\t}\n \n-\t  setup_symbol_storage (this, decl, false);\n+      /* Function was declared 'naked'.  */\n+      if (fd->naked)\n+\t{\n+\t  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl->csym) = 1;\n+\t  DECL_UNINLINABLE (decl->csym) = 1;\n \t}\n \n-      DECL_LANG_SPECIFIC (decl) = build_lang_decl (this);\n-      d_keep (decl);\n-      csym->Stree = decl;\n+      /* Vector array operations are always compiler generated.  */\n+      if (fd->isArrayOp)\n+\t{\n+\t  DECL_ARTIFICIAL (decl->csym) = 1;\n+\t  D_DECL_ONE_ONLY (decl->csym) = 1;\n+\t}\n \n-      // Can't set TREE_STATIC, etc. until we get to toObjFile as this could be\n-      // called from a variable in an imported module.\n-      if ((isConst() || isImmutable()) && (storage_class & STCinit)\n-\t  && declaration_reference_p(this))\n+      /* And so are ensure and require contracts.  */\n+      if (fd->ident == Id::ensure || fd->ident == Id::require)\n \t{\n-\t  if (!TREE_STATIC (decl))\n-\t    TREE_READONLY (decl) = 1;\n-\t  else\n-\t    csym->Sreadonly = true;\n+\t  DECL_ARTIFICIAL (decl->csym) = 1;\n+\t  TREE_PUBLIC (decl->csym) = 1;\n \t}\n \n-      // Propagate shared.\n-      if (TYPE_SHARED (TREE_TYPE (decl)))\n-\tTREE_ADDRESSABLE (decl) = 1;\n+      if (decl->storage_class & STCfinal)\n+\tDECL_FINAL_P (decl->csym) = 1;\n \n-      // Mark compiler generated temporaries as artificial.\n-      if (storage_class & STCtemp)\n-\tDECL_ARTIFICIAL (decl) = 1;\n+      maybe_set_intrinsic (fd);\n+    }\n+\n+  /* Mark compiler generated temporaries as artificial.  */\n+  if (decl->storage_class & STCtemp)\n+    DECL_ARTIFICIAL (decl->csym) = 1;\n+\n+  /* Propagate shared on the decl.  */\n+  if (TYPE_SHARED (TREE_TYPE (decl->csym)))\n+    TREE_ADDRESSABLE (decl->csym) = 1;\n+\n+  /* Symbol was marked volatile.  */\n+  if (decl->storage_class & STCvolatile)\n+    TREE_THIS_VOLATILE (decl->csym) = 1;\n+\n+  /* Protection attributes are used by the debugger.  */\n+  if (decl->protection == PROTprivate)\n+    TREE_PRIVATE (decl->csym) = 1;\n+  else if (decl->protection == PROTprotected)\n+    TREE_PROTECTED (decl->csym) = 1;\n+\n+  /* Likewise, so could the deprecated attribute.  */\n+  if (decl->storage_class & STCdeprecated)\n+    TREE_DEPRECATED (decl->csym) = 1;\n \n #if TARGET_DLLIMPORT_DECL_ATTRIBUTES\n-      // Have to test for import first\n-      if (isImportedSymbol())\n-\t{\n-\t  insert_decl_attribute (decl, \"dllimport\");\n-\t  DECL_DLLIMPORT_P (decl) = 1;\n-\t}\n-      else if (isExport())\n-\tinsert_decl_attribute (decl, \"dllexport\");\n+  // Have to test for import first\n+  if (decl->isImportedSymbol ())\n+    {\n+      insert_decl_attribute (decl->csym, \"dllimport\");\n+      DECL_DLLIMPORT_P (decl->csym) = 1;\n+    }\n+  else if (decl->isExport ())\n+    insert_decl_attribute (decl->csym, \"dllexport\");\n #endif\n \n-      if (global.params.vtls && isDataseg() && isThreadlocal())\n+  if (decl->isDataseg () || decl->isCodeseg () || decl->isThreadlocal ())\n+    {\n+      /* Check if the declaration is a template, and whether it will be emitted\n+\t in the current compilation or not.  */\n+      TemplateInstance *ti = decl->isInstantiated ();\n+      if (ti)\n \t{\n-\t  char *p = loc.toChars();\n-\t  fprintf (global.stdmsg, \"%s: %s is thread local\\n\", p ? p : \"\", toChars());\n-\t  if (p)\n-\t    free (p);\n+\t  D_DECL_ONE_ONLY (decl->csym) = 1;\n+\t  D_DECL_IS_TEMPLATE (decl->csym) = 1;\n+\n+\t  if (!DECL_EXTERNAL (decl->csym)\n+\t      && ti->minst && ti->minst->isRoot())\n+\t    TREE_STATIC (decl->csym) = 1;\n+\t  else\n+\t    DECL_EXTERNAL (decl->csym) = 1;\n+\t}\n+      else\n+\t{\n+\t  if (!DECL_EXTERNAL (decl->csym)\n+\t      && decl->getModule() && decl->getModule()->isRoot())\n+\t    TREE_STATIC (decl->csym) = 1;\n+\t  else\n+\t    DECL_EXTERNAL (decl->csym) = 1;\n \t}\n-    }\n \n-  return csym;\n-}\n+      /* Set TREE_PUBLIC by default, but allow private template to override.  */\n+      if (!fd || !fd->isNested ())\n+\tTREE_PUBLIC (decl->csym) = 1;\n \n-// Create the symbol with tree for typeinfo decls.\n+      if (D_DECL_ONE_ONLY (decl->csym))\n+\td_comdat_linkage (decl->csym);\n+    }\n \n-Symbol *\n-TypeInfoDeclaration::toSymbol()\n-{\n-  if (!csym)\n+  /* Symbol is going in thread local storage.  */\n+  if (decl->isThreadlocal () && !DECL_ARTIFICIAL (decl->csym))\n     {\n-      gcc_assert(tinfo->ty != Terror);\n-\n-      VarDeclaration::toSymbol();\n+      if (global.params.vtls)\n+\t{\n+\t  char *p = decl->loc.toChars ();\n+\t  fprintf (global.stdmsg, \"%s: %s is thread local\\n\",\n+\t\t   p ? p : \"\", decl->toChars ());\n+\t  if (p)\n+\t    free (p);\n+\t}\n \n-      // This variable is the static initialization for the\n-      // given TypeInfo.  It is the actual data, not a reference\n-      gcc_assert (TREE_CODE (TREE_TYPE (csym->Stree)) == POINTER_TYPE);\n-      TREE_TYPE (csym->Stree) = TREE_TYPE (TREE_TYPE (csym->Stree));\n-      relayout_decl (csym->Stree);\n-      TREE_USED (csym->Stree) = 1;\n+      set_decl_tls_model (decl->csym, decl_default_tls_model (decl->csym));\n+    }\n \n-      // Built-in typeinfo will be referenced as one-only.\n-      D_DECL_ONE_ONLY (csym->Stree) = 1;\n-      d_comdat_linkage (csym->Stree);\n+  /* Apply any user attributes that may affect semantic meaning.  */\n+  if (decl->userAttribDecl)\n+    {\n+      Expressions *attrs = decl->userAttribDecl->getAttributes ();\n+      decl_attributes (&decl->csym, build_attributes (attrs), 0);\n     }\n+  else if (DECL_ATTRIBUTES (decl->csym) != NULL)\n+    decl_attributes (&decl->csym, DECL_ATTRIBUTES (decl->csym), 0);\n+\n+  /* %% Probably should be a little more intelligent about setting this.  */\n+  TREE_USED (decl->csym) = 1;\n+  d_keep (decl->csym);\n \n-  return csym;\n+  return decl->csym;\n }\n \n-// Create the symbol with tree for typeinfoclass decls.\n+/* Visitor to create the decl tree for typeinfo decls.  */\n \n-Symbol *\n-TypeInfoClassDeclaration::toSymbol()\n+class TypeInfoDeclVisitor : public Visitor\n {\n-  gcc_assert (tinfo->ty == Tclass);\n-  TypeClass *tc = (TypeClass *) tinfo;\n-  return tc->sym->toSymbol();\n-}\n+public:\n+  TypeInfoDeclVisitor (void) {}\n+\n+  void visit (TypeInfoDeclaration *tid)\n+  {\n+    tree ident = get_identifier (tid->ident->string);\n+\n+    tid->csym = build_decl (UNKNOWN_LOCATION, VAR_DECL, ident,\n+\t\t\t    TREE_TYPE (build_ctype (tid->type)));\n+    set_decl_location (tid->csym, tid);\n+    DECL_LANG_SPECIFIC (tid->csym) = build_lang_decl (tid);\n+    SET_DECL_ASSEMBLER_NAME (tid->csym, ident);\n+\n+    d_keep (tid->csym);\n+\n+    DECL_CONTEXT (tid->csym) = d_decl_context (tid);\n+    DECL_ARTIFICIAL (tid->csym) = 1;\n+    TREE_STATIC (tid->csym) = 1;\n+    TREE_READONLY (tid->csym) = 1;\n+    TREE_PUBLIC (tid->csym) = 1;\n+\n+    /* The typeinfo has not been defined -- yet.  */\n+    DECL_EXTERNAL (tid->csym) = 1;\n+\n+    /* Built-in typeinfo will be referenced as one-only.  */\n+    gcc_assert (!tid->isInstantiated ());\n+    d_comdat_linkage (tid->csym);\n+  }\n+\n+  void visit (TypeInfoClassDeclaration *tid)\n+  {\n+    gcc_assert (tid->tinfo->ty == Tclass);\n+    TypeClass *tc = (TypeClass *) tid->tinfo;\n+    tid->csym = get_classinfo_decl (tc->sym);\n+  }\n+};\n+\n+/* Get the VAR_DECL of the TypeInfo for DECL.  If this does not yet exist,\n+   create it.  The TypeInfo decl provides information about the type of a given\n+   expression or object.  */\n+\n+tree\n+get_typeinfo_decl (TypeInfoDeclaration *decl)\n+{\n+  if (decl->csym)\n+    return decl->csym;\n \n+  gcc_assert (decl->tinfo->ty != Terror);\n \n-// Create the symbol with tree for function aliases.\n+  TypeInfoDeclVisitor v = TypeInfoDeclVisitor ();\n+  decl->accept (&v);\n+  gcc_assert (decl->csym != NULL_TREE);\n \n-Symbol *\n-FuncAliasDeclaration::toSymbol()\n-{\n-  return funcalias->toSymbol();\n+  return decl->csym;\n }\n \n-// Create the symbol with FUNCTION_DECL tree for functions.\n+/* Thunk code is based on g++ */\n \n-Symbol *\n-FuncDeclaration::toSymbol()\n+static int thunk_labelno;\n+\n+/* Create a static alias to function.  */\n+\n+static tree\n+make_alias_for_thunk (tree function)\n {\n-  if (!csym)\n-    {\n-      TypeFunction *ftype = (TypeFunction *) (tintro ? tintro : type);\n-      tree fntype = NULL_TREE;\n-      tree vindex = NULL_TREE;\n+  tree alias;\n+  char buf[256];\n \n-      // Run full semantic on symbols we need to know about during compilation.\n-      if (inferRetType && type && !type->nextOf())\n-\t{\n-\t  Module *old_current_module_decl = current_module_decl;\n-\t  current_module_decl = NULL;\n-\t  if (!functionSemantic())\n-\t    {\n-\t      csym = new Symbol();\n-\t      csym->Stree = error_mark_node;\n-\t      return csym;\n-\t    }\n-\t  current_module_decl = old_current_module_decl;\n-\t}\n+  // Thunks may reference extern functions which cannot be aliased.\n+  if (DECL_EXTERNAL (function))\n+    return function;\n \n-      // Use same symbol for FuncDeclaration templates with same mangle\n-      if (!this->mangleOverride && this->fbody)\n-\t{\n-\t  tree ident = get_identifier(mangleExact(this));\n-\t  if (!IDENTIFIER_DSYMBOL (ident))\n-\t    {\n-\t      csym = new Symbol();\n-\t      IDENTIFIER_DSYMBOL (ident) = this;\n-\t    }\n-\t  else\n-\t    {\n-\t      bool local_p, template_p;\n-\t      get_template_storage_info(this, &local_p, &template_p);\n-\t      // Non-templated functions shouldn't be defined twice\n-\t      if (!template_p)\n-\t\tScopeDsymbol::multiplyDefined(loc, this, IDENTIFIER_DSYMBOL (ident));\n-\n-\t      csym = IDENTIFIER_DSYMBOL (ident)->toSymbol();\n-\t      return csym;\n-\t    }\n-\t}\n-      else\n-\t{\n-\t  csym = new Symbol();\n-\t}\n+  targetm.asm_out.generate_internal_label (buf, \"LTHUNK\", thunk_labelno);\n+  thunk_labelno++;\n \n-      // Save mangle/debug names for making thunks.\n-      csym->Sident = mangleExact(this);\n-      csym->prettyIdent = toPrettyChars(true);\n+  alias = build_decl (DECL_SOURCE_LOCATION (function), FUNCTION_DECL,\n+\t\t      get_identifier (buf), TREE_TYPE (function));\n+  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);\n+  lang_hooks.dup_lang_specific_decl (alias);\n+  DECL_CONTEXT (alias) = NULL_TREE;\n+  TREE_READONLY (alias) = TREE_READONLY (function);\n+  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);\n+  TREE_PUBLIC (alias) = 0;\n \n-      tree id = get_identifier (this->isMain()\n-\t\t\t\t? csym->prettyIdent : ident->string);\n-      tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, id, NULL_TREE);\n-      DECL_CONTEXT (fndecl) = d_decl_context (this);\n+  DECL_EXTERNAL (alias) = 0;\n+  DECL_ARTIFICIAL (alias) = 1;\n \n-      csym->Stree = fndecl;\n+  DECL_DECLARED_INLINE_P (alias) = 0;\n+  DECL_INITIAL (alias) = error_mark_node;\n+  DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (function));\n \n-      TREE_TYPE (fndecl) = build_ctype(ftype);\n-      DECL_LANG_SPECIFIC (fndecl) = build_lang_decl (this);\n-      d_keep (fndecl);\n+  TREE_ADDRESSABLE (alias) = 1;\n+  TREE_USED (alias) = 1;\n+  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));\n \n-      if (isNested())\n-\t{\n-\t  // Add an extra argument for the frame/closure pointer,\n-\t  // also needed to be compatible with delegates.\n-\t  fntype = build_vthis_type(void_type_node, TREE_TYPE (fndecl));\n-\t}\n-      else if (isThis())\n-\t{\n-\t  // Do this even if there is no debug info.  It is needed to make\n-\t  // sure member functions are not called statically\n-\t  AggregateDeclaration *agg_decl = isMember2();\n-\t  tree handle = build_ctype(agg_decl->handleType());\n+  if (!flag_syntax_only)\n+    {\n+      cgraph_node *aliasn;\n+      aliasn = cgraph_node::create_same_body_alias (alias, function);\n+      gcc_assert (aliasn != NULL);\n+    }\n+  return alias;\n+}\n \n-\t  // If handle is a pointer type, get record type.\n-\t  if (!agg_decl->isStructDeclaration())\n-\t    handle = TREE_TYPE (handle);\n+// Emit the definition of a D vtable thunk.\n \n-\t  fntype = build_vthis_type(handle, TREE_TYPE (fndecl));\n+static void\n+finish_thunk (tree thunk, tree function)\n+{\n+  /* Setup how D thunks are outputted.  */\n+  int fixed_offset = -THUNK_LANG_OFFSET (thunk);\n+  bool this_adjusting = true;\n+  tree alias;\n \n-\t  if (isVirtual() && vtblIndex != -1)\n-\t    vindex = size_int (vtblIndex);\n-\t}\n-      else if (isMain() && ftype->nextOf()->toBasetype()->ty == Tvoid)\n-\t{\n-\t  // void main() implicitly converted to int main().\n-\t  fntype = build_function_type (int_type_node, TYPE_ARG_TYPES (TREE_TYPE (fndecl)));\n-\t}\n+  if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function))\n+    alias = make_alias_for_thunk (function);\n+  else\n+    alias = function;\n \n-      if (fntype != NULL_TREE)\n-\t{\n-\t  TYPE_ATTRIBUTES (fntype) = TYPE_ATTRIBUTES (TREE_TYPE (fndecl));\n-\t  TYPE_LANG_SPECIFIC (fntype) = TYPE_LANG_SPECIFIC (TREE_TYPE (fndecl));\n-\t  TREE_ADDRESSABLE (fntype) = TREE_ADDRESSABLE (TREE_TYPE (fndecl));\n-\t  TREE_TYPE (fndecl) = fntype;\n-\t  d_keep (fntype);\n-\t}\n+  TREE_ADDRESSABLE (function) = 1;\n+  TREE_USED (function) = 1;\n \n-      if (this->mangleOverride)\n-        {\n-          tree mangle = get_identifier (this->mangleOverride);\n-          SET_DECL_ASSEMBLER_NAME (fndecl, mangle);\n-        }\n-      else\n-\t{\n-\t  tree mangle = get_identifier (csym->Sident);\n-\t  mangle = targetm.mangle_decl_assembler_name (fndecl, mangle);\n-\t  SET_DECL_ASSEMBLER_NAME (fndecl, mangle);\n-\t}\n+  if (flag_syntax_only)\n+    {\n+      TREE_ASM_WRITTEN (thunk) = 1;\n+      return;\n+    }\n \n-      if (vindex)\n-\t{\n-\t  DECL_VINDEX (fndecl) = vindex;\n-\t  DECL_VIRTUAL_P (fndecl) = 1;\n-\t}\n+  if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)\n+      && targetm_common.have_named_sections)\n+    {\n+      tree fn = function;\n+      symtab_node *symbol = symtab_node::get (function);\n \n-      if (isMember2() || isFuncLiteralDeclaration())\n+      if (symbol != NULL && symbol->alias)\n \t{\n-\t  // See grokmethod in cp/decl.c\n-\t  DECL_DECLARED_INLINE_P (fndecl) = 1;\n-\t  DECL_NO_INLINE_WARNING_P (fndecl) = 1;\n+\t  if (symbol->analyzed)\n+\t    fn = symtab_node::get (function)->ultimate_alias_target ()->decl;\n+\t  else\n+\t    fn = symtab_node::get (function)->alias_target;\n \t}\n+      resolve_unique_section (fn, 0, flag_function_sections);\n \n-      if (naked)\n+      if (DECL_SECTION_NAME (fn) != NULL && DECL_ONE_ONLY (fn))\n \t{\n-\t  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl) = 1;\n-\t  DECL_UNINLINABLE (fndecl) = 1;\n-\t}\n+\t  resolve_unique_section (thunk, 0, flag_function_sections);\n \n-      // These are always compiler generated.\n-      if (isArrayOp)\n-\t{\n-\t  DECL_ARTIFICIAL (fndecl) = 1;\n-\t  D_DECL_ONE_ONLY (fndecl) = 1;\n-\t}\n-      // So are ensure and require contracts.\n-      if (ident == Id::ensure || ident == Id::require)\n-\t{\n-\t  DECL_ARTIFICIAL (fndecl) = 1;\n-\t  TREE_PUBLIC (fndecl) = 1;\n+\t  /* Output the thunk into the same section as function.  */\n+\t  set_decl_section_name (thunk, DECL_SECTION_NAME (fn));\n+\t  symtab_node::get (thunk)->implicit_section\n+\t    = symtab_node::get (fn)->implicit_section;\n \t}\n+    }\n \n-      // Storage class attributes\n-      if (storage_class & STCstatic)\n-\tTREE_STATIC (fndecl) = 1;\n-      if (storage_class & STCfinal)\n-\tDECL_FINAL_P (fndecl) = 1;\n+  /* Set up cloned argument trees for the thunk.  */\n+  tree t = NULL_TREE;\n+  for (tree a = DECL_ARGUMENTS (function); a; a = DECL_CHAIN (a))\n+    {\n+      tree x = copy_node (a);\n+      DECL_CHAIN (x) = t;\n+      DECL_CONTEXT (x) = thunk;\n+      SET_DECL_RTL (x, NULL);\n+      DECL_HAS_VALUE_EXPR_P (x) = 0;\n+      TREE_ADDRESSABLE (x) = 0;\n+      t = x;\n+    }\n+  DECL_ARGUMENTS (thunk) = nreverse (t);\n+  TREE_ASM_WRITTEN (thunk) = 1;\n \n-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES\n-      // Have to test for import first\n-      if (isImportedSymbol())\n-\t{\n-\t  insert_decl_attribute (fndecl, \"dllimport\");\n-\t  DECL_DLLIMPORT_P (fndecl) = 1;\n-\t}\n-      else if (isExport())\n-\tinsert_decl_attribute (fndecl, \"dllexport\");\n-#endif\n-      set_decl_location (fndecl, this);\n-      setup_symbol_storage (this, fndecl, false);\n+  cgraph_node *funcn, *thunk_node;\n \n-      if (!ident)\n-\tTREE_PUBLIC (fndecl) = 0;\n+  funcn = cgraph_node::get_create (function);\n+  gcc_assert (funcn);\n+  thunk_node = funcn->create_thunk (thunk, thunk, this_adjusting,\n+\t\t\t\t    fixed_offset, 0, 0, alias);\n \n-      // %% Probably should be a little more intelligent about this\n-      TREE_USED (fndecl) = 1;\n+  if (DECL_ONE_ONLY (function))\n+    thunk_node->add_to_same_comdat_group (funcn);\n \n-      maybe_set_intrinsic (this);\n-    }\n+  /* Target assemble_mi_thunk doesn't work across section boundaries\n+     on many targets, instead force thunk to be expanded in gimple.  */\n+  if (DECL_EXTERNAL (function))\n+    {\n+      /* cgraph::expand_thunk writes over current_function_decl, so if this\n+\t could ever be in use by the codegen pass, we want to know about it.  */\n+      gcc_assert (current_function_decl == NULL_TREE);\n \n-  return csym;\n+      if (!stdarg_p (TREE_TYPE (thunk)))\n+\t{\n+\t  /* Put generic thunk into COMDAT.  */\n+\t  d_comdat_linkage (thunk);\n+\t  thunk_node->create_edge (funcn, NULL, 0, CGRAPH_FREQ_BASE);\n+\t  thunk_node->expand_thunk (false, true);\n+\t}\n+    }\n }\n \n+/* Return a thunk to DECL.  Thunks adjust the incoming `this' pointer by OFFSET.\n+   Adjustor thunks are created and pointers to them stored in the method entries\n+   in the vtable in order to set the this pointer to the start of the object\n+   instance corresponding to the implementing method.  */\n \n-// Create the thunk symbol functions.\n-// Thunk is added to class at OFFSET.\n-\n-Symbol *\n-FuncDeclaration::toThunkSymbol (int offset)\n+tree\n+make_thunk (FuncDeclaration *decl, int offset)\n {\n-  Symbol *sthunk;\n-  Thunk *thunk;\n-\n-  toSymbol();\n-  toObjFile();\n+  get_symbol_decl (decl);\n+  decl->toObjFile ();\n \n   /* If the thunk is to be static (that is, it is being emitted in this\n      module, there can only be one FUNCTION_DECL for it.   Thus, there\n      is a list of all thunks for a given function. */\n-  bool found = false;\n+  tree thunk;\n \n-  for (size_t i = 0; i < csym->thunks.length(); i++)\n+  for (thunk = DECL_LANG_THUNKS (decl->csym); thunk; thunk = DECL_CHAIN (thunk))\n     {\n-      thunk = csym->thunks[i];\n-      if (thunk->offset == offset)\n-\t{\n-\t  found = true;\n-\t  break;\n-\t}\n+      if (THUNK_LANG_OFFSET (thunk) == offset)\n+\treturn thunk;\n     }\n \n-  if (!found)\n-    {\n-      thunk = new Thunk();\n-      thunk->offset = offset;\n-      csym->thunks.safe_push (thunk);\n-    }\n+  thunk = build_decl (DECL_SOURCE_LOCATION (decl->csym),\n+\t\t      FUNCTION_DECL, NULL_TREE, TREE_TYPE (decl->csym));\n+  DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (decl->csym);\n+  lang_hooks.dup_lang_specific_decl (thunk);\n+  THUNK_LANG_OFFSET (thunk) = offset;\n \n-  if (!thunk->symbol)\n-    {\n-      unsigned sz = strlen (csym->Sident) + 14;\n-      sthunk = new Symbol();\n-      sthunk->Sident = XNEWVEC (const char, sz);\n-      snprintf (CONST_CAST (char *, sthunk->Sident), sz, \"_DT%u%s\",\n-\t\toffset, csym->Sident);\n-\n-      tree target_func_decl = csym->Stree;\n-      tree thunk_decl = build_decl (DECL_SOURCE_LOCATION (target_func_decl),\n-\t\t\t\t    FUNCTION_DECL, NULL_TREE, TREE_TYPE (target_func_decl));\n-      DECL_LANG_SPECIFIC (thunk_decl) = DECL_LANG_SPECIFIC (target_func_decl);\n-      TREE_READONLY (thunk_decl) = TREE_READONLY (target_func_decl);\n-      TREE_THIS_VOLATILE (thunk_decl) = TREE_THIS_VOLATILE (target_func_decl);\n-      TREE_NOTHROW (thunk_decl) = TREE_NOTHROW (target_func_decl);\n-\n-      DECL_CONTEXT (thunk_decl) = d_decl_context (this);\n-\n-      /* Thunks inherit the public access of the function they are targetting.  */\n-      TREE_PUBLIC (thunk_decl) = TREE_PUBLIC (target_func_decl);\n-      DECL_EXTERNAL (thunk_decl) = 0;\n-\n-      /* Thunks are always addressable.  */\n-      TREE_ADDRESSABLE (thunk_decl) = 1;\n-      TREE_USED (thunk_decl) = 1;\n-      DECL_ARTIFICIAL (thunk_decl) = 1;\n-      DECL_DECLARED_INLINE_P (thunk_decl) = 0;\n-\n-      DECL_VISIBILITY (thunk_decl) = DECL_VISIBILITY (target_func_decl);\n-      /* Needed on some targets to avoid \"causes a section type conflict\".  */\n-      D_DECL_ONE_ONLY (thunk_decl) = D_DECL_ONE_ONLY (target_func_decl);\n-      DECL_COMDAT (thunk_decl) = DECL_COMDAT (target_func_decl);\n-      DECL_WEAK (thunk_decl) = DECL_WEAK (target_func_decl);\n-\n-      DECL_NAME (thunk_decl) = get_identifier (sthunk->Sident);\n-      SET_DECL_ASSEMBLER_NAME (thunk_decl, DECL_NAME (thunk_decl));\n-\n-      d_keep (thunk_decl);\n-      sthunk->Stree = thunk_decl;\n-\n-      use_thunk (thunk_decl, target_func_decl, offset);\n-\n-      thunk->symbol = sthunk;\n-    }\n+  TREE_READONLY (thunk) = TREE_READONLY (decl->csym);\n+  TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (decl->csym);\n+  TREE_NOTHROW (thunk) = TREE_NOTHROW (decl->csym);\n \n-  return thunk->symbol;\n-}\n+  DECL_CONTEXT (thunk) = d_decl_context (decl);\n \n+  /* Thunks inherit the public access of the function they are targetting.  */\n+  TREE_PUBLIC (thunk) = TREE_PUBLIC (decl->csym);\n+  DECL_EXTERNAL (thunk) = 0;\n \n-// Create the \"ClassInfo\" symbol for classes.\n+  /* Thunks are always addressable.  */\n+  TREE_ADDRESSABLE (thunk) = 1;\n+  TREE_USED (thunk) = 1;\n+  DECL_ARTIFICIAL (thunk) = 1;\n+  DECL_DECLARED_INLINE_P (thunk) = 0;\n \n-Symbol *\n-ClassDeclaration::toSymbol()\n-{\n-  if (!csym)\n-    {\n-      csym = toSymbolX (\"__Class\", 0, 0, \"Z\");\n+  DECL_VISIBILITY (thunk) = DECL_VISIBILITY (decl->csym);\n+  /* Needed on some targets to avoid \"causes a section type conflict\".  */\n+  D_DECL_ONE_ONLY (thunk) = D_DECL_ONE_ONLY (decl->csym);\n+  DECL_COMDAT (thunk) = DECL_COMDAT (decl->csym);\n+  DECL_WEAK (thunk) = DECL_WEAK (decl->csym);\n \n-      tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL,\n-\t\t\t      get_identifier (csym->prettyIdent), unknown_type_node);\n-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (csym->Sident));\n-      csym->Stree = decl;\n-      d_keep (decl);\n+  tree target_name = DECL_ASSEMBLER_NAME (decl->csym);\n+  unsigned identlen = IDENTIFIER_LENGTH (target_name) + 14;\n+  const char *ident = XNEWVEC (const char, identlen);\n+  snprintf (CONST_CAST (char *, ident), identlen,\n+\t    \"_DT%u%s\", offset, IDENTIFIER_POINTER (target_name));\n \n-      setup_symbol_storage (this, decl, true);\n-      set_decl_location (decl, this);\n+  DECL_NAME (thunk) = get_identifier (ident);\n+  SET_DECL_ASSEMBLER_NAME (thunk, DECL_NAME (thunk));\n \n-      DECL_ARTIFICIAL (decl) = 1;\n-      // ClassInfo cannot be const data, because we use the monitor on it.\n-      TREE_READONLY (decl) = 0;\n-    }\n+  d_keep (thunk);\n \n-  return csym;\n+  finish_thunk (thunk, decl->csym);\n+\n+  /* Add it to the list of thunks associated with the function.  */\n+  DECL_LANG_THUNKS (thunk) = NULL_TREE;\n+  DECL_CHAIN (thunk) = DECL_LANG_THUNKS (decl->csym);\n+  DECL_LANG_THUNKS (decl->csym) = thunk;\n+\n+  return thunk;\n }\n \n-// Create the \"InterfaceInfo\" symbol for interfaces.\n+/* Get the VAR_DECL of the ModuleInfo for DECL.  If this does not yet exist,\n+   create it.  The ModuleInfo decl is used to keep track of constructors,\n+   destructors, unittests, members, classes, and imports for the given module.\n+   This is used by the D runtime for module initialization and termination.  */\n \n-Symbol *\n-InterfaceDeclaration::toSymbol()\n+tree\n+get_moduleinfo_decl (Module *decl)\n {\n-  if (!csym)\n-    {\n-      csym = toSymbolX (\"__Interface\", 0, 0, \"Z\");\n+  if (decl->csym)\n+    return decl->csym;\n \n-      tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL,\n-\t\t\t      get_identifier (csym->prettyIdent), unknown_type_node);\n-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (csym->Sident));\n-      csym->Stree = decl;\n-      d_keep (decl);\n+  tree ident = make_internal_name (decl, \"__ModuleInfo\", \"Z\");\n \n-      setup_symbol_storage (this, decl, true);\n-      set_decl_location (decl, this);\n+  decl->csym = build_decl (BUILTINS_LOCATION, VAR_DECL,\n+\t\t\t   IDENTIFIER_PRETTY_NAME (ident), unknown_type_node);\n+  set_decl_location (decl->csym, decl);\n+  DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (NULL);\n+  SET_DECL_ASSEMBLER_NAME (decl->csym, ident);\n \n-      DECL_ARTIFICIAL (decl) = 1;\n-      TREE_READONLY (decl) = 1;\n-    }\n+  d_keep (decl->csym);\n+\n+  DECL_CONTEXT (decl->csym) = build_import_decl (decl);\n+  DECL_ARTIFICIAL (decl->csym) = 1;\n+  TREE_STATIC (decl->csym) = 1;\n+  /* Not readonly, moduleinit depends on this.  */\n+  TREE_READONLY (decl->csym) = 0;\n+  TREE_PUBLIC (decl->csym) = 1;\n+\n+  /* The moduleinfo decl has not been defined -- yet.  */\n+  DECL_EXTERNAL (decl->csym) = 1;\n \n-  return csym;\n+  return decl->csym;\n }\n \n-// Create the \"ModuleInfo\" symbol for a given module.\n+/* Get the VAR_DECL of the ClassInfo for DECL.  If this does not yet exist,\n+   create it.  The ClassInfo decl provides information about the dynamic type\n+   of a given class type or object.  */\n \n-Symbol *\n-Module::toSymbol()\n+tree\n+get_classinfo_decl (ClassDeclaration *decl)\n {\n-  if (!csym)\n-    {\n-      csym = toSymbolX (\"__ModuleInfo\", 0, 0, \"Z\");\n+  if (decl->csym)\n+    return decl->csym;\n \n-      tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL,\n-\t\t\t      get_identifier (csym->prettyIdent), unknown_type_node);\n-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (csym->Sident));\n-      csym->Stree = decl;\n-      d_keep (decl);\n+  InterfaceDeclaration *id = decl->isInterfaceDeclaration ();\n+  tree ident = make_internal_name (decl, id ? \"__Interface\" : \"__Class\", \"Z\");\n \n-      setup_symbol_storage (this, decl, true);\n-      set_decl_location (decl, this);\n+  decl->csym = build_decl (BUILTINS_LOCATION, VAR_DECL,\n+\t\t\t   IDENTIFIER_PRETTY_NAME (ident), unknown_type_node);\n+  set_decl_location (decl->csym, decl);\n+  DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (NULL);\n+  SET_DECL_ASSEMBLER_NAME (decl->csym, ident);\n \n-      DECL_ARTIFICIAL (decl) = 1;\n-      // Not readonly, moduleinit depends on this.\n-      TREE_READONLY (decl) = 0;\n-    }\n+  d_keep (decl->csym);\n \n-  return csym;\n-}\n+  /* Class is a reference, want the record type.  */\n+  DECL_CONTEXT (decl->csym) = TREE_TYPE (build_ctype (decl->type));\n+  DECL_ARTIFICIAL (decl->csym) = 1;\n+  TREE_STATIC (decl->csym) = 1;\n+  /* ClassInfo cannot be const data, because we use the monitor on it.  */\n+  TREE_READONLY (decl->csym) = 0;\n+  TREE_PUBLIC (decl->csym) = 1;\n \n-Symbol *\n-StructLiteralExp::toSymbol()\n-{\n-  if (!sym)\n-    {\n-      sym = new Symbol();\n+  /* The moduleinfo decl has not been defined -- yet.  */\n+  DECL_EXTERNAL (decl->csym) = 1;\n \n-      // Build reference symbol.\n-      tree ctype = build_ctype(type);\n-      tree decl = build_artificial_decl(ctype, NULL_TREE, \"S\");\n-      set_decl_location(decl, loc);\n+  /* Could move setting comdat linkage to the caller, who knows whether\n+     this classinfo is being emitted in this compilation.  */\n+  if (decl->isInstantiated ())\n+    d_comdat_linkage (decl->csym);\n \n-      sym->Stree = decl;\n-      this->sinit = sym;\n+  return decl->csym;\n+}\n \n-      DECL_INITIAL (sym->Stree) = build_expr(this, true);\n-      d_finish_symbol(sym);\n-    }\n+/* Get the VAR_DECL of the vtable symbol for DECL.  If this does not yet exist,\n+   create it.  The vtable is accessible via ClassInfo, but since it is needed\n+   frequently (like for rtti comparisons), make it directly accessible.  */\n \n-  return sym;\n+tree\n+get_vtable_decl (ClassDeclaration *decl)\n+{\n+  if (decl->vtblsym)\n+    return decl->vtblsym;\n+\n+  /* Note: Using a static array type for the VAR_DECL, the DECL_INITIAL value\n+     will have a different type.  However the backend seems to accept this.  */\n+  Type *vtbltype = Type::tvoidptr->sarrayOf (decl->vtbl.dim);\n+  tree ident = make_internal_name (decl, \"__vtbl\", \"Z\");\n+\n+  decl->vtblsym = build_decl (UNKNOWN_LOCATION, VAR_DECL,\n+\t\t\t      IDENTIFIER_PRETTY_NAME (ident),\n+\t\t\t      build_ctype (vtbltype));\n+  set_decl_location (decl->vtblsym, decl);\n+  DECL_LANG_SPECIFIC (decl->vtblsym) = build_lang_decl (NULL);\n+  SET_DECL_ASSEMBLER_NAME (decl->vtblsym, ident);\n+\n+  d_keep (decl->vtblsym);\n+\n+  /* Class is a reference, want the record type.  */\n+  DECL_CONTEXT (decl->vtblsym) = TREE_TYPE (build_ctype (decl->type));\n+  DECL_ARTIFICIAL (decl->vtblsym) = 1;\n+  TREE_STATIC (decl->vtblsym) = 1;\n+  TREE_READONLY (decl->vtblsym) = 1;\n+  DECL_VIRTUAL_P (decl->vtblsym) = 1;","path":"gcc/d/d-decls.cc","position":1214,"original_position":1214,"commit_id":"9462edafe11e773c67da4633dfa80c3d9ec40200","original_commit_id":"9462edafe11e773c67da4633dfa80c3d9ec40200","user":{"login":"jpf91","id":583238,"avatar_url":"https://avatars.githubusercontent.com/u/583238?v=3","gravatar_id":"","url":"https://api.github.com/users/jpf91","html_url":"https://github.com/jpf91","followers_url":"https://api.github.com/users/jpf91/followers","following_url":"https://api.github.com/users/jpf91/following{/other_user}","gists_url":"https://api.github.com/users/jpf91/gists{/gist_id}","starred_url":"https://api.github.com/users/jpf91/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpf91/subscriptions","organizations_url":"https://api.github.com/users/jpf91/orgs","repos_url":"https://api.github.com/users/jpf91/repos","events_url":"https://api.github.com/users/jpf91/events{/privacy}","received_events_url":"https://api.github.com/users/jpf91/received_events","type":"User","site_admin":false},"body":"There's an annoying checking assert in GCC <= 4.9 related to this:\r\n```c++\r\n  /* Vtables are defined by their types and must match no matter of interposition\r\n     rules.  */\r\n  if (DECL_VIRTUAL_P (real_decl))\r\n    {\r\n      gcc_checking_assert (TREE_READONLY (real_decl));\r\n      if (DECL_INITIAL (real_decl))\r\n\treturn DECL_INITIAL (real_decl);\r\n      else\r\n\t{\r\n\t  /* The C++ front end creates VAR_DECLs for vtables of typeinfo\r\n\t     classes not defined in the current TU so that it can refer\r\n\t     to them from typeinfo objects.  Avoid returning NULL_TREE.  */\r\n\t  gcc_checking_assert (!COMPLETE_TYPE_P (DECL_CONTEXT (real_decl)));\r\n\t  return error_mark_node;\r\n\t}\r\n    }\r\n```\r\nI assume I can simply remove the `DECL_VIRTUAL_P (decl->vtblsym) = 1;` line?","created_at":"2016-11-24T21:00:54Z","updated_at":"2016-11-24T21:00:54Z","html_url":"https://github.com/D-Programming-GDC/GDC/pull/243#discussion_r89545865","pull_request_url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243","_links":{"self":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/comments/89545865"},"html":{"href":"https://github.com/D-Programming-GDC/GDC/pull/243#discussion_r89545865"},"pull_request":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243"}}},"pull_request":{"url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243","id":85725428,"html_url":"https://github.com/D-Programming-GDC/GDC/pull/243","diff_url":"https://github.com/D-Programming-GDC/GDC/pull/243.diff","patch_url":"https://github.com/D-Programming-GDC/GDC/pull/243.patch","issue_url":"https://api.github.com/repos/D-Programming-GDC/GDC/issues/243","number":243,"state":"closed","locked":false,"title":"Remove Symbol, FuncFrameInfo, and others in favour of using GCC tree","user":{"login":"ibuclaw","id":397929,"avatar_url":"https://avatars.githubusercontent.com/u/397929?v=3","gravatar_id":"","url":"https://api.github.com/users/ibuclaw","html_url":"https://github.com/ibuclaw","followers_url":"https://api.github.com/users/ibuclaw/followers","following_url":"https://api.github.com/users/ibuclaw/following{/other_user}","gists_url":"https://api.github.com/users/ibuclaw/gists{/gist_id}","starred_url":"https://api.github.com/users/ibuclaw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ibuclaw/subscriptions","organizations_url":"https://api.github.com/users/ibuclaw/orgs","repos_url":"https://api.github.com/users/ibuclaw/repos","events_url":"https://api.github.com/users/ibuclaw/events{/privacy}","received_events_url":"https://api.github.com/users/ibuclaw/received_events","type":"User","site_admin":false},"body":"- [x]  Replace field accesses with macros, so that any changes in the structure only need to be changed in one place, not hundreds.\r\n- [x] Migrate `Symbol` fields into `lang_decl`.  Accessors changed from `(NODE)->xxx` to `(NODE)->Stree->xxx`\r\n- [x] Swap `Symbol` and `tree`, making the `Stree` field the data that is passed around instead.\r\n- [ ] Give macros permanent names.\r\n- [x] Convert `toSymbol` into a visitor.\r\n","created_at":"2016-09-18T22:31:33Z","updated_at":"2016-11-24T21:00:54Z","closed_at":"2016-11-20T14:09:22Z","merged_at":"2016-11-20T14:09:21Z","merge_commit_sha":"30eb55e52b6c10e9d2af1a37c7561154d891d76e","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243/commits","review_comments_url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243/comments","review_comment_url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/comments{/number}","comments_url":"https://api.github.com/repos/D-Programming-GDC/GDC/issues/243/comments","statuses_url":"https://api.github.com/repos/D-Programming-GDC/GDC/statuses/9462edafe11e773c67da4633dfa80c3d9ec40200","head":{"label":"ibuclaw:mvsymbol","ref":"mvsymbol","sha":"9462edafe11e773c67da4633dfa80c3d9ec40200","user":{"login":"ibuclaw","id":397929,"avatar_url":"https://avatars.githubusercontent.com/u/397929?v=3","gravatar_id":"","url":"https://api.github.com/users/ibuclaw","html_url":"https://github.com/ibuclaw","followers_url":"https://api.github.com/users/ibuclaw/followers","following_url":"https://api.github.com/users/ibuclaw/following{/other_user}","gists_url":"https://api.github.com/users/ibuclaw/gists{/gist_id}","starred_url":"https://api.github.com/users/ibuclaw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ibuclaw/subscriptions","organizations_url":"https://api.github.com/users/ibuclaw/orgs","repos_url":"https://api.github.com/users/ibuclaw/repos","events_url":"https://api.github.com/users/ibuclaw/events{/privacy}","received_events_url":"https://api.github.com/users/ibuclaw/received_events","type":"User","site_admin":false},"repo":{"id":9521414,"name":"GDC","full_name":"ibuclaw/GDC","owner":{"login":"ibuclaw","id":397929,"avatar_url":"https://avatars.githubusercontent.com/u/397929?v=3","gravatar_id":"","url":"https://api.github.com/users/ibuclaw","html_url":"https://github.com/ibuclaw","followers_url":"https://api.github.com/users/ibuclaw/followers","following_url":"https://api.github.com/users/ibuclaw/following{/other_user}","gists_url":"https://api.github.com/users/ibuclaw/gists{/gist_id}","starred_url":"https://api.github.com/users/ibuclaw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ibuclaw/subscriptions","organizations_url":"https://api.github.com/users/ibuclaw/orgs","repos_url":"https://api.github.com/users/ibuclaw/repos","events_url":"https://api.github.com/users/ibuclaw/events{/privacy}","received_events_url":"https://api.github.com/users/ibuclaw/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ibuclaw/GDC","description":"GNU D Compiler","fork":true,"url":"https://api.github.com/repos/ibuclaw/GDC","forks_url":"https://api.github.com/repos/ibuclaw/GDC/forks","keys_url":"https://api.github.com/repos/ibuclaw/GDC/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ibuclaw/GDC/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ibuclaw/GDC/teams","hooks_url":"https://api.github.com/repos/ibuclaw/GDC/hooks","issue_events_url":"https://api.github.com/repos/ibuclaw/GDC/issues/events{/number}","events_url":"https://api.github.com/repos/ibuclaw/GDC/events","assignees_url":"https://api.github.com/repos/ibuclaw/GDC/assignees{/user}","branches_url":"https://api.github.com/repos/ibuclaw/GDC/branches{/branch}","tags_url":"https://api.github.com/repos/ibuclaw/GDC/tags","blobs_url":"https://api.github.com/repos/ibuclaw/GDC/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ibuclaw/GDC/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ibuclaw/GDC/git/refs{/sha}","trees_url":"https://api.github.com/repos/ibuclaw/GDC/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ibuclaw/GDC/statuses/{sha}","languages_url":"https://api.github.com/repos/ibuclaw/GDC/languages","stargazers_url":"https://api.github.com/repos/ibuclaw/GDC/stargazers","contributors_url":"https://api.github.com/repos/ibuclaw/GDC/contributors","subscribers_url":"https://api.github.com/repos/ibuclaw/GDC/subscribers","subscription_url":"https://api.github.com/repos/ibuclaw/GDC/subscription","commits_url":"https://api.github.com/repos/ibuclaw/GDC/commits{/sha}","git_commits_url":"https://api.github.com/repos/ibuclaw/GDC/git/commits{/sha}","comments_url":"https://api.github.com/repos/ibuclaw/GDC/comments{/number}","issue_comment_url":"https://api.github.com/repos/ibuclaw/GDC/issues/comments{/number}","contents_url":"https://api.github.com/repos/ibuclaw/GDC/contents/{+path}","compare_url":"https://api.github.com/repos/ibuclaw/GDC/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ibuclaw/GDC/merges","archive_url":"https://api.github.com/repos/ibuclaw/GDC/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ibuclaw/GDC/downloads","issues_url":"https://api.github.com/repos/ibuclaw/GDC/issues{/number}","pulls_url":"https://api.github.com/repos/ibuclaw/GDC/pulls{/number}","milestones_url":"https://api.github.com/repos/ibuclaw/GDC/milestones{/number}","notifications_url":"https://api.github.com/repos/ibuclaw/GDC/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ibuclaw/GDC/labels{/name}","releases_url":"https://api.github.com/repos/ibuclaw/GDC/releases{/id}","deployments_url":"https://api.github.com/repos/ibuclaw/GDC/deployments","created_at":"2013-04-18T12:45:01Z","updated_at":"2016-10-29T08:19:52Z","pushed_at":"2016-11-24T19:34:25Z","git_url":"git://github.com/ibuclaw/GDC.git","ssh_url":"git@github.com:ibuclaw/GDC.git","clone_url":"https://github.com/ibuclaw/GDC.git","svn_url":"https://github.com/ibuclaw/GDC","homepage":"http://gdcproject.org","size":87837,"stargazers_count":2,"watchers_count":2,"language":"D","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":2,"default_branch":"master"}},"base":{"label":"D-Programming-GDC:master","ref":"master","sha":"10001461c2c0989c385cce9fb5da3be29da75f4e","user":{"login":"D-Programming-GDC","id":1551040,"avatar_url":"https://avatars.githubusercontent.com/u/1551040?v=3","gravatar_id":"","url":"https://api.github.com/users/D-Programming-GDC","html_url":"https://github.com/D-Programming-GDC","followers_url":"https://api.github.com/users/D-Programming-GDC/followers","following_url":"https://api.github.com/users/D-Programming-GDC/following{/other_user}","gists_url":"https://api.github.com/users/D-Programming-GDC/gists{/gist_id}","starred_url":"https://api.github.com/users/D-Programming-GDC/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/D-Programming-GDC/subscriptions","organizations_url":"https://api.github.com/users/D-Programming-GDC/orgs","repos_url":"https://api.github.com/users/D-Programming-GDC/repos","events_url":"https://api.github.com/users/D-Programming-GDC/events{/privacy}","received_events_url":"https://api.github.com/users/D-Programming-GDC/received_events","type":"Organization","site_admin":false},"repo":{"id":3759178,"name":"GDC","full_name":"D-Programming-GDC/GDC","owner":{"login":"D-Programming-GDC","id":1551040,"avatar_url":"https://avatars.githubusercontent.com/u/1551040?v=3","gravatar_id":"","url":"https://api.github.com/users/D-Programming-GDC","html_url":"https://github.com/D-Programming-GDC","followers_url":"https://api.github.com/users/D-Programming-GDC/followers","following_url":"https://api.github.com/users/D-Programming-GDC/following{/other_user}","gists_url":"https://api.github.com/users/D-Programming-GDC/gists{/gist_id}","starred_url":"https://api.github.com/users/D-Programming-GDC/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/D-Programming-GDC/subscriptions","organizations_url":"https://api.github.com/users/D-Programming-GDC/orgs","repos_url":"https://api.github.com/users/D-Programming-GDC/repos","events_url":"https://api.github.com/users/D-Programming-GDC/events{/privacy}","received_events_url":"https://api.github.com/users/D-Programming-GDC/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/D-Programming-GDC/GDC","description":"GNU D Compiler","fork":false,"url":"https://api.github.com/repos/D-Programming-GDC/GDC","forks_url":"https://api.github.com/repos/D-Programming-GDC/GDC/forks","keys_url":"https://api.github.com/repos/D-Programming-GDC/GDC/keys{/key_id}","collaborators_url":"https://api.github.com/repos/D-Programming-GDC/GDC/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/D-Programming-GDC/GDC/teams","hooks_url":"https://api.github.com/repos/D-Programming-GDC/GDC/hooks","issue_events_url":"https://api.github.com/repos/D-Programming-GDC/GDC/issues/events{/number}","events_url":"https://api.github.com/repos/D-Programming-GDC/GDC/events","assignees_url":"https://api.github.com/repos/D-Programming-GDC/GDC/assignees{/user}","branches_url":"https://api.github.com/repos/D-Programming-GDC/GDC/branches{/branch}","tags_url":"https://api.github.com/repos/D-Programming-GDC/GDC/tags","blobs_url":"https://api.github.com/repos/D-Programming-GDC/GDC/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/D-Programming-GDC/GDC/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/D-Programming-GDC/GDC/git/refs{/sha}","trees_url":"https://api.github.com/repos/D-Programming-GDC/GDC/git/trees{/sha}","statuses_url":"https://api.github.com/repos/D-Programming-GDC/GDC/statuses/{sha}","languages_url":"https://api.github.com/repos/D-Programming-GDC/GDC/languages","stargazers_url":"https://api.github.com/repos/D-Programming-GDC/GDC/stargazers","contributors_url":"https://api.github.com/repos/D-Programming-GDC/GDC/contributors","subscribers_url":"https://api.github.com/repos/D-Programming-GDC/GDC/subscribers","subscription_url":"https://api.github.com/repos/D-Programming-GDC/GDC/subscription","commits_url":"https://api.github.com/repos/D-Programming-GDC/GDC/commits{/sha}","git_commits_url":"https://api.github.com/repos/D-Programming-GDC/GDC/git/commits{/sha}","comments_url":"https://api.github.com/repos/D-Programming-GDC/GDC/comments{/number}","issue_comment_url":"https://api.github.com/repos/D-Programming-GDC/GDC/issues/comments{/number}","contents_url":"https://api.github.com/repos/D-Programming-GDC/GDC/contents/{+path}","compare_url":"https://api.github.com/repos/D-Programming-GDC/GDC/compare/{base}...{head}","merges_url":"https://api.github.com/repos/D-Programming-GDC/GDC/merges","archive_url":"https://api.github.com/repos/D-Programming-GDC/GDC/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/D-Programming-GDC/GDC/downloads","issues_url":"https://api.github.com/repos/D-Programming-GDC/GDC/issues{/number}","pulls_url":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls{/number}","milestones_url":"https://api.github.com/repos/D-Programming-GDC/GDC/milestones{/number}","notifications_url":"https://api.github.com/repos/D-Programming-GDC/GDC/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/D-Programming-GDC/GDC/labels{/name}","releases_url":"https://api.github.com/repos/D-Programming-GDC/GDC/releases{/id}","deployments_url":"https://api.github.com/repos/D-Programming-GDC/GDC/deployments","created_at":"2012-03-19T00:16:44Z","updated_at":"2016-11-06T09:16:55Z","pushed_at":"2016-11-24T19:34:23Z","git_url":"git://github.com/D-Programming-GDC/GDC.git","ssh_url":"git@github.com:D-Programming-GDC/GDC.git","clone_url":"https://github.com/D-Programming-GDC/GDC.git","svn_url":"https://github.com/D-Programming-GDC/GDC","homepage":"http://gdcproject.org","size":91383,"stargazers_count":283,"watchers_count":283,"language":"D","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":49,"mirror_url":null,"open_issues_count":13,"forks":49,"open_issues":13,"watchers":283,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243"},"html":{"href":"https://github.com/D-Programming-GDC/GDC/pull/243"},"issue":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/issues/243"},"comments":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/issues/243/comments"},"review_comments":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243/comments"},"review_comment":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/pulls/243/commits"},"statuses":{"href":"https://api.github.com/repos/D-Programming-GDC/GDC/statuses/9462edafe11e773c67da4633dfa80c3d9ec40200"}}}}
{"actor":{"display_login":"jpf91"}}