]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/dmodule.c
ipa-param-manip: Be careful about a reallocating hash_map
[thirdparty/gcc.git] / gcc / d / dmd / dmodule.c
1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
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/module.c
9 */
10
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13
14 #include "mars.h"
15 #include "module.h"
16 #include "parse.h"
17 #include "scope.h"
18 #include "identifier.h"
19 #include "id.h"
20 #include "import.h"
21 #include "dsymbol.h"
22 #include "expression.h"
23 #include "lexer.h"
24 #include "attrib.h"
25
26 AggregateDeclaration *Module::moduleinfo;
27
28 Module *Module::rootModule;
29 DsymbolTable *Module::modules;
30 Modules Module::amodules;
31
32 Dsymbols Module::deferred; // deferred Dsymbol's needing semantic() run on them
33 Dsymbols Module::deferred2; // deferred Dsymbol's needing semantic2() run on them
34 Dsymbols Module::deferred3; // deferred Dsymbol's needing semantic3() run on them
35 unsigned Module::dprogress;
36
37 void Module::_init()
38 {
39 modules = new DsymbolTable();
40 }
41
42 Module::Module(const char *filename, Identifier *ident, int doDocComment, int doHdrGen)
43 : Package(ident)
44 {
45 const char *srcfilename;
46
47 // printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
48 this->arg = filename;
49 md = NULL;
50 errors = 0;
51 numlines = 0;
52 members = NULL;
53 isDocFile = 0;
54 isPackageFile = false;
55 pkg = NULL;
56 needmoduleinfo = 0;
57 selfimports = 0;
58 rootimports = 0;
59 insearch = 0;
60 searchCacheIdent = NULL;
61 searchCacheSymbol = NULL;
62 searchCacheFlags = 0;
63 decldefs = NULL;
64 sictor = NULL;
65 sctor = NULL;
66 sdtor = NULL;
67 ssharedctor = NULL;
68 sshareddtor = NULL;
69 stest = NULL;
70 sfilename = NULL;
71 importedFrom = NULL;
72 srcfile = NULL;
73 docfile = NULL;
74
75 debuglevel = 0;
76 debugids = NULL;
77 debugidsNot = NULL;
78 versionlevel = 0;
79 versionids = NULL;
80 versionidsNot = NULL;
81
82 macrotable = NULL;
83 escapetable = NULL;
84 doppelganger = 0;
85 cov = NULL;
86 covb = NULL;
87
88 nameoffset = 0;
89 namelen = 0;
90
91 srcfilename = FileName::defaultExt(filename, global.mars_ext.ptr);
92
93 if (global.run_noext && global.params.run &&
94 !FileName::ext(filename) &&
95 FileName::exists(srcfilename) == 0 &&
96 FileName::exists(filename) == 1)
97 {
98 FileName::free(srcfilename);
99 srcfilename = FileName::removeExt(filename); // just does a mem.strdup(filename)
100 }
101 else if (!FileName::equalsExt(srcfilename, global.mars_ext.ptr) &&
102 !FileName::equalsExt(srcfilename, global.hdr_ext.ptr) &&
103 !FileName::equalsExt(srcfilename, "dd"))
104 {
105 error("source file name '%s' must have .%s extension", srcfilename, global.mars_ext);
106 fatal();
107 }
108 srcfile = new File(srcfilename);
109 objfile = setOutfile(global.params.objname.ptr, global.params.objdir.ptr, filename, global.obj_ext.ptr);
110
111 if (doDocComment)
112 setDocfile();
113
114 if (doHdrGen)
115 hdrfile = setOutfile(global.params.hdrname.ptr, global.params.hdrdir.ptr, arg, global.hdr_ext.ptr);
116
117 //objfile = new File(objfilename);
118 }
119
120 Module *Module::create(const char *filename, Identifier *ident, int doDocComment, int doHdrGen)
121 {
122 return new Module(filename, ident, doDocComment, doHdrGen);
123 }
124
125 void Module::setDocfile()
126 {
127 docfile = setOutfile(global.params.docname.ptr, global.params.docdir.ptr, arg, global.doc_ext.ptr);
128 }
129
130 /*********************************************
131 * Combines things into output file name for .html and .di files.
132 * Input:
133 * name Command line name given for the file, NULL if none
134 * dir Command line directory given for the file, NULL if none
135 * arg Name of the source file
136 * ext File name extension to use if 'name' is NULL
137 * global.params.preservePaths get output path from arg
138 * srcfile Input file - output file name must not match input file
139 */
140
141 File *Module::setOutfile(const char *name, const char *dir, const char *arg, const char *ext)
142 {
143 const char *docfilename;
144
145 if (name)
146 {
147 docfilename = name;
148 }
149 else
150 {
151 const char *argdoc;
152 if (global.params.preservePaths)
153 argdoc = arg;
154 else
155 argdoc = FileName::name(arg);
156
157 // If argdoc doesn't have an absolute path, make it relative to dir
158 if (!FileName::absolute(argdoc))
159 { //FileName::ensurePathExists(dir);
160 argdoc = FileName::combine(dir, argdoc);
161 }
162 docfilename = FileName::forceExt(argdoc, ext);
163 }
164
165 if (FileName::equals(docfilename, srcfile->name->str))
166 {
167 error("source file and output file have same name '%s'", srcfile->name->str);
168 fatal();
169 }
170
171 return new File(docfilename);
172 }
173
174 void Module::deleteObjFile()
175 {
176 if (global.params.obj)
177 objfile->remove();
178 if (docfile)
179 docfile->remove();
180 }
181
182 const char *Module::kind() const
183 {
184 return "module";
185 }
186
187 static void checkModFileAlias(OutBuffer *buf, OutBuffer *dotmods,
188 Array<const char *> *ms, size_t msdim, const char *p)
189 {
190 /* Check and replace the contents of buf[] with
191 * an alias string from global.params.modFileAliasStrings[]
192 */
193 dotmods->writestring(p);
194 for (size_t j = msdim; j--;)
195 {
196 const char *m = (*ms)[j];
197 const char *q = strchr(m, '=');
198 assert(q);
199 if (dotmods->length() == (size_t)(q - m) && memcmp(dotmods->peekChars(), m, q - m) == 0)
200 {
201 buf->reset();
202 size_t qlen = strlen(q + 1);
203 if (qlen && (q[qlen] == '/' || q[qlen] == '\\'))
204 --qlen; // remove trailing separator
205 buf->write(q + 1, qlen);
206 break; // last matching entry in ms[] wins
207 }
208 }
209 dotmods->writeByte('.');
210 }
211
212 /**
213 * Converts a chain of identifiers to the filename of the module
214 *
215 * Params:
216 * packages = the names of the "parent" packages
217 * ident = the name of the child package or module
218 *
219 * Returns:
220 * the filename of the child package or module
221 */
222 static const char *getFilename(Identifiers *packages, Identifier *ident)
223 {
224 const char *filename = ident->toChars();
225
226 if (packages == NULL || packages->length == 0)
227 return filename;
228
229 OutBuffer buf;
230 OutBuffer dotmods;
231 Array<const char *> *ms = &global.params.modFileAliasStrings;
232 const size_t msdim = ms ? ms->length : 0;
233
234 for (size_t i = 0; i < packages->length; i++)
235 {
236 Identifier *pid = (*packages)[i];
237 const char *p = pid->toChars();
238 buf.writestring(p);
239 if (msdim)
240 checkModFileAlias(&buf, &dotmods, ms, msdim, p);
241 #if _WIN32
242 buf.writeByte('\\');
243 #else
244 buf.writeByte('/');
245 #endif
246 }
247 buf.writestring(filename);
248 if (msdim)
249 checkModFileAlias(&buf, &dotmods, ms, msdim, filename);
250 buf.writeByte(0);
251 filename = (char *)buf.extractData();
252
253 return filename;
254 }
255
256 /********************************************
257 * Look for the source file if it's different from filename.
258 * Look for .di, .d, directory, and along global.path.
259 * Does not open the file.
260 * Input:
261 * filename as supplied by the user
262 * global.path
263 * Returns:
264 * NULL if it's not different from filename.
265 */
266
267 static const char *lookForSourceFile(const char *filename)
268 {
269 /* Search along global.path for .di file, then .d file.
270 */
271 const char *sdi = FileName::forceExt(filename, global.hdr_ext.ptr);
272 if (FileName::exists(sdi) == 1)
273 return sdi;
274
275 const char *sd = FileName::forceExt(filename, global.mars_ext.ptr);
276 if (FileName::exists(sd) == 1)
277 return sd;
278
279 if (FileName::exists(filename) == 2)
280 {
281 /* The filename exists and it's a directory.
282 * Therefore, the result should be: filename/package.d
283 * iff filename/package.d is a file
284 */
285 const char *ni = FileName::combine(filename, "package.di");
286 if (FileName::exists(ni) == 1)
287 return ni;
288 FileName::free(ni);
289 const char *n = FileName::combine(filename, "package.d");
290 if (FileName::exists(n) == 1)
291 return n;
292 FileName::free(n);
293 }
294
295 if (FileName::absolute(filename))
296 return NULL;
297
298 if (!global.path)
299 return NULL;
300
301 for (size_t i = 0; i < global.path->length; i++)
302 {
303 const char *p = (*global.path)[i];
304 const char *n = FileName::combine(p, sdi);
305 if (FileName::exists(n) == 1)
306 {
307 return n;
308 }
309 FileName::free(n);
310
311 n = FileName::combine(p, sd);
312 if (FileName::exists(n) == 1)
313 {
314 return n;
315 }
316 FileName::free(n);
317
318 const char *b = FileName::removeExt(filename);
319 n = FileName::combine(p, b);
320 FileName::free(b);
321 if (FileName::exists(n) == 2)
322 {
323 const char *n2i = FileName::combine(n, "package.di");
324 if (FileName::exists(n2i) == 1)
325 return n2i;
326 FileName::free(n2i);
327 const char *n2 = FileName::combine(n, "package.d");
328 if (FileName::exists(n2) == 1)
329 {
330 return n2;
331 }
332 FileName::free(n2);
333 }
334 FileName::free(n);
335 }
336 return NULL;
337 }
338
339 Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
340 {
341 //printf("Module::load(ident = '%s')\n", ident->toChars());
342
343 // Build module filename by turning:
344 // foo.bar.baz
345 // into:
346 // foo\bar\baz
347 const char *filename = getFilename(packages, ident);
348 // Look for the source file
349 const char *result = lookForSourceFile(filename);
350 if (result)
351 filename = result;
352
353 Module *m = new Module(filename, ident, 0, 0);
354 m->loc = loc;
355
356 if (!m->read(loc))
357 return NULL;
358
359 if (global.params.verbose)
360 {
361 OutBuffer buf;
362 if (packages)
363 {
364 for (size_t i = 0; i < packages->length; i++)
365 {
366 Identifier *pid = (*packages)[i];
367 buf.writestring(pid->toChars());
368 buf.writeByte('.');
369 }
370 }
371 buf.printf("%s\t(%s)", ident->toChars(), m->srcfile->toChars());
372 message("import %s", buf.peekChars());
373 }
374
375 m = m->parse();
376
377 // Call onImport here because if the module is going to be compiled then we
378 // need to determine it early because it affects semantic analysis. This is
379 // being done after parsing the module so the full module name can be taken
380 // from whatever was declared in the file.
381 if (!m->isRoot() && Compiler::onImport(m))
382 {
383 m->importedFrom = m;
384 assert(m->isRoot());
385 }
386 return m;
387 }
388
389 bool Module::read(Loc loc)
390 {
391 //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
392 if (srcfile->read())
393 {
394 if (!strcmp(srcfile->toChars(), "object.d"))
395 {
396 ::error(loc, "cannot find source code for runtime library file 'object.d'");
397 errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
398 const char *dmdConfFile = global.inifilename.length ? FileName::canonicalName(global.inifilename.ptr) : NULL;
399 errorSupplemental(loc, "config file: %s", dmdConfFile ? dmdConfFile : "not found");
400 }
401 else
402 {
403 // if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module
404 bool isPackageMod = (strcmp(toChars(), "package") != 0) &&
405 (strcmp(srcfile->name->name(), "package.d") == 0 || (strcmp(srcfile->name->name(), "package.di") == 0));
406
407 if (isPackageMod)
408 ::error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'",
409 toChars(), srcfile->toChars());
410 else
411 error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
412 }
413
414 if (!global.gag)
415 {
416 /* Print path
417 */
418 if (global.path)
419 {
420 for (size_t i = 0; i < global.path->length; i++)
421 {
422 const char *p = (*global.path)[i];
423 fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p);
424 }
425 }
426 else
427 fprintf(stderr, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
428 fatal();
429 }
430 return false;
431 }
432 return true;
433 }
434
435 Module *Module::parse()
436 {
437 //printf("Module::parse(srcfile='%s') this=%p\n", srcfile->name->toChars(), this);
438
439 const char *srcname = srcfile->name->toChars();
440 //printf("Module::parse(srcname = '%s')\n", srcname);
441
442 isPackageFile = (strcmp(srcfile->name->name(), "package.d") == 0 ||
443 strcmp(srcfile->name->name(), "package.di") == 0);
444
445 utf8_t *buf = (utf8_t *)srcfile->buffer;
446 size_t buflen = srcfile->len;
447
448 if (buflen >= 2)
449 {
450 /* Convert all non-UTF-8 formats to UTF-8.
451 * BOM : http://www.unicode.org/faq/utf_bom.html
452 * 00 00 FE FF UTF-32BE, big-endian
453 * FF FE 00 00 UTF-32LE, little-endian
454 * FE FF UTF-16BE, big-endian
455 * FF FE UTF-16LE, little-endian
456 * EF BB BF UTF-8
457 */
458
459 unsigned le;
460 unsigned bom = 1; // assume there's a BOM
461 if (buf[0] == 0xFF && buf[1] == 0xFE)
462 {
463 if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
464 { // UTF-32LE
465 le = 1;
466
467 Lutf32:
468 OutBuffer dbuf;
469 unsigned *pu = (unsigned *)(buf);
470 unsigned *pumax = &pu[buflen / 4];
471
472 if (buflen & 3)
473 { error("odd length of UTF-32 char source %u", buflen);
474 fatal();
475 }
476
477 dbuf.reserve(buflen / 4);
478 for (pu += bom; pu < pumax; pu++)
479 { unsigned u;
480
481 u = le ? Port::readlongLE(pu) : Port::readlongBE(pu);
482 if (u & ~0x7F)
483 {
484 if (u > 0x10FFFF)
485 { error("UTF-32 value %08x greater than 0x10FFFF", u);
486 fatal();
487 }
488 dbuf.writeUTF8(u);
489 }
490 else
491 dbuf.writeByte(u);
492 }
493 dbuf.writeByte(0); // add 0 as sentinel for scanner
494 buflen = dbuf.length() - 1; // don't include sentinel in count
495 buf = (utf8_t *) dbuf.extractData();
496 }
497 else
498 { // UTF-16LE (X86)
499 // Convert it to UTF-8
500 le = 1;
501
502 Lutf16:
503 OutBuffer dbuf;
504 unsigned short *pu = (unsigned short *)(buf);
505 unsigned short *pumax = &pu[buflen / 2];
506
507 if (buflen & 1)
508 { error("odd length of UTF-16 char source %u", buflen);
509 fatal();
510 }
511
512 dbuf.reserve(buflen / 2);
513 for (pu += bom; pu < pumax; pu++)
514 { unsigned u;
515
516 u = le ? Port::readwordLE(pu) : Port::readwordBE(pu);
517 if (u & ~0x7F)
518 { if (u >= 0xD800 && u <= 0xDBFF)
519 { unsigned u2;
520
521 if (++pu > pumax)
522 { error("surrogate UTF-16 high value %04x at EOF", u);
523 fatal();
524 }
525 u2 = le ? Port::readwordLE(pu) : Port::readwordBE(pu);
526 if (u2 < 0xDC00 || u2 > 0xDFFF)
527 { error("surrogate UTF-16 low value %04x out of range", u2);
528 fatal();
529 }
530 u = (u - 0xD7C0) << 10;
531 u |= (u2 - 0xDC00);
532 }
533 else if (u >= 0xDC00 && u <= 0xDFFF)
534 { error("unpaired surrogate UTF-16 value %04x", u);
535 fatal();
536 }
537 else if (u == 0xFFFE || u == 0xFFFF)
538 { error("illegal UTF-16 value %04x", u);
539 fatal();
540 }
541 dbuf.writeUTF8(u);
542 }
543 else
544 dbuf.writeByte(u);
545 }
546 dbuf.writeByte(0); // add 0 as sentinel for scanner
547 buflen = dbuf.length() - 1; // don't include sentinel in count
548 buf = (utf8_t *) dbuf.extractData();
549 }
550 }
551 else if (buf[0] == 0xFE && buf[1] == 0xFF)
552 { // UTF-16BE
553 le = 0;
554 goto Lutf16;
555 }
556 else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
557 { // UTF-32BE
558 le = 0;
559 goto Lutf32;
560 }
561 else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
562 { // UTF-8
563
564 buf += 3;
565 buflen -= 3;
566 }
567 else
568 {
569 /* There is no BOM. Make use of Arcane Jill's insight that
570 * the first char of D source must be ASCII to
571 * figure out the encoding.
572 */
573
574 bom = 0;
575 if (buflen >= 4)
576 { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
577 { // UTF-32LE
578 le = 1;
579 goto Lutf32;
580 }
581 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
582 { // UTF-32BE
583 le = 0;
584 goto Lutf32;
585 }
586 }
587 if (buflen >= 2)
588 {
589 if (buf[1] == 0)
590 { // UTF-16LE
591 le = 1;
592 goto Lutf16;
593 }
594 else if (buf[0] == 0)
595 { // UTF-16BE
596 le = 0;
597 goto Lutf16;
598 }
599 }
600
601 // It's UTF-8
602 if (buf[0] >= 0x80)
603 { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
604 fatal();
605 }
606 }
607 }
608
609 /* If it starts with the string "Ddoc", then it's a documentation
610 * source file.
611 */
612 if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
613 {
614 comment = buf + 4;
615 isDocFile = 1;
616 if (!docfile)
617 setDocfile();
618 return this;
619 }
620 {
621 Parser p(this, buf, buflen, docfile != NULL);
622 p.nextToken();
623 members = p.parseModule();
624 md = p.md;
625 numlines = p.scanloc.linnum;
626 if (p.errors)
627 ++global.errors;
628 }
629
630 if (srcfile->ref == 0)
631 ::free(srcfile->buffer);
632 srcfile->buffer = NULL;
633 srcfile->len = 0;
634
635 /* The symbol table into which the module is to be inserted.
636 */
637 DsymbolTable *dst;
638
639 if (md)
640 {
641 /* A ModuleDeclaration, md, was provided.
642 * The ModuleDeclaration sets the packages this module appears in, and
643 * the name of this module.
644 */
645 this->ident = md->id;
646 Package *ppack = NULL;
647 dst = Package::resolve(md->packages, &this->parent, &ppack);
648 assert(dst);
649
650 Module *m = ppack ? ppack->isModule() : NULL;
651 if (m && (strcmp(m->srcfile->name->name(), "package.d") != 0 &&
652 strcmp(m->srcfile->name->name(), "package.di") != 0))
653 {
654 ::error(md->loc, "package name '%s' conflicts with usage as a module name in file %s",
655 ppack->toPrettyChars(), m->srcfile->toChars());
656 }
657 }
658 else
659 {
660 /* The name of the module is set to the source file name.
661 * There are no packages.
662 */
663 dst = modules; // and so this module goes into global module symbol table
664
665 /* Check to see if module name is a valid identifier
666 */
667 if (!Identifier::isValidIdentifier(this->ident->toChars()))
668 error("has non-identifier characters in filename, use module declaration instead");
669 }
670
671 // Insert module into the symbol table
672 Dsymbol *s = this;
673 if (isPackageFile)
674 {
675 /* If the source tree is as follows:
676 * pkg/
677 * +- package.d
678 * +- common.d
679 * the 'pkg' will be incorporated to the internal package tree in two ways:
680 * import pkg;
681 * and:
682 * import pkg.common;
683 *
684 * If both are used in one compilation, 'pkg' as a module (== pkg/package.d)
685 * and a package name 'pkg' will conflict each other.
686 *
687 * To avoid the conflict:
688 * 1. If preceding package name insertion had occurred by Package::resolve,
689 * reuse the previous wrapping 'Package' if it exists
690 * 2. Otherwise, 'package.d' wrapped by 'Package' is inserted to the internal tree in here.
691 *
692 * Then change Package::isPkgMod to PKGmodule and set Package::mod.
693 *
694 * Note that the 'wrapping Package' is the Package that contains package.d and other submodules,
695 * the one inserted to the symbol table.
696 */
697 Dsymbol *ps = dst->lookup(ident);
698 Package *p = ps ? ps->isPackage() : NULL;
699 if (p == NULL)
700 {
701 p = new Package(ident);
702 p->tag = this->tag; // reuse the same package tag
703 p->symtab = new DsymbolTable();
704 }
705 this->tag= p->tag; // reuse the 'older' package tag
706 this->pkg = p;
707 p->parent = this->parent;
708 p->isPkgMod = PKGmodule;
709 p->mod = this;
710 s = p;
711 }
712 if (!dst->insert(s))
713 {
714 /* It conflicts with a name that is already in the symbol table.
715 * Figure out what went wrong, and issue error message.
716 */
717 Dsymbol *prev = dst->lookup(ident);
718 assert(prev);
719 if (Module *mprev = prev->isModule())
720 {
721 if (FileName::compare(srcname, mprev->srcfile->toChars()) != 0)
722 error(loc, "from file %s conflicts with another module %s from file %s",
723 srcname, mprev->toChars(), mprev->srcfile->toChars());
724 else if (isRoot() && mprev->isRoot())
725 error(loc, "from file %s is specified twice on the command line",
726 srcname);
727 else
728 error(loc, "from file %s must be imported with 'import %s;'",
729 srcname, toPrettyChars());
730
731 // Bugzilla 14446: Return previously parsed module to avoid AST duplication ICE.
732 return mprev;
733 }
734 else if (Package *pkg = prev->isPackage())
735 {
736 // 'package.d' loaded after a previous 'Package' insertion
737 if (isPackageFile)
738 amodules.push(this); // Add to global array of all modules
739 else
740 error(md ? md->loc : loc, "from file %s conflicts with package name %s",
741 srcname, pkg->toChars());
742 }
743 else
744 assert(global.errors);
745 }
746 else
747 {
748 // Add to global array of all modules
749 amodules.push(this);
750 }
751 Compiler::onParseModule(this);
752 return this;
753 }
754
755 void Module::importAll(Scope *)
756 {
757 //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
758
759 if (_scope)
760 return; // already done
761
762 if (isDocFile)
763 {
764 error("is a Ddoc file, cannot import it");
765 return;
766 }
767
768 /* Note that modules get their own scope, from scratch.
769 * This is so regardless of where in the syntax a module
770 * gets imported, it is unaffected by context.
771 * Ignore prevsc.
772 */
773 Scope *sc = Scope::createGlobal(this); // create root scope
774
775 if (md && md->msg)
776 md->msg = semanticString(sc, md->msg, "deprecation message");
777
778 // Add import of "object", even for the "object" module.
779 // If it isn't there, some compiler rewrites, like
780 // classinst == classinst -> .object.opEquals(classinst, classinst)
781 // would fail inside object.d.
782 if (members->length == 0 || ((*members)[0])->ident != Id::object ||
783 (*members)[0]->isImport() == NULL)
784 {
785 Import *im = new Import(Loc(), NULL, Id::object, NULL, 0);
786 members->shift(im);
787 }
788
789 if (!symtab)
790 {
791 // Add all symbols into module's symbol table
792 symtab = new DsymbolTable();
793 for (size_t i = 0; i < members->length; i++)
794 {
795 Dsymbol *s = (*members)[i];
796 s->addMember(sc, sc->scopesym);
797 }
798 }
799 // anything else should be run after addMember, so version/debug symbols are defined
800
801 /* Set scope for the symbols so that if we forward reference
802 * a symbol, it can possibly be resolved on the spot.
803 * If this works out well, it can be extended to all modules
804 * before any semantic() on any of them.
805 */
806 setScope(sc); // remember module scope for semantic
807 for (size_t i = 0; i < members->length; i++)
808 {
809 Dsymbol *s = (*members)[i];
810 s->setScope(sc);
811 }
812
813 for (size_t i = 0; i < members->length; i++)
814 {
815 Dsymbol *s = (*members)[i];
816 s->importAll(sc);
817 }
818
819 sc = sc->pop();
820 sc->pop(); // 2 pops because Scope::createGlobal() created 2
821 }
822
823 /**********************************
824 * Determine if we need to generate an instance of ModuleInfo
825 * for this Module.
826 */
827
828 int Module::needModuleInfo()
829 {
830 //printf("needModuleInfo() %s, %d, %d\n", toChars(), needmoduleinfo, global.params.cov);
831 return needmoduleinfo || global.params.cov;
832 }
833
834 Dsymbol *Module::search(const Loc &loc, Identifier *ident, int flags)
835 {
836 /* Since modules can be circularly referenced,
837 * need to stop infinite recursive searches.
838 * This is done with the cache.
839 */
840
841 //printf("%s Module::search('%s', flags = x%x) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
842 if (insearch)
843 return NULL;
844
845 /* Qualified module searches always search their imports,
846 * even if SearchLocalsOnly
847 */
848 if (!(flags & SearchUnqualifiedModule))
849 flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
850
851 if (searchCacheIdent == ident && searchCacheFlags == flags)
852 {
853 //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
854 // toChars(), ident->toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol->toChars() : "null");
855 return searchCacheSymbol;
856 }
857
858 unsigned int errors = global.errors;
859
860 insearch = 1;
861 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
862 insearch = 0;
863
864 if (errors == global.errors)
865 {
866 // Bugzilla 10752: We can cache the result only when it does not cause
867 // access error so the side-effect should be reproduced in later search.
868 searchCacheIdent = ident;
869 searchCacheSymbol = s;
870 searchCacheFlags = flags;
871 }
872 return s;
873 }
874
875 bool Module::isPackageAccessible(Package *p, Prot protection, int flags)
876 {
877 if (insearch) // don't follow import cycles
878 return false;
879 if (flags & IgnorePrivateImports)
880 protection = Prot(Prot::public_); // only consider public imports
881 insearch = true;
882 bool r = ScopeDsymbol::isPackageAccessible(p, protection);
883 insearch = false;
884 return r;
885 }
886
887 Dsymbol *Module::symtabInsert(Dsymbol *s)
888 {
889 searchCacheIdent = NULL; // symbol is inserted, so invalidate cache
890 return Package::symtabInsert(s);
891 }
892
893 void Module::clearCache()
894 {
895 for (size_t i = 0; i < amodules.length; i++)
896 {
897 Module *m = amodules[i];
898 m->searchCacheIdent = NULL;
899 }
900 }
901
902 /*******************************************
903 * Can't run semantic on s now, try again later.
904 */
905
906 void Module::addDeferredSemantic(Dsymbol *s)
907 {
908 // Don't add it if it is already there
909 for (size_t i = 0; i < deferred.length; i++)
910 {
911 Dsymbol *sd = deferred[i];
912
913 if (sd == s)
914 return;
915 }
916
917 //printf("Module::addDeferredSemantic('%s')\n", s->toChars());
918 deferred.push(s);
919 }
920
921 void Module::addDeferredSemantic2(Dsymbol *s)
922 {
923 //printf("Module::addDeferredSemantic2('%s')\n", s->toChars());
924 deferred2.push(s);
925 }
926
927 void Module::addDeferredSemantic3(Dsymbol *s)
928 {
929 //printf("Module::addDeferredSemantic3('%s')\n", s->toChars());
930 deferred3.push(s);
931 }
932
933 /******************************************
934 * Run semantic() on deferred symbols.
935 */
936
937 void Module::runDeferredSemantic()
938 {
939 if (dprogress == 0)
940 return;
941
942 static int nested;
943 if (nested)
944 return;
945 //if (deferred.length) printf("+Module::runDeferredSemantic(), len = %d\n", deferred.length);
946 nested++;
947
948 size_t len;
949 do
950 {
951 dprogress = 0;
952 len = deferred.length;
953 if (!len)
954 break;
955
956 Dsymbol **todo;
957 Dsymbol **todoalloc = NULL;
958 Dsymbol *tmp;
959 if (len == 1)
960 {
961 todo = &tmp;
962 }
963 else
964 {
965 todo = (Dsymbol **)mem.xmalloc(len * sizeof(Dsymbol *));
966 todoalloc = todo;
967 }
968 memcpy(todo, deferred.tdata(), len * sizeof(Dsymbol *));
969 deferred.setDim(0);
970
971 for (size_t i = 0; i < len; i++)
972 {
973 Dsymbol *s = todo[i];
974
975 dsymbolSemantic(s, NULL);
976 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
977 }
978 //printf("\tdeferred.length = %d, len = %d, dprogress = %d\n", deferred.length, len, dprogress);
979 if (todoalloc)
980 free(todoalloc);
981 } while (deferred.length < len || dprogress); // while making progress
982 nested--;
983 //printf("-Module::runDeferredSemantic(), len = %d\n", deferred.length);
984 }
985
986 void Module::runDeferredSemantic2()
987 {
988 Module::runDeferredSemantic();
989
990 Dsymbols *a = &Module::deferred2;
991 for (size_t i = 0; i < a->length; i++)
992 {
993 Dsymbol *s = (*a)[i];
994 //printf("[%d] %s semantic2a\n", i, s->toPrettyChars());
995 semantic2(s, NULL);
996
997 if (global.errors)
998 break;
999 }
1000 a->setDim(0);
1001 }
1002
1003 void Module::runDeferredSemantic3()
1004 {
1005 Module::runDeferredSemantic2();
1006
1007 Dsymbols *a = &Module::deferred3;
1008 for (size_t i = 0; i < a->length; i++)
1009 {
1010 Dsymbol *s = (*a)[i];
1011 //printf("[%d] %s semantic3a\n", i, s->toPrettyChars());
1012
1013 semantic3(s, NULL);
1014
1015 if (global.errors)
1016 break;
1017 }
1018 a->setDim(0);
1019 }
1020
1021 /************************************
1022 * Recursively look at every module this module imports,
1023 * return true if it imports m.
1024 * Can be used to detect circular imports.
1025 */
1026
1027 int Module::imports(Module *m)
1028 {
1029 //printf("%s Module::imports(%s)\n", toChars(), m->toChars());
1030 for (size_t i = 0; i < aimports.length; i++)
1031 {
1032 Module *mi = aimports[i];
1033 if (mi == m)
1034 return true;
1035 if (!mi->insearch)
1036 {
1037 mi->insearch = 1;
1038 int r = mi->imports(m);
1039 if (r)
1040 return r;
1041 }
1042 }
1043 return false;
1044 }
1045
1046 /*************************************
1047 * Return true if module imports itself.
1048 */
1049
1050 bool Module::selfImports()
1051 {
1052 //printf("Module::selfImports() %s\n", toChars());
1053 if (selfimports == 0)
1054 {
1055 for (size_t i = 0; i < amodules.length; i++)
1056 amodules[i]->insearch = 0;
1057
1058 selfimports = imports(this) + 1;
1059
1060 for (size_t i = 0; i < amodules.length; i++)
1061 amodules[i]->insearch = 0;
1062 }
1063 return selfimports == 2;
1064 }
1065
1066 /*************************************
1067 * Return true if module imports root module.
1068 */
1069
1070 bool Module::rootImports()
1071 {
1072 //printf("Module::rootImports() %s\n", toChars());
1073 if (rootimports == 0)
1074 {
1075 for (size_t i = 0; i < amodules.length; i++)
1076 amodules[i]->insearch = 0;
1077
1078 rootimports = 1;
1079 for (size_t i = 0; i < amodules.length; ++i)
1080 {
1081 Module *m = amodules[i];
1082 if (m->isRoot() && imports(m))
1083 {
1084 rootimports = 2;
1085 break;
1086 }
1087 }
1088
1089 for (size_t i = 0; i < amodules.length; i++)
1090 amodules[i]->insearch = 0;
1091 }
1092 return rootimports == 2;
1093 }
1094
1095 bool Module::isCoreModule(Identifier *ident)
1096 {
1097 return this->ident == ident && parent && parent->ident == Id::core && !parent->parent;
1098 }
1099
1100 /* =========================== ModuleDeclaration ===================== */
1101
1102 ModuleDeclaration::ModuleDeclaration(Loc loc, Identifiers *packages, Identifier *id)
1103 {
1104 this->loc = loc;
1105 this->packages = packages;
1106 this->id = id;
1107 this->isdeprecated = false;
1108 this->msg = NULL;
1109 }
1110
1111 const char *ModuleDeclaration::toChars()
1112 {
1113 OutBuffer buf;
1114
1115 if (packages && packages->length)
1116 {
1117 for (size_t i = 0; i < packages->length; i++)
1118 {
1119 Identifier *pid = (*packages)[i];
1120 buf.writestring(pid->toChars());
1121 buf.writeByte('.');
1122 }
1123 }
1124 buf.writestring(id->toChars());
1125 return buf.extractChars();
1126 }
1127
1128 /* =========================== Package ===================== */
1129
1130 Package::Package(Identifier *ident)
1131 : ScopeDsymbol(ident)
1132 {
1133 this->isPkgMod = PKGunknown;
1134 this->mod = NULL;
1135 static unsigned packageTag = 0;
1136 this->tag = packageTag++;
1137 }
1138
1139
1140 const char *Package::kind() const
1141 {
1142 return "package";
1143 }
1144
1145 Module *Package::isPackageMod()
1146 {
1147 if (isPkgMod == PKGmodule)
1148 {
1149 return mod;
1150 }
1151 return NULL;
1152 }
1153
1154 /**
1155 * Checks for the existence of a package.d to set isPkgMod appropriately
1156 * if isPkgMod == PKGunknown
1157 */
1158 void Package::resolvePKGunknown()
1159 {
1160 if (isModule())
1161 return;
1162 if (isPkgMod != PKGunknown)
1163 return;
1164
1165 Identifiers packages;
1166 for (Dsymbol *s = this->parent; s; s = s->parent)
1167 packages.insert(0, s->ident);
1168
1169 if (lookForSourceFile(getFilename(&packages, ident)))
1170 Module::load(Loc(), &packages, this->ident);
1171 else
1172 isPkgMod = PKGpackage;
1173 }
1174
1175 /**
1176 * Checks if pkg is a sub-package of this
1177 *
1178 * For example, if this qualifies to 'a1.a2' and pkg - to 'a1.a2.a3',
1179 * this function returns 'true'. If it is other way around or qualified
1180 * package paths conflict function returns 'false'.
1181 *
1182 * Params:
1183 * pkg = possible subpackage
1184 *
1185 * Returns:
1186 * see description
1187 */
1188 bool Package::isAncestorPackageOf(const Package * const pkg) const
1189 {
1190 if (this == pkg)
1191 return true;
1192 if (!pkg || !pkg->parent)
1193 return false;
1194 return isAncestorPackageOf(pkg->parent->isPackage());
1195 }
1196
1197 /****************************************************
1198 * Input:
1199 * packages[] the pkg1.pkg2 of pkg1.pkg2.mod
1200 * Returns:
1201 * the symbol table that mod should be inserted into
1202 * Output:
1203 * *pparent the rightmost package, i.e. pkg2, or NULL if no packages
1204 * *ppkg the leftmost package, i.e. pkg1, or NULL if no packages
1205 */
1206
1207 DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package **ppkg)
1208 {
1209 DsymbolTable *dst = Module::modules;
1210 Dsymbol *parent = NULL;
1211
1212 //printf("Package::resolve()\n");
1213 if (ppkg)
1214 *ppkg = NULL;
1215
1216 if (packages)
1217 {
1218 for (size_t i = 0; i < packages->length; i++)
1219 {
1220 Identifier *pid = (*packages)[i];
1221 Package *pkg;
1222 Dsymbol *p = dst->lookup(pid);
1223 if (!p)
1224 {
1225 pkg = new Package(pid);
1226 dst->insert(pkg);
1227 pkg->parent = parent;
1228 pkg->symtab = new DsymbolTable();
1229 }
1230 else
1231 {
1232 pkg = p->isPackage();
1233 assert(pkg);
1234 // It might already be a module, not a package, but that needs
1235 // to be checked at a higher level, where a nice error message
1236 // can be generated.
1237 // dot net needs modules and packages with same name
1238
1239 // But we still need a symbol table for it
1240 if (!pkg->symtab)
1241 pkg->symtab = new DsymbolTable();
1242 }
1243 parent = pkg;
1244 dst = pkg->symtab;
1245 if (ppkg && !*ppkg)
1246 *ppkg = pkg;
1247 if (pkg->isModule())
1248 {
1249 // Return the module so that a nice error message can be generated
1250 if (ppkg)
1251 *ppkg = (Package *)p;
1252 break;
1253 }
1254 }
1255 }
1256 if (pparent)
1257 *pparent = parent;
1258 return dst;
1259 }
1260
1261 Dsymbol *Package::search(const Loc &loc, Identifier *ident, int flags)
1262 {
1263 //printf("%s Package::search('%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
1264 flags &= ~SearchLocalsOnly; // searching an import is always transitive
1265 if (!isModule() && mod)
1266 {
1267 // Prefer full package name.
1268 Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
1269 if (s)
1270 return s;
1271 //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
1272 return mod->search(loc, ident, flags);
1273 }
1274
1275 return ScopeDsymbol::search(loc, ident, flags);
1276 }