209 lines
5.1 KiB
C++
209 lines
5.1 KiB
C++
/* 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;
|
|
}
|
|
|