/* imports.cc -- Build imported modules/declarations.
   Copyright (C) 2014-2021 Free Software Foundation, Inc.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"

#include "dmd/aggregate.h"
#include "dmd/declaration.h"
#include "dmd/enum.h"
#include "dmd/identifier.h"
#include "dmd/import.h"
#include "dmd/module.h"

#include "tree.h"
#include "stringpool.h"

#include "d-tree.h"


/* Implements the visitor interface to build debug trees for all
   module and import declarations, where ISYM holds the cached
   back-end representation to be returned.  */
class ImportVisitor : public Visitor
{
  using Visitor::visit;

  /* Build the declaration DECL as an imported symbol.  */
  tree make_import (tree decl)
  {
    gcc_assert (decl != NULL_TREE);

    tree import = build_decl (input_location, IMPORTED_DECL,
			      DECL_NAME (decl), void_type_node);
    IMPORTED_DECL_ASSOCIATED_DECL (import) = decl;
    d_keep (import);

    return import;
  }

public:
  ImportVisitor (void)
  {
  }

  /* This should be overridden by each symbol class.  */
  void visit (Dsymbol *)
  {
    gcc_unreachable ();
  }

  /* Build the module decl for M, this is considered toplevel, regardless
     of whether there are any parent packages in the module system.  */
  void visit (Module *m)
  {
    Loc loc = (m->md != NULL) ? m->md->loc
      : Loc (m->srcfile->toChars (), 1, 0);

    m->isym = build_decl (make_location_t (loc), NAMESPACE_DECL,
			  get_identifier (m->toPrettyChars ()),
			  void_type_node);
    d_keep (m->isym);

    if (!m->isRoot ())
      DECL_EXTERNAL (m->isym) = 1;

    TREE_PUBLIC (m->isym) = 1;
    DECL_CONTEXT (m->isym) = NULL_TREE;
  }

  /* Build an import of another module symbol.  */

  void visit (Import *m)
  {
    tree module = build_import_decl (m->mod);
    m->isym = this->make_import (module);
  }

  /* Build an import for any kind of user defined type.
     Use the TYPE_DECL associated with the type symbol.  */
  void visit (EnumDeclaration *d)
  {
    tree type = build_ctype (d->type);
    /* Not all kinds of D enums create a TYPE_DECL.  */
    if (TREE_CODE (type) == ENUMERAL_TYPE)
      d->isym = this->make_import (TYPE_STUB_DECL (type));
  }

  void visit (AggregateDeclaration *d)
  {
    tree type = build_ctype (d->type);
    d->isym = this->make_import (TYPE_STUB_DECL (type));
  }

  void visit (ClassDeclaration *d)
  {
    /* Want the RECORD_TYPE, not POINTER_TYPE.  */
    tree type = TREE_TYPE (build_ctype (d->type));
    d->isym = this->make_import (TYPE_STUB_DECL (type));
  }

  /* For now, ignore importing other kinds of dsymbols.  */
  void visit (ScopeDsymbol *)
  {
  }

  /* Alias symbols aren't imported, but their targets are.  */
  void visit (AliasDeclaration *d)
  {
    Dsymbol *dsym = d->toAlias ();

    if (dsym == d)
      {
	Type *type = d->getType ();

	/* Type imports should really be part of their own visit method.  */
	if (type != NULL)
	  {
	    if (type->ty == Tenum)
	      dsym = type->isTypeEnum ()->sym;
	    else if (type->ty == Tstruct)
	      dsym = type->isTypeStruct ()->sym;
	    else if (type->ty == Tclass)
	      dsym = type->isTypeClass ()->sym;
	  }
      }

    /* This symbol is really an alias for another, visit the other.  */
    if (dsym != d)
      {
	dsym->accept (this);
	d->isym = dsym->isym;
      }
  }

  /* Visit the underlying alias symbol of overloadable aliases.  */
  void visit (OverDeclaration *d)
  {
    if (d->aliassym != NULL)
      {
	d->aliassym->accept (this);
	d->isym = d->aliassym->isym;
      }
  }

  /* Function aliases are the same as alias symbols.  */
  void visit (FuncAliasDeclaration *d)
  {
    FuncDeclaration *fd = d->toAliasFunc ();

    if (fd != NULL)
      {
	fd->accept (this);
	d->isym = fd->isym;
      }
  }

  /* Skip over importing templates and tuples.  */
  void visit (TemplateDeclaration *)
  {
  }

  void visit (TupleDeclaration *)
  {
  }

  /* Import any other kind of declaration.  If the class does not implement
     symbol generation routines, the compiler will throw an error.  */
  void visit (Declaration *d)
  {
    d->isym = this->make_import (get_symbol_decl (d));
  }
};


/* Build a declaration for the symbol D that can be used for the
   debug_hook imported_module_or_decl.  */
tree
build_import_decl (Dsymbol *d)
{
  if (!d->isym)
    {
      location_t saved_location = input_location;
      ImportVisitor v;

      input_location = make_location_t (d->loc);
      d->accept (&v);
      input_location = saved_location;
    }

  /* Not all visitors set `isym'.  */
  return d->isym ? d->isym : NULL_TREE;
}

