]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/dimport.c
d: Merge upstream dmd 7132b3537
[thirdparty/gcc.git] / gcc / d / dmd / dimport.c
CommitLineData
b4c522fa
IB
1
2/* Compiler implementation of the D programming language
a3b38b77 3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
b4c522fa
IB
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/import.c
9 */
10
f9ab59ff 11#include "root/dsystem.h"
b4c522fa 12#include "root/root.h"
f9ab59ff 13
b4c522fa
IB
14#include "mars.h"
15#include "dsymbol.h"
16#include "import.h"
17#include "identifier.h"
18#include "module.h"
19#include "scope.h"
20#include "mtype.h"
21#include "declaration.h"
22#include "id.h"
23#include "attrib.h"
24#include "hdrgen.h"
25
26/********************************* Import ****************************/
27
28Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
29 int isstatic)
30 : Dsymbol(NULL)
31{
32 assert(id);
33 this->loc = loc;
34 this->packages = packages;
35 this->id = id;
36 this->aliasId = aliasId;
37 this->isstatic = isstatic;
0a2ee409 38 this->protection = Prot(Prot::private_); // default to private
b4c522fa
IB
39 this->pkg = NULL;
40 this->mod = NULL;
41
42 // Set symbol name (bracketed)
43 if (aliasId)
44 {
45 // import [cstdio] = std.stdio;
46 this->ident = aliasId;
47 }
2cbc99d1 48 else if (packages && packages->length)
b4c522fa
IB
49 {
50 // import [std].stdio;
51 this->ident = (*packages)[0];
52 }
53 else
54 {
55 // import [foo];
56 this->ident = id;
57 }
58}
59
60void Import::addAlias(Identifier *name, Identifier *alias)
61{
62 if (isstatic)
63 error("cannot have an import bind list");
64
65 if (!aliasId)
66 this->ident = NULL; // make it an anonymous import
67
68 names.push(name);
69 aliases.push(alias);
70}
71
f9ab59ff 72const char *Import::kind() const
b4c522fa
IB
73{
74 return isstatic ? "static import" : "import";
75}
76
77Prot Import::prot()
78{
79 return protection;
80}
81
82Dsymbol *Import::syntaxCopy(Dsymbol *s)
83{
84 assert(!s);
85
86 Import *si = new Import(loc, packages, id, aliasId, isstatic);
87
2cbc99d1 88 for (size_t i = 0; i < names.length; i++)
b4c522fa
IB
89 {
90 si->addAlias(names[i], aliases[i]);
91 }
92
93 return si;
94}
95
96void Import::load(Scope *sc)
97{
98 //printf("Import::load('%s') %p\n", toPrettyChars(), this);
99
100 // See if existing module
101 DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
102 Dsymbol *s = dst->lookup(id);
103 if (s)
104 {
105 if (s->isModule())
106 mod = (Module *)s;
107 else
108 {
109 if (s->isAliasDeclaration())
110 {
111 ::error(loc, "%s %s conflicts with %s", s->kind(), s->toPrettyChars(), id->toChars());
112 }
113 else if (Package *p = s->isPackage())
114 {
115 if (p->isPkgMod == PKGunknown)
116 {
117 mod = Module::load(loc, packages, id);
118 if (!mod)
119 p->isPkgMod = PKGpackage;
120 else
121 {
122 // mod is a package.d, or a normal module which conflicts with the package name.
123 assert(mod->isPackageFile == (p->isPkgMod == PKGmodule));
124 if (mod->isPackageFile)
125 mod->tag = p->tag; // reuse the same package tag
126 }
127 }
128 else
129 {
130 mod = p->isPackageMod();
131 }
132 if (!mod)
133 {
134 ::error(loc, "can only import from a module, not from package %s.%s",
135 p->toPrettyChars(), id->toChars());
136 }
137 }
138 else if (pkg)
139 {
140 ::error(loc, "can only import from a module, not from package %s.%s",
141 pkg->toPrettyChars(), id->toChars());
142 }
143 else
144 {
145 ::error(loc, "can only import from a module, not from package %s",
146 id->toChars());
147 }
148 }
149 }
150
151 if (!mod)
152 {
153 // Load module
154 mod = Module::load(loc, packages, id);
155 if (mod)
156 {
157 dst->insert(id, mod); // id may be different from mod->ident,
158 // if so then insert alias
159 }
160 }
161 if (mod && !mod->importedFrom)
162 mod->importedFrom = sc ? sc->_module->importedFrom : Module::rootModule;
163 if (!pkg)
164 pkg = mod;
165
166 //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
167}
168
169void Import::importAll(Scope *sc)
170{
171 if (!mod)
172 {
173 load(sc);
174 if (mod) // if successfully loaded module
175 {
42a84c28
IB
176 mod->importAll(NULL);
177
b4c522fa
IB
178 if (mod->md && mod->md->isdeprecated)
179 {
180 Expression *msg = mod->md->msg;
181 if (StringExp *se = msg ? msg->toStringExp() : NULL)
182 mod->deprecation(loc, "is deprecated - %s", se->string);
183 else
184 mod->deprecation(loc, "is deprecated");
185 }
186
b4c522fa
IB
187 if (sc->explicitProtection)
188 protection = sc->protection;
2cbc99d1 189 if (!isstatic && !aliasId && !names.length)
b4c522fa
IB
190 {
191 sc->scopesym->importScope(mod, protection);
192 }
193 }
194 }
195}
196
b4c522fa
IB
197Dsymbol *Import::toAlias()
198{
199 if (aliasId)
200 return mod;
201 return this;
202}
203
204/*****************************
205 * Add import to sd's symbol table.
206 */
207
208void Import::addMember(Scope *sc, ScopeDsymbol *sd)
209{
210 //printf("Import::addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd->toChars(), sc);
2cbc99d1 211 if (names.length == 0)
b4c522fa
IB
212 return Dsymbol::addMember(sc, sd);
213
214 if (aliasId)
215 Dsymbol::addMember(sc, sd);
216
217 /* Instead of adding the import to sd's symbol table,
218 * add each of the alias=name pairs
219 */
2cbc99d1 220 for (size_t i = 0; i < names.length; i++)
b4c522fa
IB
221 {
222 Identifier *name = names[i];
223 Identifier *alias = aliases[i];
224
225 if (!alias)
226 alias = name;
227
228 TypeIdentifier *tname = new TypeIdentifier(loc, name);
229 AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
230 ad->_import = this;
231 ad->addMember(sc, sd);
232
233 aliasdecls.push(ad);
234 }
235}
236
237void Import::setScope(Scope *sc)
238{
239 Dsymbol::setScope(sc);
2cbc99d1 240 if (aliasdecls.length)
b4c522fa
IB
241 {
242 if (!mod)
243 importAll(sc);
244
245 sc = sc->push(mod);
246 sc->protection = protection;
2cbc99d1 247 for (size_t i = 0; i < aliasdecls.length; i++)
b4c522fa
IB
248 {
249 AliasDeclaration *ad = aliasdecls[i];
250 ad->setScope(sc);
251 }
252 sc = sc->pop();
253 }
254}
255
256Dsymbol *Import::search(const Loc &loc, Identifier *ident, int flags)
257{
258 //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
259
260 if (!pkg)
261 {
262 load(NULL);
263 mod->importAll(NULL);
a3b38b77 264 dsymbolSemantic(mod, NULL);
b4c522fa
IB
265 }
266
267 // Forward it to the package/module
268 return pkg->search(loc, ident, flags);
269}
270
271bool Import::overloadInsert(Dsymbol *s)
272{
273 /* Allow multiple imports with the same package base, but disallow
274 * alias collisions (Bugzilla 5412).
275 */
276 assert(ident && ident == s->ident);
277 Import *imp;
278 if (!aliasId && (imp = s->isImport()) != NULL && !imp->aliasId)
279 return true;
280 else
281 return false;
282}