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