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