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 }