d: Merge dmd, druntime d8e3976a58, phobos 7a6e95688
[official-gcc.git] / gcc / d / dmd / dimport.d
blobb083c03aebeeee3504b7cef03990c9bb57ccfef9
1 /**
2 * A `Dsymbol` representing a renamed import.
4 * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d)
8 * Documentation: https://dlang.org/phobos/dmd_dimport.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dimport.d
12 module dmd.dimport;
14 import dmd.arraytypes;
15 import dmd.astenums;
16 import dmd.declaration;
17 import dmd.dmodule;
18 import dmd.dscope;
19 import dmd.dsymbol;
20 import dmd.dsymbolsem;
21 import dmd.errors;
22 import dmd.expression;
23 import dmd.globals;
24 import dmd.identifier;
25 import dmd.location;
26 import dmd.mtype;
27 import dmd.visitor;
29 import core.stdc.stdio;
30 /***********************************************************
32 extern (C++) final class Import : Dsymbol
34 /* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2;
36 Identifier[] packages; // array of Identifier's representing packages
37 Identifier id; // module Identifier
38 Identifier aliasId;
39 int isstatic; // !=0 if static import
40 Visibility visibility;
42 // Pairs of alias=name to bind into current namespace
43 Identifiers names;
44 Identifiers aliases;
46 Module mod;
47 Package pkg; // leftmost package/module
49 // corresponding AliasDeclarations for alias=name pairs
50 AliasDeclarations aliasdecls;
52 extern (D) this(const ref Loc loc, Identifier[] packages, Identifier id, Identifier aliasId, int isstatic)
54 Identifier selectIdent()
56 // select Dsymbol identifier (bracketed)
57 if (aliasId)
59 // import [aliasId] = std.stdio;
60 return aliasId;
62 else if (packages.length > 0)
64 // import [std].stdio;
65 return packages[0];
67 else
69 // import [id];
70 return id;
74 super(loc, selectIdent());
76 assert(id);
77 version (none)
79 printf("Import::Import(");
80 foreach (id; packages)
82 printf("%s.", id.toChars());
84 printf("%s)\n", id.toChars());
86 this.packages = packages;
87 this.id = id;
88 this.aliasId = aliasId;
89 this.isstatic = isstatic;
90 this.visibility = Visibility.Kind.private_; // default to private
93 extern (D) void addAlias(Identifier name, Identifier _alias)
95 if (isstatic)
96 .error(loc, "%s `%s` cannot have an import bind list", kind, toPrettyChars);
97 if (!aliasId)
98 this.ident = null; // make it an anonymous import
99 names.push(name);
100 aliases.push(_alias);
103 override const(char)* kind() const
105 return isstatic ? "static import" : "import";
108 override Visibility visible() pure nothrow @nogc @safe
110 return visibility;
113 // copy only syntax trees
114 override Import syntaxCopy(Dsymbol s)
116 assert(!s);
117 auto si = new Import(loc, packages, id, aliasId, isstatic);
118 si.comment = comment;
119 for (size_t i = 0; i < names.length; i++)
121 si.addAlias(names[i], aliases[i]);
123 return si;
126 /*******************************
127 * Load this module.
128 * Returns:
129 * true for errors, false for success
131 extern (D) bool load(Scope* sc)
133 //printf("Import::load('%s') %p\n", toPrettyChars(), this);
134 // See if existing module
135 const errors = global.errors;
136 DsymbolTable dst = Package.resolve(packages, null, &pkg);
137 version (none)
139 if (pkg && pkg.isModule())
141 .error(loc, "can only import from a module, not from a member of module `%s`. Did you mean `import %s : %s`?", pkg.toChars(), pkg.toPrettyChars(), id.toChars());
142 mod = pkg.isModule(); // Error recovery - treat as import of that module
143 return true;
146 Dsymbol s = dst.lookup(id);
147 if (s)
149 if (s.isModule())
150 mod = cast(Module)s;
151 else
153 if (s.isAliasDeclaration())
155 .error(loc, "%s `%s` conflicts with `%s`", s.kind(), s.toPrettyChars(), id.toChars());
157 else if (Package p = s.isPackage())
159 if (p.isPkgMod == PKG.unknown)
161 uint preverrors = global.errors;
162 mod = Module.load(loc, packages, id);
163 if (!mod)
164 p.isPkgMod = PKG.package_;
165 else
167 // mod is a package.d, or a normal module which conflicts with the package name.
168 if (mod.isPackageFile)
169 mod.tag = p.tag; // reuse the same package tag
170 else
172 // show error if Module.load does not
173 if (preverrors == global.errors)
174 .error(loc, "%s `%s` from file %s conflicts with %s `%s`", mod.kind(), mod.toPrettyChars(), mod.srcfile.toChars, p.kind(), p.toPrettyChars());
175 return true;
179 else
181 mod = p.isPackageMod();
183 if (!mod)
185 .error(loc, "can only import from a module, not from package `%s.%s`", p.toPrettyChars(), id.toChars());
188 else if (pkg)
190 .error(loc, "can only import from a module, not from package `%s.%s`", pkg.toPrettyChars(), id.toChars());
192 else
194 .error(loc, "can only import from a module, not from package `%s`", id.toChars());
198 if (!mod)
200 // Load module
201 mod = Module.load(loc, packages, id);
202 if (mod)
204 // id may be different from mod.ident, if so then insert alias
205 dst.insert(id, mod);
208 if (mod && !mod.importedFrom)
209 mod.importedFrom = sc ? sc._module.importedFrom : Module.rootModule;
210 if (!pkg)
212 if (mod && mod.isPackageFile)
214 // one level depth package.d file (import pkg; ./pkg/package.d)
215 // it's necessary to use the wrapping Package already created
216 pkg = mod.pkg;
218 else
219 pkg = mod;
221 //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
222 return global.errors != errors;
225 /*******************************
226 * Mark the imported packages as accessible from the current
227 * scope. This access check is necessary when using FQN b/c
228 * we're using a single global package tree.
229 * https://issues.dlang.org/show_bug.cgi?id=313
231 extern (D) void addPackageAccess(ScopeDsymbol scopesym)
233 //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this);
234 if (packages.length > 0)
236 // import a.b.c.d;
237 auto p = pkg; // a
238 scopesym.addAccessiblePackage(p, visibility);
239 foreach (id; packages[1 .. $]) // [b, c]
241 auto sym = p.symtab.lookup(id);
242 // https://issues.dlang.org/show_bug.cgi?id=17991
243 // An import of truly empty file/package can happen
244 // https://issues.dlang.org/show_bug.cgi?id=20151
245 // Package in the path conflicts with a module name
246 if (sym is null)
247 break;
248 // https://issues.dlang.org/show_bug.cgi?id=23327
249 // Package conflicts with symbol of the same name
250 p = sym.isPackage();
251 if (p is null)
252 break;
253 scopesym.addAccessiblePackage(p, visibility);
256 scopesym.addAccessiblePackage(mod, visibility); // d
259 override Dsymbol toAlias()
261 if (aliasId)
262 return mod;
263 return this;
266 override bool overloadInsert(Dsymbol s)
268 /* Allow multiple imports with the same package base, but disallow
269 * alias collisions
270 * https://issues.dlang.org/show_bug.cgi?id=5412
272 assert(ident && ident == s.ident);
273 Import imp;
274 if (!aliasId && (imp = s.isImport()) !is null && !imp.aliasId)
275 return true;
276 else
277 return false;
280 override inout(Import) isImport() inout
282 return this;
285 override void accept(Visitor v)
287 v.visit(this);