1/* imports.cc -- Build imported modules/declarations.
2   Copyright (C) 2014-2020 Free Software Foundation, Inc.
3
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with GCC; see the file COPYING3.  If not see
16<http://www.gnu.org/licenses/>.  */
17
18#include "config.h"
19#include "system.h"
20#include "coretypes.h"
21
22#include "dmd/aggregate.h"
23#include "dmd/declaration.h"
24#include "dmd/enum.h"
25#include "dmd/identifier.h"
26#include "dmd/import.h"
27#include "dmd/module.h"
28
29#include "tree.h"
30#include "stringpool.h"
31
32#include "d-tree.h"
33
34
35/* Implements the visitor interface to build debug trees for all
36   module and import declarations, where ISYM holds the cached
37   back-end representation to be returned.  */
38class ImportVisitor : public Visitor
39{
40  using Visitor::visit;
41
42  /* Build the declaration DECL as an imported symbol.  */
43  tree make_import (tree decl)
44  {
45    gcc_assert (decl != NULL_TREE);
46
47    tree import = build_decl (input_location, IMPORTED_DECL,
48			      DECL_NAME (decl), void_type_node);
49    IMPORTED_DECL_ASSOCIATED_DECL (import) = decl;
50    d_keep (import);
51
52    return import;
53  }
54
55public:
56  ImportVisitor (void)
57  {
58  }
59
60  /* This should be overridden by each symbol class.  */
61  void visit (Dsymbol *)
62  {
63    gcc_unreachable ();
64  }
65
66  /* Build the module decl for M, this is considered toplevel, regardless
67     of whether there are any parent packages in the module system.  */
68  void visit (Module *m)
69  {
70    Loc loc = (m->md != NULL) ? m->md->loc
71      : Loc (m->srcfile->toChars (), 1, 0);
72
73    m->isym = build_decl (make_location_t (loc), NAMESPACE_DECL,
74			  get_identifier (m->toPrettyChars ()),
75			  void_type_node);
76    d_keep (m->isym);
77
78    if (!m->isRoot ())
79      DECL_EXTERNAL (m->isym) = 1;
80
81    TREE_PUBLIC (m->isym) = 1;
82    DECL_CONTEXT (m->isym) = NULL_TREE;
83  }
84
85  /* Build an import of another module symbol.  */
86
87  void visit (Import *m)
88  {
89    tree module = build_import_decl (m->mod);
90    m->isym = this->make_import (module);
91  }
92
93  /* Build an import for any kind of user defined type.
94     Use the TYPE_DECL associated with the type symbol.  */
95  void visit (EnumDeclaration *d)
96  {
97    tree type = build_ctype (d->type);
98    /* Not all kinds of D enums create a TYPE_DECL.  */
99    if (TREE_CODE (type) == ENUMERAL_TYPE)
100      {
101	type = TYPE_MAIN_VARIANT (type);
102	d->isym = this->make_import (TYPE_STUB_DECL (type));
103      }
104
105  }
106
107  void visit (AggregateDeclaration *d)
108  {
109    tree type = build_ctype (d->type);
110    type = TYPE_MAIN_VARIANT (type);
111    d->isym = this->make_import (TYPE_STUB_DECL (type));
112  }
113
114  void visit (ClassDeclaration *d)
115  {
116    /* Want the RECORD_TYPE, not POINTER_TYPE.  */
117    tree type = TREE_TYPE (build_ctype (d->type));
118    type = TYPE_MAIN_VARIANT (type);
119    d->isym = this->make_import (TYPE_STUB_DECL (type));
120  }
121
122  /* For now, ignore importing other kinds of dsymbols.  */
123  void visit (ScopeDsymbol *)
124  {
125  }
126
127  /* Alias symbols aren't imported, but their targets are.  */
128  void visit (AliasDeclaration *d)
129  {
130    Dsymbol *dsym = d->toAlias ();
131
132    if (dsym == d)
133      {
134	Type *type = d->getType ();
135
136	/* Type imports should really be part of their own visit method.  */
137	if (type != NULL)
138	  {
139	    if (type->ty == Tenum)
140	      dsym = ((TypeEnum *) type)->sym;
141	    else if (type->ty == Tstruct)
142	      dsym = ((TypeStruct *) type)->sym;
143	    else if (type->ty == Tclass)
144	      dsym = ((TypeClass *) type)->sym;
145	  }
146      }
147
148    /* This symbol is really an alias for another, visit the other.  */
149    if (dsym != d)
150      {
151	dsym->accept (this);
152	d->isym = dsym->isym;
153      }
154  }
155
156  /* Visit the underlying alias symbol of overloadable aliases.  */
157  void visit (OverDeclaration *d)
158  {
159    if (d->aliassym != NULL)
160      {
161	d->aliassym->accept (this);
162	d->isym = d->aliassym->isym;
163      }
164  }
165
166  /* Build IMPORTED_DECLs for all overloads in a set.  */
167  void visit (OverloadSet *d)
168  {
169    vec<tree, va_gc> *tset = NULL;
170
171    vec_alloc (tset, d->a.dim);
172
173    for (size_t i = 0; i < d->a.dim; i++)
174      vec_safe_push (tset, build_import_decl (d->a[i]));
175
176    d->isym = build_tree_list_vec (tset);
177    tset->truncate (0);
178  }
179
180  /* Function aliases are the same as alias symbols.  */
181  void visit (FuncAliasDeclaration *d)
182  {
183    FuncDeclaration *fd = d->toAliasFunc ();
184
185    if (fd != NULL)
186      {
187	fd->accept (this);
188	d->isym = fd->isym;
189      }
190  }
191
192  /* Skip over importing templates and tuples.  */
193  void visit (TemplateDeclaration *)
194  {
195  }
196
197  void visit (TupleDeclaration *)
198  {
199  }
200
201  /* Import any other kind of declaration.  If the class does not implement
202     symbol generation routines, the compiler will throw an error.  */
203  void visit (Declaration *d)
204  {
205    d->isym = this->make_import (get_symbol_decl (d));
206  }
207};
208
209
210/* Build a declaration for the symbol D that can be used for the
211   debug_hook imported_module_or_decl.  */
212tree
213build_import_decl (Dsymbol *d)
214{
215  if (!d->isym)
216    {
217      location_t saved_location = input_location;
218      ImportVisitor v;
219
220      input_location = make_location_t (d->loc);
221      d->accept (&v);
222      input_location = saved_location;
223    }
224
225  /* Not all visitors set 'isym'.  */
226  return d->isym ? d->isym : NULL_TREE;
227}
228
229