xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/dmodule.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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