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 (*members)[0]->isImport() == NULL)
684 {
685 Import *im = new Import(Loc(), NULL, Id::object, NULL, 0);
686 members->shift(im);
687 }
688
689 if (!symtab)
690 {
691 // Add all symbols into module's symbol table
692 symtab = new DsymbolTable();
693 for (size_t i = 0; i < members->dim; i++)
694 {
695 Dsymbol *s = (*members)[i];
696 s->addMember(sc, sc->scopesym);
697 }
698 }
699 // anything else should be run after addMember, so version/debug symbols are defined
700
701 /* Set scope for the symbols so that if we forward reference
702 * a symbol, it can possibly be resolved on the spot.
703 * If this works out well, it can be extended to all modules
704 * before any semantic() on any of them.
705 */
706 setScope(sc); // remember module scope for semantic
707 for (size_t i = 0; i < members->dim; i++)
708 {
709 Dsymbol *s = (*members)[i];
710 s->setScope(sc);
711 }
712
713 for (size_t i = 0; i < members->dim; i++)
714 {
715 Dsymbol *s = (*members)[i];
716 s->importAll(sc);
717 }
718
719 sc = sc->pop();
720 sc->pop(); // 2 pops because Scope::createGlobal() created 2
721 }
722
semantic(Scope *)723 void Module::semantic(Scope *)
724 {
725 if (semanticRun != PASSinit)
726 return;
727
728 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
729 semanticRun = PASSsemantic;
730
731 // Note that modules get their own scope, from scratch.
732 // This is so regardless of where in the syntax a module
733 // gets imported, it is unaffected by context.
734 Scope *sc = _scope; // see if already got one from importAll()
735 if (!sc)
736 {
737 Scope::createGlobal(this); // create root scope
738 }
739
740 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
741
742 // Pass 1 semantic routines: do public side of the definition
743 for (size_t i = 0; i < members->dim; i++)
744 {
745 Dsymbol *s = (*members)[i];
746
747 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
748 s->semantic(sc);
749 runDeferredSemantic();
750 }
751
752 if (userAttribDecl)
753 {
754 userAttribDecl->semantic(sc);
755 }
756
757 if (!_scope)
758 {
759 sc = sc->pop();
760 sc->pop(); // 2 pops because Scope::createGlobal() created 2
761 }
762 semanticRun = PASSsemanticdone;
763 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
764 }
765
semantic2(Scope *)766 void Module::semantic2(Scope*)
767 {
768 //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
769 if (semanticRun != PASSsemanticdone) // semantic() not completed yet - could be recursive call
770 return;
771 semanticRun = PASSsemantic2;
772
773 // Note that modules get their own scope, from scratch.
774 // This is so regardless of where in the syntax a module
775 // gets imported, it is unaffected by context.
776 Scope *sc = Scope::createGlobal(this); // create root scope
777 //printf("Module = %p\n", sc.scopesym);
778
779 // Pass 2 semantic routines: do initializers and function bodies
780 for (size_t i = 0; i < members->dim; i++)
781 {
782 Dsymbol *s = (*members)[i];
783 s->semantic2(sc);
784 }
785
786 if (userAttribDecl)
787 {
788 userAttribDecl->semantic2(sc);
789 }
790
791 sc = sc->pop();
792 sc->pop();
793 semanticRun = PASSsemantic2done;
794 //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
795 }
796
semantic3(Scope *)797 void Module::semantic3(Scope*)
798 {
799 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
800 if (semanticRun != PASSsemantic2done)
801 return;
802 semanticRun = PASSsemantic3;
803
804 // Note that modules get their own scope, from scratch.
805 // This is so regardless of where in the syntax a module
806 // gets imported, it is unaffected by context.
807 Scope *sc = Scope::createGlobal(this); // create root scope
808 //printf("Module = %p\n", sc.scopesym);
809
810 // Pass 3 semantic routines: do initializers and function bodies
811 for (size_t i = 0; i < members->dim; i++)
812 {
813 Dsymbol *s = (*members)[i];
814 //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
815 s->semantic3(sc);
816
817 runDeferredSemantic2();
818 }
819
820 if (userAttribDecl)
821 {
822 userAttribDecl->semantic3(sc);
823 }
824
825 sc = sc->pop();
826 sc->pop();
827 semanticRun = PASSsemantic3done;
828 }
829
830 /**********************************
831 * Determine if we need to generate an instance of ModuleInfo
832 * for this Module.
833 */
834
needModuleInfo()835 int Module::needModuleInfo()
836 {
837 //printf("needModuleInfo() %s, %d, %d\n", toChars(), needmoduleinfo, global.params.cov);
838 return needmoduleinfo || global.params.cov;
839 }
840
search(const Loc & loc,Identifier * ident,int flags)841 Dsymbol *Module::search(const Loc &loc, Identifier *ident, int flags)
842 {
843 /* Since modules can be circularly referenced,
844 * need to stop infinite recursive searches.
845 * This is done with the cache.
846 */
847
848 //printf("%s Module::search('%s', flags = x%x) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
849 if (insearch)
850 return NULL;
851
852 /* Qualified module searches always search their imports,
853 * even if SearchLocalsOnly
854 */
855 if (!(flags & SearchUnqualifiedModule))
856 flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
857
858 if (searchCacheIdent == ident && searchCacheFlags == flags)
859 {
860 //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
861 // toChars(), ident->toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol->toChars() : "null");
862 return searchCacheSymbol;
863 }
864
865 unsigned int errors = global.errors;
866
867 insearch = 1;
868 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
869 insearch = 0;
870
871 if (errors == global.errors)
872 {
873 // Bugzilla 10752: We can cache the result only when it does not cause
874 // access error so the side-effect should be reproduced in later search.
875 searchCacheIdent = ident;
876 searchCacheSymbol = s;
877 searchCacheFlags = flags;
878 }
879 return s;
880 }
881
isPackageAccessible(Package * p,Prot protection,int flags)882 bool Module::isPackageAccessible(Package *p, Prot protection, int flags)
883 {
884 if (insearch) // don't follow import cycles
885 return false;
886 if (flags & IgnorePrivateImports)
887 protection = Prot(PROTpublic); // only consider public imports
888 insearch = true;
889 bool r = ScopeDsymbol::isPackageAccessible(p, protection);
890 insearch = false;
891 return r;
892 }
893
symtabInsert(Dsymbol * s)894 Dsymbol *Module::symtabInsert(Dsymbol *s)
895 {
896 searchCacheIdent = NULL; // symbol is inserted, so invalidate cache
897 return Package::symtabInsert(s);
898 }
899
clearCache()900 void Module::clearCache()
901 {
902 for (size_t i = 0; i < amodules.dim; i++)
903 {
904 Module *m = amodules[i];
905 m->searchCacheIdent = NULL;
906 }
907 }
908
909 /*******************************************
910 * Can't run semantic on s now, try again later.
911 */
912
addDeferredSemantic(Dsymbol * s)913 void Module::addDeferredSemantic(Dsymbol *s)
914 {
915 // Don't add it if it is already there
916 for (size_t i = 0; i < deferred.dim; i++)
917 {
918 Dsymbol *sd = deferred[i];
919
920 if (sd == s)
921 return;
922 }
923
924 //printf("Module::addDeferredSemantic('%s')\n", s->toChars());
925 deferred.push(s);
926 }
927
addDeferredSemantic2(Dsymbol * s)928 void Module::addDeferredSemantic2(Dsymbol *s)
929 {
930 //printf("Module::addDeferredSemantic2('%s')\n", s->toChars());
931 deferred2.push(s);
932 }
933
addDeferredSemantic3(Dsymbol * s)934 void Module::addDeferredSemantic3(Dsymbol *s)
935 {
936 //printf("Module::addDeferredSemantic3('%s')\n", s->toChars());
937 deferred3.push(s);
938 }
939
940 /******************************************
941 * Run semantic() on deferred symbols.
942 */
943
runDeferredSemantic()944 void Module::runDeferredSemantic()
945 {
946 if (dprogress == 0)
947 return;
948
949 static int nested;
950 if (nested)
951 return;
952 //if (deferred.dim) printf("+Module::runDeferredSemantic(), len = %d\n", deferred.dim);
953 nested++;
954
955 size_t len;
956 do
957 {
958 dprogress = 0;
959 len = deferred.dim;
960 if (!len)
961 break;
962
963 Dsymbol **todo;
964 Dsymbol **todoalloc = NULL;
965 Dsymbol *tmp;
966 if (len == 1)
967 {
968 todo = &tmp;
969 }
970 else
971 {
972 todo = (Dsymbol **)mem.xmalloc(len * sizeof(Dsymbol *));
973 todoalloc = todo;
974 }
975 memcpy(todo, deferred.tdata(), len * sizeof(Dsymbol *));
976 deferred.setDim(0);
977
978 for (size_t i = 0; i < len; i++)
979 {
980 Dsymbol *s = todo[i];
981
982 s->semantic(NULL);
983 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
984 }
985 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
986 if (todoalloc)
987 free(todoalloc);
988 } while (deferred.dim < len || dprogress); // while making progress
989 nested--;
990 //printf("-Module::runDeferredSemantic(), len = %d\n", deferred.dim);
991 }
992
runDeferredSemantic2()993 void Module::runDeferredSemantic2()
994 {
995 Module::runDeferredSemantic();
996
997 Dsymbols *a = &Module::deferred2;
998 for (size_t i = 0; i < a->dim; i++)
999 {
1000 Dsymbol *s = (*a)[i];
1001 //printf("[%d] %s semantic2a\n", i, s->toPrettyChars());
1002 s->semantic2(NULL);
1003
1004 if (global.errors)
1005 break;
1006 }
1007 a->setDim(0);
1008 }
1009
runDeferredSemantic3()1010 void Module::runDeferredSemantic3()
1011 {
1012 Module::runDeferredSemantic2();
1013
1014 Dsymbols *a = &Module::deferred3;
1015 for (size_t i = 0; i < a->dim; i++)
1016 {
1017 Dsymbol *s = (*a)[i];
1018 //printf("[%d] %s semantic3a\n", i, s->toPrettyChars());
1019
1020 s->semantic3(NULL);
1021
1022 if (global.errors)
1023 break;
1024 }
1025 a->setDim(0);
1026 }
1027
1028 /************************************
1029 * Recursively look at every module this module imports,
1030 * return true if it imports m.
1031 * Can be used to detect circular imports.
1032 */
1033
imports(Module * m)1034 int Module::imports(Module *m)
1035 {
1036 //printf("%s Module::imports(%s)\n", toChars(), m->toChars());
1037 for (size_t i = 0; i < aimports.dim; i++)
1038 {
1039 Module *mi = aimports[i];
1040 if (mi == m)
1041 return true;
1042 if (!mi->insearch)
1043 {
1044 mi->insearch = 1;
1045 int r = mi->imports(m);
1046 if (r)
1047 return r;
1048 }
1049 }
1050 return false;
1051 }
1052
1053 /*************************************
1054 * Return true if module imports itself.
1055 */
1056
selfImports()1057 bool Module::selfImports()
1058 {
1059 //printf("Module::selfImports() %s\n", toChars());
1060 if (selfimports == 0)
1061 {
1062 for (size_t i = 0; i < amodules.dim; i++)
1063 amodules[i]->insearch = 0;
1064
1065 selfimports = imports(this) + 1;
1066
1067 for (size_t i = 0; i < amodules.dim; i++)
1068 amodules[i]->insearch = 0;
1069 }
1070 return selfimports == 2;
1071 }
1072
1073 /*************************************
1074 * Return true if module imports root module.
1075 */
1076
rootImports()1077 bool Module::rootImports()
1078 {
1079 //printf("Module::rootImports() %s\n", toChars());
1080 if (rootimports == 0)
1081 {
1082 for (size_t i = 0; i < amodules.dim; i++)
1083 amodules[i]->insearch = 0;
1084
1085 rootimports = 1;
1086 for (size_t i = 0; i < amodules.dim; ++i)
1087 {
1088 Module *m = amodules[i];
1089 if (m->isRoot() && imports(m))
1090 {
1091 rootimports = 2;
1092 break;
1093 }
1094 }
1095
1096 for (size_t i = 0; i < amodules.dim; i++)
1097 amodules[i]->insearch = 0;
1098 }
1099 return rootimports == 2;
1100 }
1101
isCoreModule(Identifier * ident)1102 bool Module::isCoreModule(Identifier *ident)
1103 {
1104 return this->ident == ident && parent && parent->ident == Id::core && !parent->parent;
1105 }
1106
1107 /* =========================== ModuleDeclaration ===================== */
1108
ModuleDeclaration(Loc loc,Identifiers * packages,Identifier * id)1109 ModuleDeclaration::ModuleDeclaration(Loc loc, Identifiers *packages, Identifier *id)
1110 {
1111 this->loc = loc;
1112 this->packages = packages;
1113 this->id = id;
1114 this->isdeprecated = false;
1115 this->msg = NULL;
1116 }
1117
toChars()1118 const char *ModuleDeclaration::toChars()
1119 {
1120 OutBuffer buf;
1121
1122 if (packages && packages->dim)
1123 {
1124 for (size_t i = 0; i < packages->dim; i++)
1125 {
1126 Identifier *pid = (*packages)[i];
1127 buf.writestring(pid->toChars());
1128 buf.writeByte('.');
1129 }
1130 }
1131 buf.writestring(id->toChars());
1132 return buf.extractString();
1133 }
1134
1135 /* =========================== Package ===================== */
1136
Package(Identifier * ident)1137 Package::Package(Identifier *ident)
1138 : ScopeDsymbol(ident)
1139 {
1140 this->isPkgMod = PKGunknown;
1141 this->mod = NULL;
1142 static unsigned packageTag = 0;
1143 this->tag = packageTag++;
1144 }
1145
1146
kind()1147 const char *Package::kind() const
1148 {
1149 return "package";
1150 }
1151
isPackageMod()1152 Module *Package::isPackageMod()
1153 {
1154 if (isPkgMod == PKGmodule)
1155 {
1156 return mod;
1157 }
1158 return NULL;
1159 }
1160
1161 /**
1162 * Checks if pkg is a sub-package of this
1163 *
1164 * For example, if this qualifies to 'a1.a2' and pkg - to 'a1.a2.a3',
1165 * this function returns 'true'. If it is other way around or qualified
1166 * package paths conflict function returns 'false'.
1167 *
1168 * Params:
1169 * pkg = possible subpackage
1170 *
1171 * Returns:
1172 * see description
1173 */
isAncestorPackageOf(const Package * const pkg)1174 bool Package::isAncestorPackageOf(const Package * const pkg) const
1175 {
1176 if (this == pkg)
1177 return true;
1178 if (!pkg || !pkg->parent)
1179 return false;
1180 return isAncestorPackageOf(pkg->parent->isPackage());
1181 }
1182
semantic(Scope *)1183 void Package::semantic(Scope *)
1184 {
1185 if (semanticRun < PASSsemanticdone)
1186 semanticRun = PASSsemanticdone;
1187 }
1188
1189 /****************************************************
1190 * Input:
1191 * packages[] the pkg1.pkg2 of pkg1.pkg2.mod
1192 * Returns:
1193 * the symbol table that mod should be inserted into
1194 * Output:
1195 * *pparent the rightmost package, i.e. pkg2, or NULL if no packages
1196 * *ppkg the leftmost package, i.e. pkg1, or NULL if no packages
1197 */
1198
resolve(Identifiers * packages,Dsymbol ** pparent,Package ** ppkg)1199 DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package **ppkg)
1200 {
1201 DsymbolTable *dst = Module::modules;
1202 Dsymbol *parent = NULL;
1203
1204 //printf("Package::resolve()\n");
1205 if (ppkg)
1206 *ppkg = NULL;
1207
1208 if (packages)
1209 {
1210 for (size_t i = 0; i < packages->dim; i++)
1211 {
1212 Identifier *pid = (*packages)[i];
1213 Package *pkg;
1214 Dsymbol *p = dst->lookup(pid);
1215 if (!p)
1216 {
1217 pkg = new Package(pid);
1218 dst->insert(pkg);
1219 pkg->parent = parent;
1220 pkg->symtab = new DsymbolTable();
1221 }
1222 else
1223 {
1224 pkg = p->isPackage();
1225 assert(pkg);
1226 // It might already be a module, not a package, but that needs
1227 // to be checked at a higher level, where a nice error message
1228 // can be generated.
1229 // dot net needs modules and packages with same name
1230
1231 // But we still need a symbol table for it
1232 if (!pkg->symtab)
1233 pkg->symtab = new DsymbolTable();
1234 }
1235 parent = pkg;
1236 dst = pkg->symtab;
1237 if (ppkg && !*ppkg)
1238 *ppkg = pkg;
1239 if (pkg->isModule())
1240 {
1241 // Return the module so that a nice error message can be generated
1242 if (ppkg)
1243 *ppkg = (Package *)p;
1244 break;
1245 }
1246 }
1247 }
1248 if (pparent)
1249 *pparent = parent;
1250 return dst;
1251 }
1252
search(const Loc & loc,Identifier * ident,int flags)1253 Dsymbol *Package::search(const Loc &loc, Identifier *ident, int flags)
1254 {
1255 //printf("%s Package::search('%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
1256 flags &= ~SearchLocalsOnly; // searching an import is always transitive
1257 if (!isModule() && mod)
1258 {
1259 // Prefer full package name.
1260 Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
1261 if (s)
1262 return s;
1263 //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
1264 return mod->search(loc, ident, flags);
1265 }
1266
1267 return ScopeDsymbol::search(loc, ident, flags);
1268 }
1269
1270 /* =========================== ===================== */
1271
1272 /********************************************
1273 * Look for the source file if it's different from filename.
1274 * Look for .di, .d, directory, and along global.path.
1275 * Does not open the file.
1276 * Output:
1277 * path the path where the file was found if it was not the current directory
1278 * Input:
1279 * filename as supplied by the user
1280 * global.path
1281 * Returns:
1282 * NULL if it's not different from filename.
1283 */
1284
lookForSourceFile(const char ** path,const char * filename)1285 const char *lookForSourceFile(const char **path, const char *filename)
1286 {
1287 /* Search along global.path for .di file, then .d file.
1288 */
1289 *path = NULL;
1290
1291 const char *sdi = FileName::forceExt(filename, global.hdr_ext);
1292 if (FileName::exists(sdi) == 1)
1293 return sdi;
1294
1295 const char *sd = FileName::forceExt(filename, global.mars_ext);
1296 if (FileName::exists(sd) == 1)
1297 return sd;
1298
1299 if (FileName::exists(filename) == 2)
1300 {
1301 /* The filename exists and it's a directory.
1302 * Therefore, the result should be: filename/package.d
1303 * iff filename/package.d is a file
1304 */
1305 const char *ni = FileName::combine(filename, "package.di");
1306 if (FileName::exists(ni) == 1)
1307 return ni;
1308 FileName::free(ni);
1309 const char *n = FileName::combine(filename, "package.d");
1310 if (FileName::exists(n) == 1)
1311 return n;
1312 FileName::free(n);
1313 }
1314
1315 if (FileName::absolute(filename))
1316 return NULL;
1317
1318 if (!global.path)
1319 return NULL;
1320
1321 for (size_t i = 0; i < global.path->dim; i++)
1322 {
1323 const char *p = (*global.path)[i];
1324
1325 const char *n = FileName::combine(p, sdi);
1326 if (FileName::exists(n) == 1)
1327 {
1328 *path = p;
1329 return n;
1330 }
1331 FileName::free(n);
1332
1333 n = FileName::combine(p, sd);
1334 if (FileName::exists(n) == 1)
1335 {
1336 *path = p;
1337 return n;
1338 }
1339 FileName::free(n);
1340
1341 const char *b = FileName::removeExt(filename);
1342 n = FileName::combine(p, b);
1343 FileName::free(b);
1344 if (FileName::exists(n) == 2)
1345 {
1346 const char *n2i = FileName::combine(n, "package.di");
1347 if (FileName::exists(n2i) == 1)
1348 return n2i;
1349 FileName::free(n2i);
1350 const char *n2 = FileName::combine(n, "package.d");
1351 if (FileName::exists(n2) == 1)
1352 {
1353 *path = p;
1354 return n2;
1355 }
1356 FileName::free(n2);
1357 }
1358 FileName::free(n);
1359 }
1360 return NULL;
1361 }
1362