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