Changeset 183
- Timestamp:
- 07/03/09 07:32:24 (15 years ago)
- Files:
-
- trunk/src/access.c (modified) (1 diff)
- trunk/src/aggregate.h (modified) (2 diffs)
- trunk/src/arrayop.c (modified) (1 diff)
- trunk/src/attrib.c (modified) (1 diff)
- trunk/src/backend (added)
- trunk/src/backend/aa.c (added)
- trunk/src/backend/aa.h (added)
- trunk/src/backend/bcomplex.c (added)
- trunk/src/backend/bcomplex.h (added)
- trunk/src/backend/blockopt.c (added)
- trunk/src/backend/cc.h (added)
- trunk/src/backend/cdef.h (added)
- trunk/src/backend/cdeflnx.h (added)
- trunk/src/backend/cg87.c (added)
- trunk/src/backend/cg.c (added)
- trunk/src/backend/cgcod.c (added)
- trunk/src/backend/cgcs.c (added)
- trunk/src/backend/cgcv.c (added)
- trunk/src/backend/cgcv.h (added)
- trunk/src/backend/cgelem.c (added)
- trunk/src/backend/cgen.c (added)
- trunk/src/backend/cgobj.c (added)
- trunk/src/backend/cgreg.c (added)
- trunk/src/backend/cgsched.c (added)
- trunk/src/backend/cod1.c (added)
- trunk/src/backend/cod2.c (added)
- trunk/src/backend/cod3.c (added)
- trunk/src/backend/cod4.c (added)
- trunk/src/backend/cod5.c (added)
- trunk/src/backend/code.c (added)
- trunk/src/backend/code.h (added)
- trunk/src/backend/cpp.h (added)
- trunk/src/backend/cppman.c (added)
- trunk/src/backend/cv4.h (added)
- trunk/src/backend/debug.c (added)
- trunk/src/backend/dt.c (added)
- trunk/src/backend/dt.h (added)
- trunk/src/backend/dwarf2.h (added)
- trunk/src/backend/dwarf.c (added)
- trunk/src/backend/dwarf.h (added)
- trunk/src/backend/ee.c (added)
- trunk/src/backend/el.c (added)
- trunk/src/backend/elfobj.c (moved) (moved from trunk/src/elfobj.c) (3 diffs)
- trunk/src/backend/el.h (added)
- trunk/src/backend/evalu8.c (added)
- trunk/src/backend/exh.h (added)
- trunk/src/backend/gdag.c (added)
- trunk/src/backend/gflow.c (added)
- trunk/src/backend/global.h (added)
- trunk/src/backend/glocal.c (added)
- trunk/src/backend/gloop.c (added)
- trunk/src/backend/go.c (added)
- trunk/src/backend/go.h (added)
- trunk/src/backend/gother.c (added)
- trunk/src/backend/html.c (moved) (moved from trunk/src/html.c) (4 diffs)
- trunk/src/backend/html.h (moved) (moved from trunk/src/html.h) (1 diff)
- trunk/src/backend/iasm.h (added)
- trunk/src/backendlicense.txt (added)
- trunk/src/backend/mach.h (added)
- trunk/src/backend/machobj.c (moved) (moved from trunk/src/machobj.c) (3 diffs)
- trunk/src/backend/md5.c (moved) (moved from trunk/src/md5.c)
- trunk/src/backend/md5.h (moved) (moved from trunk/src/md5.h)
- trunk/src/backend/melf.h (added)
- trunk/src/backend/newman.c (added)
- trunk/src/backend/nteh.c (added)
- trunk/src/backend/oper.h (added)
- trunk/src/backend/optabgen.c (added)
- trunk/src/backend/os.c (added)
- trunk/src/backend/outbuf.c (added)
- trunk/src/backend/outbuf.h (added)
- trunk/src/backend/out.c (added)
- trunk/src/backend/parser.h (added)
- trunk/src/backend/ptrntab.c (added)
- trunk/src/backend/rtlsym.c (added)
- trunk/src/backend/rtlsym.h (added)
- trunk/src/backend/strtold.c (added)
- trunk/src/backend/symbol.c (added)
- trunk/src/backend/tassert.h (added)
- trunk/src/backend/ti_achar.c (added)
- trunk/src/backend/tinfo.h (added)
- trunk/src/backend/token.h (added)
- trunk/src/backend/ty.h (added)
- trunk/src/backend/type.c (added)
- trunk/src/backend/type.h (added)
- trunk/src/backend/var.c (added)
- trunk/src/builtin.c (modified) (2 diffs)
- trunk/src/cast.c (modified) (3 diffs)
- trunk/src/class.c (modified) (5 diffs)
- trunk/src/clone.c (modified) (3 diffs)
- trunk/src/constfold.c (modified) (1 diff)
- trunk/src/cppmangle.c (added)
- trunk/src/declaration.c (modified) (3 diffs)
- trunk/src/declaration.h (modified) (1 diff)
- trunk/src/doc.c (modified) (1 diff)
- trunk/src/dsymbol.c (modified) (2 diffs)
- trunk/src/dsymbol.h (modified) (2 diffs)
- trunk/src/e2ir.c (modified) (6 diffs)
- trunk/src/eh.c (added)
- trunk/src/expression.c (modified) (13 diffs)
- trunk/src/expression.h (modified) (1 diff)
- trunk/src/func.c (modified) (3 diffs)
- trunk/src/glue.c (added)
- trunk/src/hdrgen.c (modified) (1 diff)
- trunk/src/iasm.c (added)
- trunk/src/inifile.c (modified) (1 diff)
- trunk/src/interpret.c (modified) (1 diff)
- trunk/src/lexer.c (modified) (2 diffs)
- trunk/src/libelf.c (modified) (1 diff)
- trunk/src/libmach.c (modified) (1 diff)
- trunk/src/libomf.c (added)
- trunk/src/link.c (modified) (1 diff)
- trunk/src/linux.mak (added)
- trunk/src/macro.c (modified) (1 diff)
- trunk/src/mars.c (modified) (6 diffs)
- trunk/src/mars.h (modified) (1 diff)
- trunk/src/module.c (modified) (3 diffs)
- trunk/src/module.h (modified) (1 diff)
- trunk/src/msc.c (added)
- trunk/src/mtype.c (modified) (8 diffs)
- trunk/src/mtype.h (modified) (2 diffs)
- trunk/src/objfile.h (added)
- trunk/src/opover.c (modified) (1 diff)
- trunk/src/osx.mak (added)
- trunk/src/parse.c (modified) (5 diffs)
- trunk/src/ph.c (added)
- trunk/src/readme.txt (modified) (1 diff)
- trunk/src/root (added)
- trunk/src/root/array.c (moved) (moved from trunk/src/array.c) (1 diff)
- trunk/src/root/dchar.c (moved) (moved from trunk/src/dchar.c) (1 diff)
- trunk/src/root/dchar.h (moved) (moved from trunk/src/dchar.h)
- trunk/src/root/gnuc.c (moved) (moved from trunk/src/gnuc.c)
- trunk/src/root/gnuc.h (moved) (moved from trunk/src/gnuc.h)
- trunk/src/root/lstring.c (moved) (moved from trunk/src/lstring.c) (1 diff)
- trunk/src/root/lstring.h (moved) (moved from trunk/src/lstring.h)
- trunk/src/root/man.c (moved) (moved from trunk/src/man.c)
- trunk/src/root/port.c (added)
- trunk/src/root/port.h (moved) (moved from trunk/src/port.h)
- trunk/src/root/rmem.c (moved) (moved from trunk/src/mem.c) (1 diff)
- trunk/src/root/rmem.h (moved) (moved from trunk/src/mem.h)
- trunk/src/root/root.c (moved) (moved from trunk/src/root.c) (1 diff)
- trunk/src/root/root.h (moved) (moved from trunk/src/root.h)
- trunk/src/root/stringtable.c (moved) (moved from trunk/src/stringtable.c) (1 diff)
- trunk/src/root/stringtable.h (moved) (moved from trunk/src/stringtable.h)
- trunk/src/s2ir.c (added)
- trunk/src/scope.c (modified) (1 diff)
- trunk/src/statement.c (modified) (6 diffs)
- trunk/src/statement.h (modified) (2 diffs)
- trunk/src/struct.c (modified) (3 diffs)
- trunk/src/template.c (modified) (14 diffs)
- trunk/src/template.h (modified) (3 diffs)
- trunk/src/tk (added)
- trunk/src/tk.c (added)
- trunk/src/tk/filespec.c (added)
- trunk/src/tk/filespec.h (added)
- trunk/src/tk/list.c (added)
- trunk/src/tk/list.h (added)
- trunk/src/tk/mem.c (added)
- trunk/src/tk/mem.h (added)
- trunk/src/tk/vec.c (added)
- trunk/src/tk/vec.h (added)
- trunk/src/tocsym.c (modified) (1 diff)
- trunk/src/toctype.c (added)
- trunk/src/tocvdebug.c (added)
- trunk/src/todt.c (modified) (1 diff)
- trunk/src/toelfdebug.c (added)
- trunk/src/toir.c (modified) (4 diffs)
- trunk/src/toir.h (modified) (1 diff)
- trunk/src/toobj.c (modified) (4 diffs)
- trunk/src/traits.c (modified) (2 diffs)
- trunk/src/typinf.c (modified) (1 diff)
- trunk/src/util.c (added)
- trunk/src/win32.mak (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/access.c
r169 r183 1 1 2 2 // Copyright (c) 1999-2006 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 15 15 #include "root.h" 16 #include " mem.h"16 #include "rmem.h" 17 17 18 18 #include "enum.h" 19 19 #include "aggregate.h" 20 20 #include "init.h" 21 21 #include "attrib.h" 22 22 #include "scope.h" 23 23 #include "id.h" 24 24 #include "mtype.h" 25 25 #include "declaration.h" 26 26 #include "aggregate.h" 27 27 #include "expression.h" 28 28 #include "module.h" 29 29 30 30 #define LOG 0 31 31 32 32 /* Code to do access checks 33 33 */ 34 34 35 35 int hasPackageAccess(Scope *sc, Dsymbol *s); 36 36 trunk/src/aggregate.h
r177 r183 35 35 36 36 37 37 struct AggregateDeclaration : ScopeDsymbol 38 38 { 39 39 Type *type; 40 40 unsigned storage_class; 41 41 enum PROT protection; 42 42 Type *handle; // 'this' type 43 43 unsigned structsize; // size of struct 44 44 unsigned alignsize; // size of struct for alignment purposes 45 45 unsigned structalign; // struct member alignment in effect 46 46 int hasUnions; // set if aggregate has overlapping fields 47 47 Array fields; // VarDeclaration fields 48 48 unsigned sizeok; // set when structsize contains valid data 49 49 // 0: no size 50 50 // 1: size is correct 51 51 // 2: cannot determine size; fwd referenced 52 52 int isdeprecated; // !=0 if deprecated 53 53 Scope *scope; // !=NULL means context to use 54 54 55 int isnested; // !=0 if is nested 56 VarDeclaration *vthis; // 'this' parameter if this aggregate is nested 57 55 58 // Special member functions 56 59 InvariantDeclaration *inv; // invariant 57 60 NewDeclaration *aggNew; // allocator 58 61 DeleteDeclaration *aggDelete; // deallocator 59 62 60 63 #if V2 61 64 CtorDeclaration *ctor; 62 65 CtorDeclaration *defaultCtor; // default constructor 63 66 #endif 64 67 65 68 FuncDeclarations dtors; // Array of destructors 66 69 FuncDeclaration *dtor; // aggregate destructor 67 70 68 71 #ifdef IN_GCC 69 72 Array methods; // flat list of all methods for debug information 70 73 #endif 71 74 72 75 AggregateDeclaration(Loc loc, Identifier *id); 73 76 void semantic2(Scope *sc); 74 77 void semantic3(Scope *sc); 75 78 void inlineScan(); 76 79 unsigned size(Loc loc); 77 80 static void alignmember(unsigned salign, unsigned size, unsigned *poffset); 78 81 Type *getType(); 79 82 void addField(Scope *sc, VarDeclaration *v); 80 83 int isDeprecated(); // is aggregate deprecated? 81 84 FuncDeclaration *buildDtor(Scope *sc); 85 int isNested(); 82 86 83 87 void emitComment(Scope *sc); 84 88 void toDocBuffer(OutBuffer *buf); 85 89 86 90 // For access checking 87 91 virtual PROT getAccess(Dsymbol *smember); // determine access to smember 88 92 int isFriendOf(AggregateDeclaration *cd); 89 93 int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class? 90 94 void accessCheck(Loc loc, Scope *sc, Dsymbol *smember); 91 95 92 96 enum PROT prot(); 93 97 94 98 // Back end 95 99 Symbol *stag; // tag symbol for debug data 96 100 Symbol *sinit; 97 101 Symbol *toInitializer(); 98 102 99 103 AggregateDeclaration *isAggregateDeclaration() { return this; } 100 104 }; 101 105 … … 187 191 FuncDeclaration *staticDtor; 188 192 Array vtbl; // Array of FuncDeclaration's making up the vtbl[] 189 193 Array vtblFinal; // More FuncDeclaration's that aren't in vtbl[] 190 194 191 195 BaseClasses baseclasses; // Array of BaseClass's; first is super, 192 196 // rest are Interface's 193 197 194 198 int interfaces_dim; 195 199 BaseClass **interfaces; // interfaces[interfaces_dim] for this class 196 200 // (does not include baseClass) 197 201 198 202 BaseClasses *vtblInterfaces; // array of base interfaces that have 199 203 // their own vtbl[] 200 204 201 205 ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration 202 206 int com; // !=0 if this is a COM class (meaning 203 207 // it derives from IUnknown) 204 208 int isauto; // !=0 if this is an auto class 205 209 int isabstract; // !=0 if abstract class 206 210 207 int isnested; // !=0 if is nested208 VarDeclaration *vthis; // 'this' parameter if this class is nested209 210 211 int inuse; // to prevent recursive attempts 211 212 212 213 ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); 213 214 Dsymbol *syntaxCopy(Dsymbol *s); 214 215 void semantic(Scope *sc); 215 216 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 216 217 int isBaseOf2(ClassDeclaration *cd); 217 218 218 219 #define OFFSET_RUNTIME 0x76543210 219 220 virtual int isBaseOf(ClassDeclaration *cd, int *poffset); 220 221 221 222 Dsymbol *search(Loc, Identifier *ident, int flags); 222 223 #if V2 223 224 int isFuncHidden(FuncDeclaration *fd); 224 225 #endif 225 226 FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); 226 227 void interfaceSemantic(Scope *sc); 227 int isNested();228 228 int isCOMclass(); 229 229 virtual int isCOMinterface(); 230 230 #if V2 231 231 virtual int isCPPinterface(); 232 232 #endif 233 233 int isAbstract(); 234 234 virtual int vtblOffset(); 235 235 const char *kind(); 236 236 char *mangle(); 237 237 void toDocBuffer(OutBuffer *buf); 238 238 239 239 PROT getAccess(Dsymbol *smember); // determine access to smember 240 240 241 241 void addLocalClass(ClassDeclarations *); 242 242 243 243 // Back end 244 244 void toObjFile(int multiobj); // compile to .obj file 245 245 void toDebug(); 246 246 unsigned baseVtblOffset(BaseClass *bc); 247 247 Symbol *toSymbol(); trunk/src/arrayop.c
r177 r183 1 1 2 2 // Copyright (c) 1999-2008 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 #include <stdio.h> 11 11 #include <string.h> 12 12 #include <assert.h> 13 13 14 #if _WIN32 || IN_GCC 15 #include "mem.h" 16 #else 17 #include "../root/mem.h" 18 #endif 14 #include "rmem.h" 19 15 20 16 #include "stringtable.h" 21 17 22 18 #include "expression.h" 23 19 #include "statement.h" 24 20 #include "mtype.h" 25 21 #include "declaration.h" 26 22 #include "scope.h" 27 23 #include "id.h" 28 24 #include "module.h" 29 25 #include "init.h" 30 26 31 27 extern int binary(const char *p , const char **tab, int high); 32 28 33 29 /************************************** 34 30 * Hash table of array op functions already generated or known about. 35 31 */ 36 32 37 33 StringTable arrayfuncs; 38 34 trunk/src/attrib.c
r182 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 15 #if _WIN32 || IN_GCC 16 #include "mem.h" 17 #elif linux || __APPLE__ 18 #include "../root/mem.h" 19 #endif 15 #include "rmem.h" 20 16 21 17 #include "init.h" 22 18 #include "declaration.h" 23 19 #include "attrib.h" 24 20 #include "cond.h" 25 21 #include "scope.h" 26 22 #include "id.h" 27 23 #include "expression.h" 28 24 #include "dsymbol.h" 29 25 #include "aggregate.h" 30 26 #include "module.h" 31 27 #include "parse.h" 32 28 #include "template.h" 33 29 34 30 extern void obj_includelib(const char *name); 35 31 void obj_startaddress(Symbol *s); 36 32 37 33 38 34 /********************************* AttribDeclaration ****************************/ 39 35 trunk/src/backend/elfobj.c
r182 r183 1 2 //_ elfobj.c Modified by: Walter Bright 3 // Copyright (c) 1984-2009 by Digital Mars, http://www.digitalmars.com 1 // Copyright (C) ?-1998 by Symantec 2 // Copyright (C) 2000-2009 by Digital Mars 4 3 // All Rights Reserved 5 // Written by Walter Bright 4 // http://www.digitalmars.com 5 /* 6 * This source file is made available for personal use 7 * only. The license is in /dmd/src/dmd/backendlicense.txt 8 * For any other uses, please contact Digital Mars. 9 */ 10 11 6 12 // Output to ELF object files 7 13 8 14 #if SCPP || MARS 9 15 #include <stdio.h> 10 16 #include <string.h> 11 17 #include <stdlib.h> 12 18 #include <malloc.h> 13 19 #include <sys/types.h> 14 20 #include <sys/stat.h> 15 21 #include <fcntl.h> 16 22 #include <ctype.h> 17 23 18 24 #if linux || __APPLE__ 19 25 #include <signal.h> 20 26 #include <unistd.h> 21 27 #endif 22 28 23 29 #include "cc.h" 24 30 #include "global.h" 25 31 #include "code.h" … … 1464 1470 if (s->Sfl == FLdata || s->Sfl == FLtlsdata) 1465 1471 { 1466 1472 objpubdef(s->Sseg,s,0); 1467 1473 searchfixlist(s); // backpatch any refs to this symbol 1468 1474 } 1469 1475 return s->Sseg; 1470 1476 } 1471 1477 1472 1478 /******************************** 1473 1479 * Get a segment for a segment name. 1474 1480 * Input: 1475 1481 * name name of segment, if NULL then revert to default name 1476 1482 * suffix append to name 1477 1483 * align alignment 1478 1484 * Returns: 1479 1485 * segment index of found or newly created segment 1480 1486 */ 1481 1487 1482 1488 int elf_getsegment2(IDXSEC shtidx, IDXSYM symidx, IDXSEC relidx) 1483 1489 { 1490 //printf("SegData = %p\n", SegData); 1484 1491 int seg = ++seg_count; 1485 1492 if (seg_count >= seg_max) 1486 1493 { // need more room in segment table 1487 1494 seg_max += OB_SEG_INC; 1488 1495 SegData = (seg_data **)mem_realloc(SegData,seg_max * sizeof(seg_data *)); 1489 memset(&SegData[seg_count], 0, OB_SEG_INC* sizeof(seg_data *));1496 memset(&SegData[seg_count], 0, (seg_max - seg_count) * sizeof(seg_data *)); 1490 1497 } 1491 1498 assert(seg_count < seg_max); 1492 1499 if (!SegData[seg]) 1493 1500 { SegData[seg] = (seg_data *)mem_calloc(sizeof(seg_data)); 1501 //printf("test2: SegData[%d] = %p\n", seg, SegData[seg]); 1494 1502 } 1495 1503 1496 1504 seg_data *pseg = SegData[seg]; 1497 1505 pseg->SDseg = seg; 1498 1506 pseg->SDshtidx = shtidx; 1499 1507 pseg->SDoffset = 0; 1500 1508 if (pseg->SDbuf) 1501 1509 pseg->SDbuf->setsize(0); 1502 1510 else 1503 1511 { if (SecHdrTab[shtidx].sh_type != SHT_NOBITS) 1504 1512 { pseg->SDbuf = new Outbuffer(OB_XTRA_STR); 1505 1513 pseg->SDbuf->reserve(1024); 1506 1514 } 1507 1515 } 1508 1516 if (pseg->SDrel) 1509 1517 pseg->SDrel->setsize(0); 1510 1518 pseg->SDsymidx = symidx; 1511 1519 pseg->SDrelidx = relidx; 1512 1520 pseg->SDrelmaxoff = 0; 1513 1521 pseg->SDrelindex = 0; … … 1719 1727 if (tyfunc(s->ty()) && !variadic(s->Stype)) 1720 1728 #else 1721 1729 if (!(config.flags4 & CFG4oldstdmangle) && 1722 1730 config.exe == EX_NT && tyfunc(s->ty()) && 1723 1731 !variadic(s->Stype)) 1724 1732 #endif 1725 1733 { 1726 1734 char *pstr = unsstr(type_paramsize(s->Stype)); 1727 1735 size_t pstrlen = strlen(pstr); 1728 1736 size_t destlen = len + 1 + pstrlen + 1; 1729 1737 1730 1738 if (destlen > DEST_LEN) 1731 1739 dest = (char *)mem_malloc(destlen); 1732 1740 memcpy(dest,name,len); 1733 1741 dest[len] = '@'; 1734 1742 memcpy(dest + 1 + len, pstr, pstrlen + 1); 1735 1743 break; 1736 1744 } 1737 1745 case mTYman_cpp: 1738 1746 case mTYman_c: 1739 case mTYman_ java:1747 case mTYman_d: 1740 1748 case mTYman_sys: 1741 1749 case 0: 1742 1750 if (len >= DEST_LEN) 1743 1751 dest = (char *)mem_malloc(len + 1); 1744 1752 memcpy(dest,name,len+1);// copy in name and trailing 0 1745 1753 break; 1746 1754 1747 1755 default: 1748 1756 #ifdef DEBUG 1749 1757 printf("mangling %x\n",type_mangle(s->Stype)); 1750 1758 symbol_print(s); 1751 1759 #endif 1752 1760 printf("%d\n", type_mangle(s->Stype)); 1753 1761 assert(0); 1754 1762 } 1755 1763 //dbg_printf("\t %s\n",dest); 1756 1764 return dest; 1757 1765 } 1758 1766 1759 1767 /******************************* trunk/src/backend/html.c
r125 r183 1 1 2 // Copyright (c) 1999-200 6by Digital Mars2 // Copyright (c) 1999-2009 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 11 11 /* HTML parser 12 12 */ 13 13 14 14 #include <stdio.h> 15 15 #include <string.h> 16 16 #include <ctype.h> 17 17 #include <stdarg.h> 18 18 #include <errno.h> 19 19 #include <wchar.h> 20 20 21 #include "mars.h"22 21 #include "html.h" 23 22 23 #if MARS 24 24 #include <assert.h> 25 25 #include "root.h" 26 #include "../mars/mars.h" 26 //#include "../mars/mars.h" 27 #else 28 #include "outbuf.h" 29 #include "msgs2.h" 30 31 extern void html_err(const char *, unsigned, unsigned, ...); 32 33 static char __file__[] = __FILE__; /* for tassert.h */ 34 #include "tassert.h" 35 #endif 36 37 #if __GNUC__ 38 int memicmp(const char *s1, const char *s2, int n); 39 #if 0 40 { 41 int result = 0; 42 43 for (int i = 0; i < n; i++) 44 { char c1 = s1[i]; 45 char c2 = s2[i]; 46 47 result = c1 - c2; 48 if (result) 49 { 50 if ('A' <= c1 && c1 <= 'Z') 51 c1 += 'a' - 'A'; 52 if ('A' <= c2 && c2 <= 'Z') 53 c2 += 'a' - 'A'; 54 result = c1 - c2; 55 if (result) 56 break; 57 } 58 } 59 return result; 60 } 61 #endif 62 #endif 27 63 28 64 extern int HtmlNamedEntity(unsigned char *p, int length); 29 65 30 66 static int isLineSeparator(const unsigned char* p); 31 67 32 68 /********************************** 33 69 * Determine if beginning of tag identifier 34 70 * or a continuation of a tag identifier. 35 71 */ 36 72 37 73 inline int istagstart(int c) 38 74 { 39 75 return (isalpha(c) || c == '_'); 40 76 } 41 77 42 78 inline int istag(int c) 43 79 { 44 80 return (isalnum(c) || c == '_'); 45 81 } 46 82 … … 48 84 */ 49 85 50 86 Html::Html(const char *sourcename, unsigned char *base, unsigned length) 51 87 { 52 88 //printf("Html::Html()\n"); 53 89 this->sourcename = sourcename; 54 90 this->base = base; 55 91 p = base; 56 92 end = base + length; 57 93 linnum = 1; 58 94 dbuf = NULL; 59 95 inCode = 0; 60 96 } 61 97 62 98 /********************************************** 63 99 * Print error & quit. 64 100 */ 65 101 66 102 void Html::error(const char *format, ...) 67 103 { 68 if (!global.gag) 69 { 70 printf("%s(%d) : HTML Error: ", sourcename, linnum); 71 72 va_list ap; 73 va_start(ap, format); 74 vprintf(format, ap); 75 va_end(ap); 76 77 printf("\n"); 78 fflush(stdout); 79 } 80 81 global.errors++; 104 printf("%s(%d) : HTML Error: ", sourcename, linnum); 105 106 va_list ap; 107 va_start(ap, format); 108 vprintf(format, ap); 109 va_end(ap); 110 111 printf("\n"); 112 fflush(stdout); 113 114 //#if MARS 115 // global.errors++; 116 //#else 117 exit(EXIT_FAILURE); 118 //#endif 82 119 } 83 120 84 121 /********************************************** 85 122 * Extract all the code from an HTML file, 86 123 * concatenate it all together, and store in buf. 87 124 */ 88 125 126 #if MARS 89 127 void Html::extractCode(OutBuffer *buf) 128 #else 129 void Html::extractCode(Outbuffer *buf) 130 #endif 90 131 { 91 132 //printf("Html::extractCode()\n"); 92 133 dbuf = buf; // save for other routines 93 134 buf->reserve(end - p); 94 135 inCode = 0; 95 136 while (1) 96 137 { 97 138 //printf("p = %p, *p = x%x\n", p, *p); 98 139 switch (*p) 99 140 { 100 141 #if 0 // strings are not recognized outside of tags 101 142 case '"': 102 143 case '\'': 103 144 skipString(); 104 145 continue; 105 146 #endif 106 147 case '<': 107 148 if (p[1] == '!' && isCommentStart()) 108 149 { // Comments start with <!-- 109 150 scanComment(); … … 113 154 scanCDATA(); 114 155 } 115 156 else if (p[1] == '/' && istagstart(*skipWhite(p + 2))) 116 157 skipTag(); 117 158 else if (istagstart(*skipWhite(p + 1))) 118 159 skipTag(); 119 160 else 120 161 goto Ldefault; 121 162 continue; 122 163 123 164 case 0: 124 165 case 0x1a: 125 166 break; // end of file 126 167 127 168 case '&': 128 169 if (inCode) 129 170 { // Translate character entity into ascii for D parser 130 171 int c; 131 172 132 173 c = charEntity(); 174 #if MARS 133 175 buf->writeUTF8(c); 176 #else 177 buf->writeByte(c); 178 #endif 134 179 } 135 180 else 136 181 p++; 137 182 continue; 138 183 139 184 case '\r': 140 185 if (p[1] == '\n') 141 186 goto Ldefault; 142 187 case '\n': 143 188 linnum++; 144 189 // Always extract new lines, so that D lexer counts the 145 190 // lines right. 146 191 buf->writeByte(*p); 147 192 p++; 148 193 continue; 149 194 150 195 default: 151 196 Ldefault: 152 197 if (inCode) 153 198 buf->writeByte(*p); 154 199 p++; 155 200 continue; 156 201 } 157 202 break; 158 203 } 159 204 buf->writeByte(0); // ending sentinel 205 #if SCPP 206 //printf("Code is: '%s'\n", buf->toString() + 3); 207 #endif 208 #if MARS 160 209 //printf("D code is: '%s'\n", (char *)buf->data); 210 #endif 161 211 } 162 212 163 213 /*********************************************** 164 214 * Scan to end of <> tag. 165 215 * Look for <code> and </code> tags to start/stop D processing. 166 216 * Input: 167 217 * p is on opening '<' of tag; it's already verified that 168 218 * it's a tag by lookahead 169 219 * Output: 170 220 * p is past closing '>' of tag 171 221 */ 172 222 173 223 void Html::skipTag() 174 224 { 175 225 enum TagState // what parsing state we're in 176 226 { 177 227 TStagstart, // start of tag name 178 228 TStag, // in a tag name 179 229 TSrest, // following tag name 180 230 }; … … 514 564 p += len; 515 565 return 1; 516 566 } 517 567 else 518 568 { 519 569 return 0; 520 570 } 521 571 } 522 572 523 573 void Html::scanCDATA() 524 574 { 525 575 while(*p && *p != 0x1A) 526 576 { 527 577 int lineSepLength = isLineSeparator(p); 528 578 if (lineSepLength>0) 529 579 { 530 580 /* Always extract new lines, so that D lexer counts the lines 531 581 * right. 532 582 */ 533 583 linnum++; 534 dbuf->write UTF8('\n');584 dbuf->writeByte('\n'); 535 585 p += lineSepLength; 536 586 continue; 537 587 } 538 588 else if (p[0] == ']' && p[1] == ']' && p[2] == '>') 539 589 { 540 590 /* end of CDATA section */ 541 591 p += 3; 542 592 return; 543 593 } 544 594 else if (inCode) 545 595 { 546 596 /* this CDATA section contains D code */ 547 597 dbuf->writeByte(*p); 548 598 } 549 599 550 600 p++; 551 601 } 552 602 } 553 603 554 604 /******************************************** trunk/src/backend/html.h
r125 r183 1 1 2 // Compiler implementation of the D programming language3 2 // Copyright (c) 1999-2006 by Digital Mars 4 3 // All Rights Reserved 5 4 // written by Walter Bright 6 // http://www.digitalmars.com5 // www.digitalmars.com 7 6 // License for redistribution is by either the Artistic License 8 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 8 // See the included readme.txt for details. 10 9 11 #ifndef DMD_HTML_H12 #define DMD_HTML_H 113 10 11 #if MARS 14 12 struct OutBuffer; 13 #else 14 struct Outbuffer; 15 #endif 15 16 16 17 struct Html 17 18 { 18 19 const char *sourcename; 19 20 20 21 unsigned char *base; // pointer to start of buffer 21 22 unsigned char *end; // past end of buffer 22 23 unsigned char *p; // current character 23 24 unsigned linnum; // current line number 25 #if MARS 24 26 OutBuffer *dbuf; // code source buffer 27 #else 28 Outbuffer *dbuf; // code source buffer 29 #endif 25 30 int inCode; // !=0 if in code 26 31 27 32 28 33 Html(const char *sourcename, unsigned char *base, unsigned length); 29 34 30 35 void error(const char *format, ...); 36 #if MARS 31 37 void extractCode(OutBuffer *buf); 38 #else 39 void extractCode(Outbuffer *buf); 40 #endif 32 41 void skipTag(); 33 42 void skipString(); 34 43 unsigned char *skipWhite(unsigned char *q); 35 44 void scanComment(); 36 45 int isCommentStart(); 37 46 void scanCDATA(); 38 47 int isCDATAStart(); 39 48 int charEntity(); 40 49 static int namedEntity(unsigned char *p, int length); 41 50 }; 42 43 #endiftrunk/src/backend/machobj.c
r182 r183 1 1 2 //_ machobj.c Modified by: Walter Bright 3 // Copyright (c) 2009 by Digital Mars, http://www.digitalmars.com 2 // Copyright (c) 2009 by Digital Mars 4 3 // All Rights Reserved 5 // Written by Walter Bright 6 // Output to Mach-O object files 4 // written by Walter Bright 5 // http://www.digitalmars.com 6 // License for redistribution is by either the Artistic License 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 // See the included readme.txt for details. 9 7 10 8 11 #if SCPP || MARS 9 12 #include <stdio.h> 10 13 #include <string.h> 11 14 #include <stdlib.h> 12 15 #include <sys/types.h> 13 16 #include <sys/stat.h> 14 17 #include <fcntl.h> 15 18 #include <ctype.h> 16 19 17 20 #if _WIN32 || linux 18 21 #include <malloc.h> 19 22 #endif 20 23 21 24 #if linux || __APPLE__ 22 25 #include <signal.h> 23 26 #include <unistd.h> 24 27 #endif 25 28 26 29 #include "cc.h" … … 1407 1410 * segment index of found or newly created segment 1408 1411 */ 1409 1412 1410 1413 int mach_getsegment(const char *sectname, const char *segname, 1411 1414 int align, int flags) 1412 1415 { 1413 1416 assert(strlen(sectname) <= 16); 1414 1417 assert(strlen(segname) <= 16); 1415 1418 for (int seg = 1; seg <= seg_count; seg++) 1416 1419 { seg_data *pseg = SegData[seg]; 1417 1420 if (strncmp(SecHdrTab[pseg->SDshtidx].sectname, sectname, 16) == 0 && 1418 1421 strncmp(SecHdrTab[pseg->SDshtidx].segname, segname, 16) == 0) 1419 1422 return seg; // return existing segment 1420 1423 } 1421 1424 1422 1425 int seg = ++seg_count; 1423 1426 if (seg_count >= seg_max) 1424 1427 { // need more room in segment table 1425 1428 seg_max += 10; 1426 1429 SegData = (seg_data **)mem_realloc(SegData,seg_max * sizeof(seg_data *)); 1427 memset(&SegData[seg_count], 0, 10* sizeof(seg_data *));1430 memset(&SegData[seg_count], 0, (seg_max - seg_count) * sizeof(seg_data *)); 1428 1431 } 1429 1432 assert(seg_count < seg_max); 1430 1433 if (SegData[seg]) 1431 1434 { seg_data *pseg = SegData[seg]; 1432 1435 Outbuffer *b1 = pseg->SDbuf; 1433 1436 Outbuffer *b2 = pseg->SDrel; 1434 1437 memset(pseg, 0, sizeof(seg_data)); 1435 1438 if (b1) 1436 1439 b1->setsize(0); 1437 1440 if (b2) 1438 1441 b2->setsize(0); 1439 1442 pseg->SDbuf = b1; 1440 1443 pseg->SDrel = b2; 1441 1444 } 1442 1445 else 1443 1446 { 1444 1447 seg_data *pseg = (seg_data *)mem_calloc(sizeof(seg_data)); 1445 1448 SegData[seg] = pseg; 1446 1449 if (flags != S_ZEROFILL) 1447 1450 { pseg->SDbuf = new Outbuffer(4096); … … 1608 1611 #if TARGET_LINUX || TARGET_OSX 1609 1612 if (tyfunc(s->ty()) && !variadic(s->Stype)) 1610 1613 #else 1611 1614 if (!(config.flags4 & CFG4oldstdmangle) && 1612 1615 config.exe == EX_NT && tyfunc(s->ty()) && 1613 1616 !variadic(s->Stype)) 1614 1617 #endif 1615 1618 { 1616 1619 char *pstr = unsstr(type_paramsize(s->Stype)); 1617 1620 size_t pstrlen = strlen(pstr); 1618 1621 size_t destlen = len + 1 + pstrlen + 1; 1619 1622 1620 1623 if (destlen > DEST_LEN) 1621 1624 dest = (char *)mem_malloc(destlen); 1622 1625 memcpy(dest,name,len); 1623 1626 dest[len] = '@'; 1624 1627 memcpy(dest + 1 + len, pstr, pstrlen + 1); 1625 1628 break; 1626 1629 } 1627 1630 case mTYman_cpp: 1628 case mTYman_ java:1631 case mTYman_d: 1629 1632 case mTYman_sys: 1630 1633 case 0: 1631 1634 if (len >= DEST_LEN) 1632 1635 dest = (char *)mem_malloc(len + 1); 1633 1636 memcpy(dest,name,len+1);// copy in name and trailing 0 1634 1637 break; 1635 1638 1636 1639 case mTYman_c: 1637 1640 if (len >= DEST_LEN - 1) 1638 1641 dest = (char *)mem_malloc(1 + len + 1); 1639 1642 dest[0] = '_'; 1640 1643 memcpy(dest + 1,name,len+1);// copy in name and trailing 0 1641 1644 break; 1642 1645 1643 1646 1644 1647 default: 1645 1648 #ifdef DEBUG 1646 1649 printf("mangling %x\n",type_mangle(s->Stype)); 1647 1650 symbol_print(s); 1648 1651 #endif trunk/src/builtin.c
r163 r183 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-200 7by Digital Mars3 // Copyright (c) 1999-2009 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <assert.h> 13 13 #include <math.h> 14 14 15 15 #include "mars.h" 16 16 #include "declaration.h" 17 17 #include "attrib.h" 18 18 #include "expression.h" 19 19 #include "scope.h" 20 20 #include "mtype.h" 21 21 #include "aggregate.h" 22 22 #include "identifier.h" 23 23 #include "id.h" 24 24 #include "module.h" 25 25 26 #if V2 27 26 28 /********************************** 27 29 * Determine if function is a builtin one. 28 30 */ 29 31 enum BUILTIN FuncDeclaration::isBuiltin() 30 32 { 31 static const char FeZe[] = "F eZe"; //real function(real)33 static const char FeZe[] = "FNaNbeZe"; // pure nothrow real function(real) 32 34 33 35 //printf("FuncDeclaration::isBuiltin() %s\n", toChars()); 34 36 if (builtin == BUILTINunknown) 35 37 { 36 38 builtin = BUILTINnot; 37 39 if (parent && parent->isModule()) 38 40 { 39 41 if (parent->ident == Id::math && 40 42 parent->parent && parent->parent->ident == Id::std && 41 43 !parent->parent->parent) 42 44 { 45 //printf("deco = %s\n", type->deco); 43 46 if (strcmp(type->deco, FeZe) == 0) 44 47 { 45 48 if (ident == Id::sin) 46 49 builtin = BUILTINsin; 47 50 else if (ident == Id::cos) 48 51 builtin = BUILTINcos; 49 52 else if (ident == Id::tan) 50 53 builtin = BUILTINtan; 51 54 else if (ident == Id::_sqrt) 52 55 builtin = BUILTINsqrt; 53 56 else if (ident == Id::fabs) 54 57 builtin = BUILTINfabs; 55 58 //printf("builtin = %d\n", builtin); 56 59 } 60 else if (strcmp(type->deco, "FNaNbdZd") == 0 || 61 strcmp(type->deco, "FNaNbfZf") == 0) 62 builtin = BUILTINsqrt; 57 63 } 58 64 } 59 65 } 60 66 return builtin; 61 67 } 62 68 63 69 64 70 /************************************** 65 71 * Evaluate builtin function. 66 72 * Return result; NULL if cannot evaluate it. 67 73 */ 68 74 69 75 Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments) 70 76 { 71 77 assert(arguments && arguments->dim); 72 78 Expression *arg0 = (Expression *)arguments->data[0]; 73 79 Expression *e = NULL; 74 80 switch (builtin) 75 81 { 76 82 case BUILTINsin: … … 83 89 e = new RealExp(0, cosl(arg0->toReal()), Type::tfloat80); 84 90 break; 85 91 86 92 case BUILTINtan: 87 93 if (arg0->op == TOKfloat64) 88 94 e = new RealExp(0, tanl(arg0->toReal()), Type::tfloat80); 89 95 break; 90 96 91 97 case BUILTINsqrt: 92 98 if (arg0->op == TOKfloat64) 93 99 e = new RealExp(0, sqrtl(arg0->toReal()), Type::tfloat80); 94 100 break; 95 101 96 102 case BUILTINfabs: 97 103 if (arg0->op == TOKfloat64) 98 104 e = new RealExp(0, fabsl(arg0->toReal()), Type::tfloat80); 99 105 break; 100 106 } 101 107 return e; 102 108 } 109 110 #endif trunk/src/cast.c
r181 r183 1 1 2 2 // Copyright (c) 1999-2008 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 #include <stdio.h> 11 11 #include <assert.h> 12 12 13 #if _WIN32 || IN_GCC 14 #include "mem.h" 15 #else 16 #include "../root/mem.h" 17 #endif 13 #include "rmem.h" 18 14 19 15 #include "expression.h" 20 16 #include "mtype.h" 21 17 #include "utf.h" 22 18 #include "declaration.h" 23 19 #include "aggregate.h" 24 20 25 21 /* ==================== implicitCast ====================== */ 26 22 27 23 /************************************** 28 24 * Do an implicit cast. 29 25 * Issue error if it can't be done. 30 26 */ 31 27 32 28 Expression *Expression::implicitCastTo(Scope *sc, Type *t) 33 29 { 34 30 //printf("Expression::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars()); 35 31 36 32 MATCH match = implicitConvTo(t); 37 33 if (match) … … 44 40 Expression *e = optimize(WANTflags | WANTvalue); 45 41 46 42 if (e->op == TOKint64) 47 43 return e->implicitCastTo(sc, t); 48 44 49 45 if (tyfrom == Tint32 && 50 46 (op == TOKadd || op == TOKmin || 51 47 op == TOKand || op == TOKor || op == TOKxor) 52 48 ) 53 49 { 54 50 /* This is really only a semi-kludge fix, 55 51 * we really should look at the operands of op 56 52 * and see if they are narrower types. 57 53 * For example, b=b|b and b=b|7 and s=b+b should be allowed, 58 54 * but b=b|i should be an error. 59 55 */ 60 56 ; 61 57 } 62 58 else 63 59 { 64 fprintf(stdmsg, "warning - "); 65 error("implicit conversion of expression (%s) of type %s to %s can cause loss of data", 60 warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data", 66 61 toChars(), type->toChars(), t->toChars()); 67 62 } 68 63 } 69 64 #if V2 70 65 if (match == MATCHconst && t == type->constOf()) 71 66 { 72 67 Expression *e = copy(); 73 68 e->type = t; 74 69 return e; 75 70 } 76 71 #endif 77 72 return castTo(sc, t); 78 73 } 79 74 80 75 Expression *e = optimize(WANTflags | WANTvalue); 81 76 if (e != this) 82 77 return e->implicitCastTo(sc, t); 83 78 84 79 #if 0 85 80 printf("ty = %d\n", type->ty); … … 1708 1703 break; 1709 1704 1710 1705 case Tint8: 1711 1706 case Tuns8: 1712 1707 case Tint16: 1713 1708 case Tuns16: 1714 1709 case Tbit: 1715 1710 case Tbool: 1716 1711 case Tchar: 1717 1712 case Twchar: 1718 1713 e = e->castTo(sc, Type::tint32); 1719 1714 break; 1720 1715 1721 1716 case Tdchar: 1722 1717 e = e->castTo(sc, Type::tuns32); 1723 1718 break; 1724 1719 } 1725 1720 return e; 1726 1721 } 1727 1722 1723 /*********************************** 1724 * See if both types are arrays that can be compared 1725 * for equality. Return !=0 if so. 1726 * If they are arrays, but incompatible, issue error. 1727 * This is to enable comparing things like an immutable 1728 * array with a mutable one. 1729 */ 1730 1731 int arrayTypeCompatible(Loc loc, Type *t1, Type *t2) 1732 { 1733 t1 = t1->toBasetype(); 1734 t2 = t2->toBasetype(); 1735 1736 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) && 1737 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer)) 1738 { 1739 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst && 1740 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst && 1741 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid)) 1742 { 1743 error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars()); 1744 } 1745 return 1; 1746 } 1747 return 0; 1748 } trunk/src/class.c
r180 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 15 15 #include "root.h" 16 #include " mem.h"16 #include "rmem.h" 17 17 18 18 #include "enum.h" 19 19 #include "init.h" 20 20 #include "attrib.h" 21 21 #include "declaration.h" 22 22 #include "aggregate.h" 23 23 #include "id.h" 24 24 #include "mtype.h" 25 25 #include "scope.h" 26 26 #include "module.h" 27 27 #include "expression.h" 28 28 #include "statement.h" 29 29 30 30 /********************************* ClassDeclaration ****************************/ 31 31 32 32 ClassDeclaration *ClassDeclaration::classinfo; 33 33 ClassDeclaration *ClassDeclaration::object; 34 34 35 35 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) 36 36 : AggregateDeclaration(loc, id) … … 171 171 object->error("%s", msg); 172 172 object = this; 173 173 } 174 174 175 175 if (id == Id::ClassInfo) 176 176 { if (classinfo) 177 177 classinfo->error("%s", msg); 178 178 classinfo = this; 179 179 } 180 180 181 181 if (id == Id::ModuleInfo) 182 182 { if (Module::moduleinfo) 183 183 Module::moduleinfo->error("%s", msg); 184 184 Module::moduleinfo = this; 185 185 } 186 186 } 187 187 188 188 com = 0; 189 189 isauto = 0; 190 190 isabstract = 0; 191 isnested = 0;192 vthis = NULL;193 191 inuse = 0; 194 192 } 195 193 196 194 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) 197 195 { 198 196 ClassDeclaration *cd; 199 197 200 198 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars()); 201 199 if (s) 202 200 cd = (ClassDeclaration *)s; 203 201 else 204 202 cd = new ClassDeclaration(loc, ident, NULL); 205 203 206 204 cd->storage_class |= storage_class; 207 205 208 206 cd->baseclasses.setDim(this->baseclasses.dim); 209 207 for (int i = 0; i < cd->baseclasses.dim; i++) 210 208 { 211 209 BaseClass *b = (BaseClass *)this->baseclasses.data[i]; 212 210 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); … … 489 487 if (toParent2()) 490 488 { 491 489 error("is nested within %s, but super class %s is nested within %s", 492 490 toParent2()->toChars(), 493 491 baseClass->toChars(), 494 492 baseClass->toParent2()->toChars()); 495 493 } 496 494 else 497 495 { 498 496 error("is not nested, but super class %s is nested within %s", 499 497 baseClass->toChars(), 500 498 baseClass->toParent2()->toChars()); 501 499 } 502 500 isnested = 0; 503 501 } 504 502 } 505 503 else if (!(storage_class & STCstatic)) 506 504 { Dsymbol *s = toParent2(); 507 505 if (s) 508 506 { 509 ClassDeclaration *cd = s->isClassDeclaration();507 AggregateDeclaration *ad = s->isClassDeclaration(); 510 508 FuncDeclaration *fd = s->isFuncDeclaration(); 511 509 512 510 513 if ( cd || fd)511 if (ad || fd) 514 512 { isnested = 1; 515 513 Type *t; 516 if ( cd)517 t = cd->type;514 if (ad) 515 t = ad->handle; 518 516 else if (fd) 519 517 { AggregateDeclaration *ad = fd->isMember2(); 520 518 if (ad) 521 519 t = ad->handle; 522 520 else 523 521 { 524 t = new TypePointer(Type::tvoid); 525 t = t->semantic(0, sc); 522 t = Type::tvoidptr; 526 523 } 527 524 } 528 525 else 529 526 assert(0); 527 if (t->ty == Tstruct) // ref to struct 528 t = Type::tvoidptr; 530 529 assert(!vthis); 531 530 vthis = new ThisDeclaration(t); 532 531 members->push(vthis); 533 532 } 534 533 } 535 534 } 536 535 } 537 536 538 537 if (storage_class & (STCauto | STCscope)) 539 538 isauto = 1; 540 539 if (storage_class & STCabstract) 541 540 isabstract = 1; 542 541 if (storage_class & STCinvariant) 543 542 type = type->invariantOf(); 544 543 else if (storage_class & STCconst) 545 544 type = type->constOf(); 546 545 547 546 sc = sc->push(this); 548 547 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | 549 548 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls); … … 868 867 return !overloadApply(fdstart, &isf, fd); 869 868 } 870 869 } 871 870 #endif 872 871 873 872 /**************** 874 873 * Find virtual function matching identifier and type. 875 874 * Used to build virtual function tables for interface implementations. 876 875 */ 877 876 878 877 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) 879 878 { 880 879 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); 881 880 882 881 ClassDeclaration *cd = this; 883 882 Array *vtbl = &cd->vtbl; 884 883 while (1) 885 884 { 886 885 for (size_t i = 0; i < vtbl->dim; i++) 887 886 { 888 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i]; 887 FuncDeclaration *fd = ((Dsymbol*)vtbl->data[i])->isFuncDeclaration(); 888 if (!fd) 889 continue; // the first entry might be a ClassInfo 889 890 890 891 //printf("\t[%d] = %s\n", i, fd->toChars()); 891 892 if (ident == fd->ident && 892 893 //tf->equals(fd->type) 893 894 fd->type->covariant(tf) == 1 894 895 ) 895 896 { //printf("\t\tfound\n"); 896 897 return fd; 897 898 } 898 899 //else printf("\t\t%d\n", fd->type->covariant(tf)); 899 900 } 900 901 if (!cd) 901 902 break; 902 903 vtbl = &cd->vtblFinal; 903 904 cd = cd->baseClass; 904 905 } 905 906 906 907 return NULL; 907 908 } 908 909 … … 953 954 */ 954 955 955 956 int ClassDeclaration::isAbstract() 956 957 { 957 958 if (isabstract) 958 959 return TRUE; 959 960 for (int i = 1; i < vtbl.dim; i++) 960 961 { 961 962 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); 962 963 963 964 //printf("\tvtbl[%d] = %p\n", i, fd); 964 965 if (!fd || fd->isAbstract()) 965 966 { 966 967 isabstract |= 1; 967 968 return TRUE; 968 969 } 969 970 } 970 971 return FALSE; 971 972 } 972 973 973 974 /****************************************975 * Returns !=0 if there's an extra member which is the 'this'976 * pointer to the enclosing context (enclosing class or function)977 */978 979 int ClassDeclaration::isNested()980 {981 return isnested;982 }983 974 984 975 /**************************************** 985 976 * Determine if slot 0 of the vtbl[] is reserved for something else. 986 977 * For class objects, yes, this is where the classinfo ptr goes. 987 978 * For COM interfaces, no. 988 979 * For non-COM interfaces, yes, this is where the Interface ptr goes. 989 980 */ 990 981 991 982 int ClassDeclaration::vtblOffset() 992 983 { 993 984 return 1; 994 985 } 995 986 996 987 /**************************************** 997 988 */ 998 989 999 990 const char *ClassDeclaration::kind() 1000 991 { 1001 992 return "class"; 1002 993 } trunk/src/clone.c
r179 r183 30 30 */ 31 31 32 32 int StructDeclaration::needOpAssign() 33 33 { 34 34 #define X 0 35 35 if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars()); 36 36 if (hasIdentityAssign) 37 37 goto Ldontneed; 38 38 39 39 if (dtor || postblit) 40 40 goto Lneed; 41 41 42 42 /* If any of the fields need an opAssign, then we 43 43 * need it too. 44 44 */ 45 45 for (size_t i = 0; i < fields.dim; i++) 46 46 { 47 47 Dsymbol *s = (Dsymbol *)fields.data[i]; 48 48 VarDeclaration *v = s->isVarDeclaration(); 49 49 assert(v && v->storage_class & STCfield); 50 if (v->storage_class & STCref) 51 continue; 50 52 Type *tv = v->type->toBasetype(); 51 53 while (tv->ty == Tsarray) 52 54 { TypeSArray *ta = (TypeSArray *)tv; 53 55 tv = tv->nextOf()->toBasetype(); 54 56 } 55 57 if (tv->ty == Tstruct) 56 58 { TypeStruct *ts = (TypeStruct *)tv; 57 59 StructDeclaration *sd = ts->sym; 58 60 if (sd->needOpAssign()) 59 61 goto Lneed; 60 62 } 61 63 } 62 64 Ldontneed: 63 65 if (X) printf("\tdontneed\n"); 64 66 return 0; 65 67 66 68 Lneed: 67 69 if (X) printf("\tneed\n"); 68 70 return 1; 69 71 #undef X … … 247 249 248 250 /***************************************** 249 251 * Create inclusive postblit for struct by aggregating 250 252 * all the postblits in postblits[] with the postblits for 251 253 * all the members. 252 254 * Note the close similarity with AggregateDeclaration::buildDtor(), 253 255 * and the ordering changes (runs forward instead of backwards). 254 256 */ 255 257 256 258 #if V2 257 259 FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) 258 260 { 259 261 //printf("StructDeclaration::buildPostBlit() %s\n", toChars()); 260 262 Expression *e = NULL; 261 263 262 264 for (size_t i = 0; i < fields.dim; i++) 263 265 { 264 266 Dsymbol *s = (Dsymbol *)fields.data[i]; 265 267 VarDeclaration *v = s->isVarDeclaration(); 266 268 assert(v && v->storage_class & STCfield); 269 if (v->storage_class & STCref) 270 continue; 267 271 Type *tv = v->type->toBasetype(); 268 272 size_t dim = 1; 269 273 while (tv->ty == Tsarray) 270 274 { TypeSArray *ta = (TypeSArray *)tv; 271 275 dim *= ((TypeSArray *)tv)->dim->toInteger(); 272 276 tv = tv->nextOf()->toBasetype(); 273 277 } 274 278 if (tv->ty == Tstruct) 275 279 { TypeStruct *ts = (TypeStruct *)tv; 276 280 StructDeclaration *sd = ts->sym; 277 281 if (sd->postblit) 278 282 { Expression *ex; 279 283 280 284 // this.v 281 285 ex = new ThisExp(0); 282 286 ex = new DotVarExp(0, ex, v, 0); 283 287 284 288 if (dim == 1) 285 289 { // this.v.dtor() 286 290 ex = new DotVarExp(0, ex, sd->postblit, 0); … … 342 346 343 347 /***************************************** 344 348 * Create inclusive destructor for struct/class by aggregating 345 349 * all the destructors in dtors[] with the destructors for 346 350 * all the members. 347 351 * Note the close similarity with StructDeclaration::buildPostBlit(), 348 352 * and the ordering changes (runs backward instead of forwards). 349 353 */ 350 354 351 355 FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) 352 356 { 353 357 //printf("AggregateDeclaration::buildDtor() %s\n", toChars()); 354 358 Expression *e = NULL; 355 359 356 360 #if V2 357 361 for (size_t i = 0; i < fields.dim; i++) 358 362 { 359 363 Dsymbol *s = (Dsymbol *)fields.data[i]; 360 364 VarDeclaration *v = s->isVarDeclaration(); 361 365 assert(v && v->storage_class & STCfield); 366 if (v->storage_class & STCref) 367 continue; 362 368 Type *tv = v->type->toBasetype(); 363 369 size_t dim = 1; 364 370 while (tv->ty == Tsarray) 365 371 { TypeSArray *ta = (TypeSArray *)tv; 366 372 dim *= ((TypeSArray *)tv)->dim->toInteger(); 367 373 tv = tv->nextOf()->toBasetype(); 368 374 } 369 375 if (tv->ty == Tstruct) 370 376 { TypeStruct *ts = (TypeStruct *)tv; 371 377 StructDeclaration *sd = ts->sym; 372 378 if (sd->dtor) 373 379 { Expression *ex; 374 380 375 381 // this.v 376 382 ex = new ThisExp(0); 377 383 ex = new DotVarExp(0, ex, v, 0); 378 384 379 385 if (dim == 1) 380 386 { // this.v.dtor() 381 387 ex = new DotVarExp(0, ex, sd->dtor, 0); trunk/src/constfold.c
r178 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2007 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 #include <math.h> 15 15 16 16 #if __DMC__ 17 17 #include <complex.h> 18 18 #endif 19 19 20 #include " mem.h"20 #include "rmem.h" 21 21 #include "root.h" 22 22 23 23 #include "mtype.h" 24 24 #include "expression.h" 25 25 #include "aggregate.h" 26 26 #include "declaration.h" 27 27 28 28 #ifdef IN_GCC 29 29 #include "d-gcc-real.h" 30 30 31 31 /* %% fix? */ 32 32 extern "C" bool real_isnan (const real_t *); 33 33 #endif 34 34 35 35 static real_t zero; // work around DMC bug for now 36 36 37 37 #define LOG 0 38 38 39 39 Expression *expType(Type *type, Expression *e) 40 40 { trunk/src/declaration.c
r181 r183 439 439 // it is not knowable from the syntax whether this is an alias 440 440 // for a type or an alias for a symbol. It is up to the semantic() 441 441 // pass to distinguish. 442 442 // If it is a type, then type is set and getType() will return that 443 443 // type. If it is a symbol, then aliassym is set and type is NULL - 444 444 // toAlias() will return aliasssym. 445 445 446 446 Dsymbol *s; 447 447 Type *t; 448 448 Expression *e; 449 449 450 450 /* This section is needed because resolve() will: 451 451 * const x = 3; 452 452 * alias x y; 453 453 * try to alias y to 3. 454 454 */ 455 455 s = type->toDsymbol(sc); 456 456 if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember())) 457 457 goto L2; // it's a symbolic alias 458 458 459 //printf("alias type is %s\n", type->toChars()); 460 type->resolve(loc, sc, &e, &t, &s); 459 if (storage_class & STCref) 460 { // For 'ref' to be attached to function types, and picked 461 // up by Type::resolve(), it has to go into sc. 462 sc = sc->push(); 463 sc->stc |= STCref; 464 type->resolve(loc, sc, &e, &t, &s); 465 sc = sc->pop(); 466 } 467 else 468 type->resolve(loc, sc, &e, &t, &s); 461 469 if (s) 462 470 { 463 471 goto L2; 464 472 } 465 473 else if (e) 466 474 { 467 475 // Try to convert Expression to Dsymbol 468 476 s = getDsymbol(e); 469 477 if (s) 470 478 goto L2; 471 479 472 480 error("cannot alias an expression %s", e->toChars()); 473 481 t = e->type; 474 482 } 475 483 else if (t) 476 484 type = t; 477 485 if (overnext) 478 486 ScopeDsymbol::multiplyDefined(0, this, overnext); 479 487 this->inSemantic = 0; 480 488 return; … … 840 848 if (ti) 841 849 { 842 850 // Take care of nested templates 843 851 while (1) 844 852 { 845 853 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); 846 854 if (!ti2) 847 855 break; 848 856 ti = ti2; 849 857 } 850 858 851 859 // If it's a member template 852 860 AggregateDeclaration *ad = ti->tempdecl->isMember(); 853 861 if (ad && storage_class != STCundefined) 854 862 { 855 863 error("cannot use template to add field to aggregate '%s'", ad->toChars()); 856 864 } 857 865 } 858 866 } 859 867 860 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref) 868 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref && 869 ident != Id::This) 870 { 861 871 error("only parameters or foreach declarations can be ref"); 872 } 862 873 863 874 if (type->isauto() && !noauto) 864 875 { 865 876 if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls) || !fd) 866 877 { 867 878 error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope"); 868 879 } 869 880 870 881 if (!(storage_class & (STCauto | STCscope))) 871 882 { 872 883 if (!(storage_class & STCparameter) && ident != Id::withSym) 873 884 error("reference to scope class must be scope"); 874 885 } 875 886 } 876 887 877 888 if ((isConst() || isInvariant()) && !init && !fd) 878 889 { // Initialize by constructor only 879 890 storage_class |= STCctorinit; 880 891 } 881 892 … … 886 897 887 898 enum TOK op = TOKconstruct; 888 899 if (!init && !sc->inunion && !isStatic() && fd && 889 900 (!(storage_class & (STCfield | STCin | STCforeach | STCparameter)) || (storage_class & STCout)) && 890 901 type->size() != 0) 891 902 { 892 903 // Provide a default initializer 893 904 //printf("Providing default initializer for '%s'\n", toChars()); 894 905 if (type->ty == Tstruct && 895 906 ((TypeStruct *)type)->sym->zeroInit == 1) 896 907 { /* If a struct is all zeros, as a special case 897 908 * set it's initializer to the integer 0. 898 909 * In AssignExp::toElem(), we check for this and issue 899 910 * a memset() to initialize the struct. 900 911 * Must do same check in interpreter. 901 912 */ 902 913 Expression *e = new IntegerExp(loc, 0, Type::tint32); 903 914 Expression *e1; 904 915 e1 = new VarExp(loc, this); 905 916 e = new AssignExp(loc, e1, e); 917 e->op = TOKconstruct; 906 918 e->type = e1->type; // don't type check this, it would fail 907 919 init = new ExpInitializer(loc, e); 908 920 return; 909 921 } 910 922 else if (type->ty == Ttypedef) 911 923 { TypeTypedef *td = (TypeTypedef *)type; 912 924 if (td->sym->init) 913 925 { init = td->sym->init; 914 926 ExpInitializer *ie = init->isExpInitializer(); 915 927 if (ie) 916 928 // Make copy so we can modify it 917 929 init = new ExpInitializer(ie->loc, ie->exp); 918 930 } 919 931 else 920 932 init = getExpInitializer(); 921 933 } 922 934 else 923 935 { 924 936 init = getExpInitializer(); 925 937 } trunk/src/declaration.h
r180 r183 420 420 { 421 421 TypeInfoInvariantDeclaration(Type *tinfo); 422 422 423 423 void toDt(dt_t **pdt); 424 424 }; 425 425 426 426 struct TypeInfoSharedDeclaration : TypeInfoDeclaration 427 427 { 428 428 TypeInfoSharedDeclaration(Type *tinfo); 429 429 430 430 void toDt(dt_t **pdt); 431 431 }; 432 432 #endif 433 433 434 434 /**************************************************************/ 435 435 436 436 struct ThisDeclaration : VarDeclaration 437 437 { 438 438 ThisDeclaration(Type *t); 439 439 Dsymbol *syntaxCopy(Dsymbol *); 440 ThisDeclaration *isThisDeclaration() { return this; } 440 441 }; 441 442 442 443 enum ILS 443 444 { 444 445 ILSuninitialized, // not computed yet 445 446 ILSno, // cannot inline 446 447 ILSyes, // can inline 447 448 }; 448 449 449 450 /**************************************************************/ 450 451 #if V2 451 452 452 453 enum BUILTIN 453 454 { 454 455 BUILTINunknown = -1, // not known if this is a builtin 455 456 BUILTINnot, // this is not a builtin 456 457 BUILTINsin, // std.math.sin 457 458 BUILTINcos, // std.math.cos 458 459 BUILTINtan, // std.math.tan 459 460 BUILTINsqrt, // std.math.sqrt trunk/src/doc.c
r182 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 // This implements the Ddoc capability. 12 12 13 13 #include <stdio.h> 14 14 #include <string.h> 15 15 #include <time.h> 16 16 #include <ctype.h> 17 17 #include <assert.h> 18 18 19 #ifdef IN_GCC 20 #include "mem.h" 21 #else 22 #if _WIN32 23 #include "..\root\mem.h" 24 #elif linux || __APPLE__ 25 #include "../root/mem.h" 26 #else 27 #error "fix this" 28 #endif 29 #endif 30 19 #include "rmem.h" 31 20 #include "root.h" 32 21 33 22 #include "mars.h" 34 23 #include "dsymbol.h" 35 24 #include "macro.h" 36 25 #include "template.h" 37 26 #include "lexer.h" 38 27 #include "aggregate.h" 39 28 #include "declaration.h" 40 29 #include "enum.h" 41 30 #include "id.h" 42 31 #include "module.h" 43 32 #include "scope.h" 44 33 #include "hdrgen.h" 45 34 #include "doc.h" 46 35 #include "mtype.h" 47 36 48 37 struct Escape 49 38 { 50 39 const char *strings[256]; trunk/src/dsymbol.c
r180 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <string.h> 13 13 #include <assert.h> 14 14 15 #include " mem.h"15 #include "rmem.h" 16 16 17 17 #include "mars.h" 18 18 #include "dsymbol.h" 19 19 #include "aggregate.h" 20 20 #include "identifier.h" 21 21 #include "module.h" 22 22 #include "mtype.h" 23 23 #include "expression.h" 24 24 #include "statement.h" 25 25 #include "declaration.h" 26 26 #include "id.h" 27 27 #include "scope.h" 28 28 #include "init.h" 29 29 #include "import.h" 30 30 #include "template.h" 31 31 #include "attrib.h" 32 32 33 33 /****************************** Dsymbol ******************************/ 34 34 35 35 Dsymbol::Dsymbol() … … 989 989 990 990 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s) 991 991 : ScopeDsymbol() 992 992 { 993 993 exp = NULL; 994 994 type = NULL; 995 995 td = s; 996 996 this->sc = sc; 997 997 } 998 998 999 999 Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) 1000 1000 { 1001 1001 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); 1002 1002 if (ident == Id::length || ident == Id::dollar) 1003 1003 { VarDeclaration **pvar; 1004 1004 Expression *ce; 1005 1005 1006 1006 L1: 1007 1007 1008 1008 if (td) 1009 { 1009 { /* $ gives the number of elements in the tuple 1010 */ 1010 1011 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1011 1012 Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); 1012 1013 v->init = new ExpInitializer(0, e); 1013 1014 v->storage_class |= STCstatic | STCconst; 1014 1015 v->semantic(sc); 1015 1016 return v; 1016 1017 } 1017 1018 1018 1019 if (type) 1019 { 1020 { /* $ gives the number of type entries in the type tuple 1021 */ 1020 1022 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1021 1023 Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); 1022 1024 v->init = new ExpInitializer(0, e); 1023 1025 v->storage_class |= STCstatic | STCconst; 1024 1026 v->semantic(sc); 1025 1027 return v; 1026 1028 } 1027 1029 1028 1030 if (exp->op == TOKindex) 1029 { 1031 { /* array[index] where index is some function of $ 1032 */ 1030 1033 IndexExp *ie = (IndexExp *)exp; 1031 1034 1032 1035 pvar = &ie->lengthVar; 1033 1036 ce = ie->e1; 1034 1037 } 1035 1038 else if (exp->op == TOKslice) 1036 { 1039 { /* array[lwr .. upr] where lwr or upr is some function of $ 1040 */ 1037 1041 SliceExp *se = (SliceExp *)exp; 1038 1042 1039 1043 pvar = &se->lengthVar; 1040 1044 ce = se->e1; 1041 1045 } 1042 1046 else 1047 /* Didn't find $, look in enclosing scope(s). 1048 */ 1043 1049 return NULL; 1044 1050 1051 /* If we are indexing into an array that is really a type 1052 * tuple, rewrite this as an index into a type tuple and 1053 * try again. 1054 */ 1045 1055 if (ce->op == TOKtype) 1046 1056 { 1047 1057 Type *t = ((TypeExp *)ce)->type; 1048 1058 if (t->ty == Ttuple) 1049 1059 { type = (TypeTuple *)t; 1050 1060 goto L1; 1051 1061 } 1052 1062 } 1053 1063 1054 if (!*pvar) 1055 { 1064 /* *pvar is lazily initialized, so if we refer to $ 1065 * multiple times, it gets set only once. 1066 */ 1067 if (!*pvar) // if not already initialized 1068 { /* Create variable v and set it to the value of $, 1069 * which will be a constant. 1070 */ 1056 1071 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); 1057 1072 1058 1073 if (ce->op == TOKvar) 1059 1074 { // if ce is const, get its initializer 1060 1075 ce = fromConstInitializer(WANTvalue | WANTinterpret, ce); 1061 1076 } 1062 1077 1063 1078 if (ce->op == TOKstring) 1064 1079 { /* It is for a string literal, so the 1065 1080 * length will be a const. 1066 1081 */ 1067 1082 Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t); 1068 1083 v->init = new ExpInitializer(0, e); 1069 1084 v->storage_class |= STCstatic | STCconst; 1070 1085 } 1071 1086 else if (ce->op == TOKarrayliteral) 1072 1087 { /* It is for an array literal, so the 1073 1088 * length will be a const. 1074 1089 */ 1075 1090 Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t); trunk/src/dsymbol.h
r179 r183 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #ifndef DMD_DSYMBOL_H 12 12 #define DMD_DSYMBOL_H 13 13 14 14 #ifdef __DMC__ 15 15 #pragma once 16 16 #endif /* __DMC__ */ 17 17 18 18 #include "root.h" 19 19 #include "stringtable.h" 20 20 21 21 #include "mars.h" 22 22 #include "arraytypes.h" 23 23 24 24 struct Identifier; 25 25 struct Scope; 26 26 struct DsymbolTable; 27 27 struct Declaration; 28 struct ThisDeclaration; 28 29 struct TupleDeclaration; 29 30 struct TypedefDeclaration; 30 31 struct AliasDeclaration; 31 32 struct AggregateDeclaration; 32 33 struct EnumDeclaration; 33 34 struct ClassDeclaration; 34 35 struct InterfaceDeclaration; 35 36 struct StructDeclaration; 36 37 struct UnionDeclaration; 37 38 struct FuncDeclaration; 38 39 struct FuncAliasDeclaration; 39 40 struct FuncLiteralDeclaration; 40 41 struct CtorDeclaration; 41 42 struct PostBlitDeclaration; 42 43 struct DtorDeclaration; 43 44 struct StaticCtorDeclaration; 44 45 struct StaticDtorDeclaration; 45 46 struct InvariantDeclaration; 46 47 struct UnitTestDeclaration; 47 48 struct NewDeclaration; … … 164 165 165 166 // Backend 166 167 167 168 virtual Symbol *toSymbol(); // to backend symbol 168 169 virtual void toObjFile(int multiobj); // compile to .obj file 169 170 virtual int cvMember(unsigned char *p); // emit cv debug info for member 170 171 171 172 Symbol *toImport(); // to backend import symbol 172 173 static Symbol *toImport(Symbol *s); // to backend import symbol 173 174 174 175 Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper 175 176 176 177 // Eliminate need for dynamic_cast 177 178 virtual Package *isPackage() { return NULL; } 178 179 virtual Module *isModule() { return NULL; } 179 180 virtual EnumMember *isEnumMember() { return NULL; } 180 181 virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; } 181 182 virtual TemplateInstance *isTemplateInstance() { return NULL; } 182 183 virtual TemplateMixin *isTemplateMixin() { return NULL; } 183 184 virtual Declaration *isDeclaration() { return NULL; } 185 virtual ThisDeclaration *isThisDeclaration() { return NULL; } 184 186 virtual TupleDeclaration *isTupleDeclaration() { return NULL; } 185 187 virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; } 186 188 virtual AliasDeclaration *isAliasDeclaration() { return NULL; } 187 189 virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; } 188 190 virtual FuncDeclaration *isFuncDeclaration() { return NULL; } 189 191 virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; } 190 192 virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; } 191 193 virtual CtorDeclaration *isCtorDeclaration() { return NULL; } 192 194 virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; } 193 195 virtual DtorDeclaration *isDtorDeclaration() { return NULL; } 194 196 virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; } 195 197 virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; } 196 198 virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; } 197 199 virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; } 198 200 virtual NewDeclaration *isNewDeclaration() { return NULL; } 199 201 virtual VarDeclaration *isVarDeclaration() { return NULL; } 200 202 virtual ClassDeclaration *isClassDeclaration() { return NULL; } 201 203 virtual StructDeclaration *isStructDeclaration() { return NULL; } 202 204 virtual UnionDeclaration *isUnionDeclaration() { return NULL; } 203 205 virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; } trunk/src/e2ir.c
r182 r183 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-200 8by Digital Mars3 // Copyright (c) 1999-2009 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <string.h> 13 13 #include <time.h> 14 14 #include <complex.h> 15 15 16 16 #include "lexer.h" 17 17 #include "expression.h" 18 18 #include "mtype.h" 19 19 #include "dsymbol.h" 20 20 #include "declaration.h" 21 21 #include "enum.h" 22 22 #include "aggregate.h" 23 23 #include "attrib.h" 24 24 #include "module.h" 25 25 #include "init.h" 26 26 #include "template.h" 27 27 28 #if _WIN32 29 #include "..\tk\mem.h" // for mem_malloc 30 #elif linux || __APPLE__ 31 #include "../tk/mem.h" // for mem_malloc 32 #endif 28 #include "mem.h" // for tk/mem_malloc 33 29 34 30 #include "cc.h" 35 31 #include "el.h" 36 32 #include "oper.h" 37 33 #include "global.h" 38 34 #include "code.h" 39 35 #include "type.h" 40 36 #include "dt.h" 41 37 #include "irstate.h" 42 38 #include "id.h" 43 39 #include "type.h" 44 40 #include "toir.h" 45 41 46 42 static char __file__[] = __FILE__; /* for tassert.h */ 47 43 #include "tassert.h" 48 44 49 45 50 46 elem *addressElem(elem *e, Type *t); 51 47 elem *array_toPtr(Type *t, elem *e); 52 48 elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result); … … 1515 1512 if (cdp != cdthis) 1516 1513 { int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset); 1517 1514 assert(i); 1518 1515 } 1519 1516 ethis = thisexp->toElem(irs); 1520 1517 if (offset) 1521 1518 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset)); 1522 1519 1523 1520 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset)); 1524 1521 ey = el_una(OPind, TYnptr, ey); 1525 1522 ey = el_bin(OPeq, TYnptr, ey, ethis); 1526 1523 1527 1524 //printf("ex: "); elem_print(ex); 1528 1525 //printf("ey: "); elem_print(ey); 1529 1526 //printf("ez: "); elem_print(ez); 1530 1527 } 1531 1528 else if (cd->isNested()) 1532 1529 { /* Initialize cd->vthis: 1533 1530 * *(ey + cd.vthis.offset) = this; 1534 1531 */ 1535 elem *ethis; 1536 FuncDeclaration *thisfd = irs->getFunc(); 1537 int offset = 0; 1538 Dsymbol *cdp = cd->toParent2(); // class/func we're nested in 1539 1540 if (cdp == thisfd) 1541 { /* Class we're new'ing is a local class in this function: 1542 * void thisfd() { class cd { } } 1543 */ 1544 if (irs->sclosure) 1545 ethis = el_var(irs->sclosure); 1546 else if (irs->sthis) 1547 { 1548 #if V2 1549 if (thisfd->closureVars.dim) 1550 #else 1551 if (thisfd->nestedFrameRef) 1552 #endif 1553 { 1554 ethis = el_ptr(irs->sthis); 1555 } 1556 else 1557 ethis = el_var(irs->sthis); 1558 } 1559 else 1560 { 1561 ethis = el_long(TYnptr, 0); 1562 #if V2 1563 if (thisfd->closureVars.dim) 1564 #else 1565 if (thisfd->nestedFrameRef) 1566 #endif 1567 { 1568 ethis->Eoper = OPframeptr; 1569 } 1570 } 1571 } 1572 else if (thisfd->vthis && 1573 (cdp == thisfd->toParent2() || 1574 (cdp->isClassDeclaration() && 1575 cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset) 1576 ) 1577 ) 1578 ) 1579 { /* Class we're new'ing is at the same level as thisfd 1580 */ 1581 assert(offset == 0); // BUG: should handle this case 1582 ethis = el_var(irs->sthis); 1583 } 1584 else 1585 { 1586 ethis = getEthis(loc, irs, cd->toParent2()); 1587 ethis = el_una(OPaddr, TYnptr, ethis); 1588 } 1589 1590 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset)); 1591 ey = el_una(OPind, TYnptr, ey); 1592 ey = el_bin(OPeq, TYnptr, ey, ethis); 1593 1532 ey = setEthis(loc, irs, ey, cd); 1594 1533 } 1595 1534 1596 1535 if (member) 1597 1536 // Call constructor 1598 1537 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments); 1599 1538 1600 1539 e = el_combine(ex, ey); 1601 1540 e = el_combine(e, ez); 1602 1541 } 1603 1542 else if (t->ty == Tpointer && t->nextOf()->toBasetype()->ty == Tstruct) 1604 1543 { 1605 1544 Symbol *csym; 1606 1545 1607 1546 t = newtype->toBasetype(); 1608 1547 assert(t->ty == Tstruct); 1609 1548 TypeStruct *tclass = (TypeStruct *)(t); 1610 1549 StructDeclaration *cd = tclass->sym; 1611 1550 1612 1551 /* Things to do: 1613 1552 * 1) ex: call allocator 1614 1553 * 2) ey: set vthis for nested classes 1615 1554 * 3) ez: call constructor 1616 1555 */ 1617 1556 1618 1557 elem *ex = NULL; 1619 1558 elem *ey = NULL; 1620 1559 elem *ez = NULL; 1621 1560 1622 1561 if (allocator) 1623 1562 { elem *ei; 1624 1563 Symbol *si; 1625 1564 1626 1565 ex = el_var(allocator->toSymbol()); 1627 1566 ex = callfunc(loc, irs, 1, type, ex, allocator->type, 1628 1567 allocator, allocator->type, NULL, newargs); 1629 1568 1630 1569 si = tclass->sym->toInitializer(); 1631 1570 ei = el_var(si); 1632 1571 1633 if (member) 1572 if (cd->isNested()) 1573 { 1574 ey = el_same(&ex); 1575 ez = el_copytree(ey); 1576 } 1577 else if (member) 1634 1578 ez = el_same(&ex); 1635 else 1579 1580 if (!member) 1636 1581 { /* Statically intialize with default initializer 1637 1582 */ 1638 1583 ex = el_una(OPind, TYstruct, ex); 1639 1584 ex = el_bin(OPstreq, TYnptr, ex, ei); 1640 1585 ex->Enumbytes = cd->size(loc); 1641 1586 ex = el_una(OPaddr, TYnptr, ex); 1642 1587 } 1643 1588 ectype = tclass; 1644 1589 } 1645 1590 else 1646 1591 { 1647 1592 d_uns64 elemsize = cd->size(loc); 1648 1593 1649 1594 // call _d_newarrayT(ti, 1) 1650 1595 e = el_long(TYsize_t, 1); 1651 1596 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); 1652 1597 1653 1598 int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; 1654 1599 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); 1655 1600 1656 1601 // The new functions return an array, so convert to a pointer 1657 1602 // ex -> (unsigned)(e >> 32) 1658 1603 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); 1659 1604 ex = el_una(OP64_32, TYnptr, e); 1660 1605 1661 1606 ectype = NULL; 1662 1607 1663 if (member) 1608 if (cd->isNested()) 1609 { 1610 ey = el_same(&ex); 1611 ez = el_copytree(ey); 1612 } 1613 else if (member) 1664 1614 ez = el_same(&ex); 1665 1615 //elem_print(ex); 1666 1616 //elem_print(ey); 1667 1617 //elem_print(ez); 1618 } 1619 1620 if (cd->isNested()) 1621 { /* Initialize cd->vthis: 1622 * *(ey + cd.vthis.offset) = this; 1623 */ 1624 ey = setEthis(loc, irs, ey, cd); 1668 1625 } 1669 1626 1670 1627 if (member) 1671 1628 { // Call constructor 1672 1629 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments); 1673 1630 #if STRUCTTHISREF 1674 1631 /* Structs return a ref, which gets automatically dereferenced. 1675 1632 * But we want a pointer to the instance. 1676 1633 */ 1677 1634 ez = el_una(OPaddr, TYnptr, ez); 1678 1635 #endif 1679 1636 } 1680 1637 1681 1638 e = el_combine(ex, ey); 1682 1639 e = el_combine(e, ez); 1683 1640 } 1684 1641 else if (t->ty == Tarray) 1685 1642 { 1686 1643 TypeDArray *tda = (TypeDArray *)(t); 1687 1644 … … 2736 2693 elem *eb; 2737 2694 elem *ei; 2738 2695 elem *ev; 2739 2696 TY ty; 2740 2697 Type *ta; 2741 2698 2742 2699 ae = (IndexExp *)(e1); 2743 2700 ta = ae->e1->type->toBasetype(); 2744 2701 ty = ta->ty; 2745 2702 } 2746 2703 2747 2704 #if V2 2748 2705 /* Look for reference initializations 2749 2706 */ 2750 2707 if (op == TOKconstruct && e1->op == TOKvar) 2751 2708 { 2752 2709 VarExp *ve = (VarExp *)e1; 2753 2710 Declaration *s = ve->var; 2754 2711 if (s->storage_class & STCref) 2755 2712 { 2713 #if 0 2756 2714 Expression *ae = e2->addressOf(NULL); 2757 2715 e = ae->toElem(irs); 2716 #else 2717 e = e2->toElem(irs); 2718 e = addressElem(e, e2->type); 2719 #endif 2758 2720 elem *es = el_var(s->toSymbol()); 2759 2721 es->Ety = TYnptr; 2760 2722 e = el_bin(OPeq, TYnptr, es, e); 2723 // BUG: type is struct, and e2 is TOKint64 2761 2724 goto Lret; 2762 2725 } 2763 2726 } 2764 2727 #endif 2765 2728 2766 2729 #if 1 2767 2730 /* This will work if we can distinguish an assignment from 2768 2731 * an initialization of the lvalue. It'll work if the latter. 2769 2732 * If the former, because of aliasing of the return value with 2770 2733 * function arguments, it'll fail. 2771 2734 */ 2772 2735 if (op == TOKconstruct && e2->op == TOKcall) 2773 2736 { CallExp *ce = (CallExp *)e2; 2774 2737 2775 2738 TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype(); 2776 2739 if (tf->ty == Tfunction && tf->retStyle() == RETstack) 2777 2740 { 2778 2741 elem *ehidden = e1->toElem(irs); 2779 2742 ehidden = el_una(OPaddr, TYnptr, ehidden); 2780 2743 assert(!irs->ehidden); 2781 2744 irs->ehidden = ehidden; 2782 2745 e = e2->toElem(irs); 2783 2746 goto Lret; 2784 2747 } 2785 2748 } 2786 2749 #endif 2750 //printf("test1 %d\n", op); 2751 //if (op == TOKconstruct) printf("construct\n"); 2787 2752 if (t1b->ty == Tstruct) 2788 { 2753 { elem *eleft = e1->toElem(irs); 2754 2789 2755 if (e2->op == TOKint64) 2790 2756 { /* Implement: 2791 2757 * (struct = 0) 2792 2758 * with: 2793 2759 * memset(&struct, 0, struct.sizeof) 2794 2760 */ 2795 elem *el = e1->toElem(irs); 2796 elem *enbytes = el_long(TYint, e1->type->size()); 2761 elem *ey = NULL; 2762 int sz = e1->type->size(); 2763 StructDeclaration *sd = ((TypeStruct *)t1b)->sym; 2764 if (sd->isnested && op == TOKconstruct) 2765 { 2766 ey = el_una(OPaddr, TYnptr, eleft); 2767 eleft = el_same(&ey); 2768 ey = setEthis(loc, irs, ey, sd); 2769 sz = sd->vthis->offset; 2770 } 2771 2772 elem *el = eleft; 2773 elem *enbytes = el_long(TYint, sz); 2797 2774 elem *evalue = el_long(TYint, 0); 2798 2775 2799 el = el_una(OPaddr, TYnptr, el); 2776 if (!(sd->isnested && op == TOKconstruct)) 2777 el = el_una(OPaddr, TYnptr, el); 2800 2778 e = el_param(enbytes, evalue); 2801 2779 e = el_bin(OPmemset,TYnptr,el,e); 2780 e = el_combine(ey, e); 2802 2781 el_setLoc(e, loc); 2803 2782 //e = el_una(OPind, TYstruct, e); 2804 2783 } 2805 2784 else 2806 2785 { 2807 elem *e1;2808 elem *e2;2809 tym_t tym;2810 2811 2786 //printf("toElemBin() '%s'\n", toChars()); 2812 2787 2813 tym = type->totym();2814 2815 e 1 = this->e1->toElem(irs);2788 tym_t tym = type->totym(); 2789 2790 elem *e1 = eleft; 2816 2791 elem *ex = e1; 2817 2792 if (e1->Eoper == OPind) 2818 2793 ex = e1->E1; 2819 2794 if (this->e2->op == TOKstructliteral && 2820 2795 ex->Eoper == OPvar && ex->EV.sp.Voffset == 0) 2821 2796 { StructLiteralExp *se = (StructLiteralExp *)this->e2; 2822 2797 2823 2798 Symbol *symSave = se->sym; 2824 2799 size_t soffsetSave = se->soffset; 2825 2800 int fillHolesSave = se->fillHoles; 2826 2801 2827 2802 se->sym = ex->EV.sp.Vsym; 2828 2803 se->soffset = 0; 2829 2804 se->fillHoles = (op == TOKconstruct || op == TOKblit) ? 1 : 0; 2830 2805 2831 2806 el_free(e1); 2832 2807 e = this->e2->toElem(irs); 2833 2808 2834 2809 se->sym = symSave; 2835 2810 se->soffset = soffsetSave; 2836 2811 se->fillHoles = fillHolesSave; 2837 2812 } 2838 2813 else 2839 2814 { 2840 e 2 = this->e2->toElem(irs);2815 elem *e2 = this->e2->toElem(irs); 2841 2816 e = el_bin(OPstreq,tym,e1,e2); 2842 2817 e->Enumbytes = this->e1->type->size(); 2843 2818 } 2844 2819 goto Lret; 2845 2820 } 2846 2821 } 2847 2822 else 2848 2823 e = toElemBin(irs,OPeq); 2849 2824 return e; 2850 2825 2851 2826 Lret: 2852 2827 el_setLoc(e,loc); 2853 2828 return e; 2854 2829 } 2855 2830 2856 2831 /*************************************** 2857 2832 */ 2858 2833 2859 2834 elem *AddAssignExp::toElem(IRState *irs) 2860 2835 { … … 3967 3942 case X(Tfloat64,Tfloat80): eop = OPd_ld; goto Leop; 3968 3943 case X(Tfloat64,Timaginary32): goto Lzero; 3969 3944 case X(Tfloat64,Timaginary64): goto Lzero; 3970 3945 case X(Tfloat64,Timaginary80): goto Lzero; 3971 3946 case X(Tfloat64,Tcomplex32): 3972 3947 case X(Tfloat64,Tcomplex64): 3973 3948 case X(Tfloat64,Tcomplex80): 3974 3949 e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e); 3975 3950 fty = Tcomplex64; 3976 3951 goto Lagain; 3977 3952 3978 3953 /* ============================= */ 3979 3954 3980 3955 case X(Tfloat80,Tint8): 3981 3956 case X(Tfloat80,Tuns8): 3982 3957 case X(Tfloat80,Tint16): 3983 3958 case X(Tfloat80,Tuns16): 3984 3959 case X(Tfloat80,Tint32): 3985 3960 case X(Tfloat80,Tuns32): 3986 3961 case X(Tfloat80,Tint64): 3987 case X(Tfloat80,Tuns64):3988 3962 case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e); 3989 3963 fty = Tfloat64; 3990 3964 goto Lagain; 3965 case X(Tfloat80,Tuns64): 3966 eop = OPld_u64; goto Leop; 3991 3967 case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop; 3992 3968 case X(Tfloat80,Timaginary32): goto Lzero; 3993 3969 case X(Tfloat80,Timaginary64): goto Lzero; 3994 3970 case X(Tfloat80,Timaginary80): goto Lzero; 3995 3971 case X(Tfloat80,Tcomplex32): 3996 3972 case X(Tfloat80,Tcomplex64): 3997 3973 case X(Tfloat80,Tcomplex80): 3998 3974 e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0)); 3999 3975 fty = Tcomplex80; 4000 3976 goto Lagain; 4001 3977 4002 3978 /* ============================= */ 4003 3979 4004 3980 case X(Timaginary32,Tint8): 4005 3981 case X(Timaginary32,Tuns8): 4006 3982 case X(Timaginary32,Tint16): 4007 3983 case X(Timaginary32,Tuns16): 4008 3984 case X(Timaginary32,Tint32): 4009 3985 case X(Timaginary32,Tuns32): 4010 3986 case X(Timaginary32,Tint64): … … 4620 4596 e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize)); 4621 4597 size_t vend = v->offset + v->type->size(); 4622 4598 if (offset < vend) 4623 4599 offset = vend; 4624 4600 } 4625 4601 e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize)); 4626 4602 } 4627 4603 4628 4604 if (elements) 4629 4605 { 4630 4606 dim = elements->dim; 4631 4607 assert(dim <= sd->fields.dim); 4632 4608 for (size_t i = 0; i < dim; i++) 4633 4609 { Expression *el = (Expression *)elements->data[i]; 4634 4610 if (!el) 4635 4611 continue; 4636 4612 4637 4613 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; 4638 4614 VarDeclaration *v = s->isVarDeclaration(); 4639 4615 assert(v); 4616 assert(!v->isThisDeclaration()); 4640 4617 4641 4618 elem *e1; 4642 4619 if (tybasic(stmp->Stype->Tty) == TYnptr) 4643 4620 { e1 = el_var(stmp); 4644 4621 e1->EV.sp.Voffset = soffset; 4645 4622 } 4646 4623 else 4647 4624 { e1 = el_ptr(stmp); 4648 4625 if (soffset) 4649 4626 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); 4650 4627 } 4651 4628 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset)); 4652 4629 elem *ec = e1; // pointer to destination 4653 4630 4654 4631 elem *ep = el->toElem(irs); 4655 4632 4656 4633 Type *t1b = v->type->toBasetype(); 4657 4634 Type *t2b = el->type->toBasetype(); 4658 4635 if (t1b->ty == Tsarray) 4659 4636 { … … 4713 4690 } 4714 4691 #if V2 4715 4692 /* Call postBlit() on e1 4716 4693 */ 4717 4694 Type *tb = v->type->toBasetype(); 4718 4695 if (tb->ty == Tstruct) 4719 4696 { StructDeclaration *sd = ((TypeStruct *)tb)->sym; 4720 4697 if (sd->postblit) 4721 4698 { FuncDeclaration *fd = sd->postblit; 4722 4699 ec = el_copytree(ec); 4723 4700 ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL); 4724 4701 e1 = el_bin(OPcomma, ec->Ety, e1, ec); 4725 4702 } 4726 4703 } 4727 4704 #endif 4728 4705 } 4729 4706 e = el_combine(e, e1); 4730 4707 } 4731 4708 } 4732 4709 4710 if (sd->isnested) 4711 { // Initialize the hidden 'this' pointer 4712 assert(sd->fields.dim); 4713 Dsymbol *s = (Dsymbol *)sd->fields.data[sd->fields.dim - 1]; 4714 ThisDeclaration *v = s->isThisDeclaration(); 4715 assert(v); 4716 4717 elem *e1; 4718 if (tybasic(stmp->Stype->Tty) == TYnptr) 4719 { e1 = el_var(stmp); 4720 e1->EV.sp.Voffset = soffset; 4721 } 4722 else 4723 { e1 = el_ptr(stmp); 4724 if (soffset) 4725 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); 4726 } 4727 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset)); 4728 e1 = setEthis(loc, irs, e1, sd); 4729 4730 e = el_combine(e, e1); 4731 } 4732 4733 4733 elem *ev = el_var(stmp); 4734 4734 ev->Enumbytes = sd->structsize; 4735 4735 e = el_combine(e, ev); 4736 4736 el_setLoc(e,loc); 4737 4737 return e; 4738 4738 } trunk/src/expression.c
r182 r183 15 15 #include <assert.h> 16 16 #if _MSC_VER 17 17 #include <complex> 18 18 #else 19 19 #include <complex.h> 20 20 #endif 21 21 22 22 #if _WIN32 && __DMC__ 23 23 extern "C" char * __cdecl __locale_decpoint; 24 24 #endif 25 25 26 26 #if IN_GCC 27 27 // Issues with using -include total.h (defines integer_t) and then complex.h fails... 28 28 #undef integer_t 29 29 #endif 30 30 31 31 #ifdef __APPLE__ 32 32 #define integer_t dmd_integer_t 33 33 #endif 34 34 35 #if IN_GCC 36 #include "mem.h" 37 #elif _WIN32 38 #include "..\root\mem.h" 39 #elif linux || __APPLE__ 40 #include "../root/mem.h" 41 #endif 35 #include "rmem.h" 42 36 43 37 //#include "port.h" 44 38 #include "mtype.h" 45 39 #include "init.h" 46 40 #include "expression.h" 47 41 #include "template.h" 48 42 #include "utf.h" 49 43 #include "enum.h" 50 44 #include "scope.h" 51 45 #include "statement.h" 52 46 #include "declaration.h" 53 47 #include "aggregate.h" 54 48 #include "import.h" 55 49 #include "id.h" 56 50 #include "dsymbol.h" 57 51 #include "module.h" 58 52 #include "attrib.h" 59 53 #include "hdrgen.h" 60 54 #include "parse.h" 61 55 … … 933 927 } 934 928 935 929 char *Expression::toChars() 936 930 { OutBuffer *buf; 937 931 HdrGenState hgs; 938 932 939 933 memset(&hgs, 0, sizeof(hgs)); 940 934 buf = new OutBuffer(); 941 935 toCBuffer(buf, &hgs); 942 936 return buf->toChars(); 943 937 } 944 938 945 939 void Expression::error(const char *format, ...) 946 940 { 947 941 va_list ap; 948 942 va_start(ap, format); 949 943 ::verror(loc, format, ap); 950 944 va_end( ap ); 951 945 } 952 946 947 void Expression::warning(const char *format, ...) 948 { 949 if (global.params.warnings && !global.gag) 950 { 951 fprintf(stdmsg, "warning - "); 952 va_list ap; 953 va_start(ap, format); 954 ::verror(loc, format, ap); 955 va_end( ap ); 956 } 957 } 958 953 959 void Expression::rvalue() 954 960 { 955 961 if (type && type->toBasetype()->ty == Tvoid) 956 962 { error("expression %s is void and has no value", toChars()); 957 963 #if 0 958 964 dump(0); 959 965 halt(); 960 966 #endif 961 967 type = Type::tint32; 962 968 } 963 969 } 964 970 965 971 Expression *Expression::combine(Expression *e1, Expression *e2) 966 972 { 967 973 if (e1) 968 974 { 969 975 if (e2) 970 976 { 971 977 e1 = new CommaExp(e1->loc, e1, e2); 972 978 e1->type = e2->type; … … 3055 3061 3056 3062 // sd( e1, e2, e3, ... ) 3057 3063 3058 3064 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements) 3059 3065 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) 3060 3066 { 3061 3067 this->sd = sd; 3062 3068 this->elements = elements; 3063 3069 this->sym = NULL; 3064 3070 this->soffset = 0; 3065 3071 this->fillHoles = 1; 3066 3072 } 3067 3073 3068 3074 Expression *StructLiteralExp::syntaxCopy() 3069 3075 { 3070 3076 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); 3071 3077 } 3072 3078 3073 3079 Expression *StructLiteralExp::semantic(Scope *sc) 3074 3080 { Expression *e; 3081 int nfields = sd->fields.dim - sd->isnested; 3075 3082 3076 3083 #if LOGSEMANTIC 3077 3084 printf("StructLiteralExp::semantic('%s')\n", toChars()); 3078 3085 #endif 3079 3086 if (type) 3080 3087 return this; 3081 3088 3082 3089 // Run semantic() on each element 3083 3090 for (size_t i = 0; i < elements->dim; i++) 3084 3091 { e = (Expression *)elements->data[i]; 3085 3092 if (!e) 3086 3093 continue; 3087 3094 e = e->semantic(sc); 3088 3095 elements->data[i] = (void *)e; 3089 3096 } 3090 3097 expandTuples(elements); 3091 3098 size_t offset = 0; 3092 3099 for (size_t i = 0; i < elements->dim; i++) 3093 3100 { e = (Expression *)elements->data[i]; 3094 3101 if (!e) 3095 3102 continue; 3096 3103 3097 3104 if (!e->type) 3098 3105 error("%s has no value", e->toChars()); 3099 3106 e = resolveProperties(sc, e); 3100 if (i >= sd->fields.dim)3107 if (i >= nfields) 3101 3108 { error("more initializers than fields of %s", sd->toChars()); 3102 3109 break; 3103 3110 } 3104 3111 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; 3105 3112 VarDeclaration *v = s->isVarDeclaration(); 3106 3113 assert(v); 3107 3114 if (v->offset < offset) 3108 3115 error("overlapping initialization for %s", v->toChars()); 3109 3116 offset = v->offset + v->type->size(); 3110 3117 3111 3118 Type *telem = v->type; 3112 3119 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) 3113 3120 { /* Static array initialization, as in: 3114 3121 * T[3][5] = e; 3115 3122 */ 3116 3123 telem = telem->toBasetype()->nextOf(); 3117 3124 } 3118 3125 3119 3126 e = e->implicitCastTo(sc, telem); 3120 3127 3121 3128 elements->data[i] = (void *)e; 3122 3129 } 3123 3130 3124 3131 /* Fill out remainder of elements[] with default initializers for fields[] 3125 3132 */ 3126 for (size_t i = elements->dim; i < sd->fields.dim; i++)3133 for (size_t i = elements->dim; i < nfields; i++) 3127 3134 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; 3128 3135 VarDeclaration *v = s->isVarDeclaration(); 3129 3136 assert(v); 3137 assert(!v->isThisDeclaration()); 3130 3138 3131 3139 if (v->offset < offset) 3132 3140 { e = NULL; 3133 3141 sd->hasUnions = 1; 3134 3142 } 3135 3143 else 3136 3144 { 3137 3145 if (v->init) 3138 3146 { e = v->init->toExpression(); 3139 3147 if (!e) 3140 3148 error("cannot make expression out of initializer for %s", v->toChars()); 3141 3149 } 3142 3150 else 3143 3151 { e = v->type->defaultInit(); 3144 3152 e->loc = loc; 3145 3153 } 3146 3154 offset = v->offset + v->type->size(); 3147 3155 } 3148 3156 elements->push(e); 3149 3157 } … … 4681 4689 assert(0); 4682 4690 } 4683 4691 goto Lyes; 4684 4692 } 4685 4693 else if (id && tspec) 4686 4694 { 4687 4695 /* Evaluate to TRUE if targ matches tspec. 4688 4696 * If TRUE, declare id as an alias for the specialized type. 4689 4697 */ 4690 4698 4691 4699 MATCH m; 4692 4700 assert(parameters && parameters->dim); 4693 4701 4694 4702 Objects dedtypes; 4695 4703 dedtypes.setDim(parameters->dim); 4696 4704 dedtypes.zero(); 4697 4705 4698 4706 m = targ->deduceType(NULL, tspec, parameters, &dedtypes); 4699 4707 if (m == MATCHnomatch || 4700 4708 (m != MATCHexact && tok == TOKequal)) 4709 { 4701 4710 goto Lno; 4711 } 4702 4712 else 4703 4713 { 4704 4714 tded = (Type *)dedtypes.data[0]; 4705 4715 if (!tded) 4706 4716 tded = targ; 4707 4717 4708 4718 Objects tiargs; 4709 4719 tiargs.setDim(1); 4710 4720 tiargs.data[0] = (void *)targ; 4711 4721 4712 4722 for (int i = 1; i < parameters->dim; i++) 4713 4723 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; 4714 4724 Declaration *s; 4715 4725 4716 4726 m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s); 4717 4727 if (m == MATCHnomatch) 4718 4728 goto Lno; 4719 4729 s->semantic(sc); 4720 4730 if (!sc->insert(s)) 4721 4731 error("declaration %s is already defined", s->toChars()); … … 4723 4733 Object *o = (Object *)dedtypes.data[i]; 4724 4734 Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o); 4725 4735 #endif 4726 4736 if (sc->sd) 4727 4737 s->addMember(sc, sc->sd, 1); 4728 4738 } 4729 4739 4730 4740 goto Lyes; 4731 4741 } 4732 4742 } 4733 4743 else if (id) 4734 4744 { 4735 4745 /* Declare id as an alias for type targ. Evaluate to TRUE 4736 4746 */ 4737 4747 tded = targ; 4738 4748 goto Lyes; 4739 4749 } 4740 4750 else if (tspec) 4741 4751 { 4742 4752 /* Evaluate to TRUE if targ matches tspec 4753 * is(targ == tspec) 4754 * is(targ : tspec) 4743 4755 */ 4744 4756 tspec = tspec->semantic(loc, sc); 4745 4757 //printf("targ = %s\n", targ->toChars()); 4746 4758 //printf("tspec = %s\n", tspec->toChars()); 4747 4759 if (tok == TOKcolon) 4748 4760 { if (targ->implicitConvTo(tspec)) 4749 4761 goto Lyes; 4750 4762 else 4751 4763 goto Lno; 4752 4764 } 4753 4765 else /* == */ 4754 4766 { if (targ->equals(tspec)) 4755 4767 goto Lyes; 4756 4768 else 4757 4769 goto Lno; 4758 4770 } 4759 4771 } 4760 4772 4761 4773 Lyes: 4762 4774 if (id) … … 5952 5964 arguments->data[0] = (void *)earg1; 5953 5965 arguments->data[1] = (void *)earg2; 5954 5966 5955 5967 this->arguments = arguments; 5956 5968 } 5957 5969 5958 5970 Expression *CallExp::syntaxCopy() 5959 5971 { 5960 5972 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); 5961 5973 } 5962 5974 5963 5975 5964 5976 Expression *CallExp::semantic(Scope *sc) 5965 5977 { 5966 5978 TypeFunction *tf; 5967 5979 FuncDeclaration *f; 5968 5980 int i; 5969 5981 Type *t1; 5970 5982 int istemp; 5971 5983 Objects *targsi = NULL; // initial list of template arguments 5984 TemplateInstance *tierror = NULL; 5972 5985 5973 5986 #if LOGSEMANTIC 5974 5987 printf("CallExp::semantic() %s\n", toChars()); 5975 5988 #endif 5976 5989 if (type) 5977 5990 return this; // semantic() already run 5978 5991 #if 0 5979 5992 if (arguments && arguments->dim) 5980 5993 { 5981 5994 Expression *earg = (Expression *)arguments->data[0]; 5982 5995 earg->print(); 5983 5996 if (earg->type) earg->type->print(); 5984 5997 } 5985 5998 #endif 5986 5999 5987 6000 if (e1->op == TOKdelegate) 5988 6001 { DelegateExp *de = (DelegateExp *)e1; 5989 6002 5990 6003 e1 = new DotVarExp(de->loc, de->e1, de->func); 5991 6004 return semantic(sc); … … 6041 6054 */ 6042 6055 if (e1->op == TOKimport && !e1->type) 6043 6056 { ScopeExp *se = (ScopeExp *)e1; 6044 6057 TemplateInstance *ti = se->sds->isTemplateInstance(); 6045 6058 if (ti && !ti->semanticdone) 6046 6059 { 6047 6060 /* Attempt to instantiate ti. If that works, go with it. 6048 6061 * If not, go with partial explicit specialization. 6049 6062 */ 6050 6063 ti->semanticTiargs(sc); 6051 6064 unsigned errors = global.errors; 6052 6065 global.gag++; 6053 6066 ti->semantic(sc); 6054 6067 global.gag--; 6055 6068 if (errors != global.errors) 6056 6069 { 6057 6070 /* Didn't work, go with partial explicit specialization 6058 6071 */ 6059 6072 global.errors = errors; 6060 6073 targsi = ti->tiargs; 6074 tierror = ti; // for error reporting 6061 6075 e1 = new IdentifierExp(loc, ti->name); 6062 6076 } 6063 6077 } 6064 6078 } 6065 6079 6066 6080 /* This recognizes: 6067 6081 * expr.foo!(tiargs)(funcargs) 6068 6082 */ 6069 6083 if (e1->op == TOKdotti && !e1->type) 6070 6084 { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1; 6071 6085 TemplateInstance *ti = se->ti; 6072 6086 if (!ti->semanticdone) 6073 6087 { 6074 6088 /* Attempt to instantiate ti. If that works, go with it. 6075 6089 * If not, go with partial explicit specialization. 6076 6090 */ 6077 6091 ti->semanticTiargs(sc); 6078 6092 Expression *etmp; 6079 6093 unsigned errors = global.errors; 6080 6094 global.gag++; 6081 6095 etmp = e1->semantic(sc); 6082 6096 global.gag--; 6083 6097 if (errors != global.errors) 6084 6098 { 6085 6099 global.errors = errors; 6086 6100 targsi = ti->tiargs; 6101 tierror = ti; // for error reporting 6087 6102 e1 = new DotIdExp(loc, se->e1, ti->name); 6088 6103 } 6089 6104 else 6090 6105 e1 = etmp; 6091 6106 } 6092 6107 } 6093 6108 #endif 6094 6109 6095 6110 istemp = 0; 6096 6111 Lagain: 6097 6112 //printf("Lagain: %s\n", toChars()); 6098 6113 f = NULL; 6099 6114 if (e1->op == TOKthis || e1->op == TOKsuper) 6100 6115 { 6101 6116 // semantic() run later for these 6102 6117 } 6103 6118 else 6104 6119 { 6105 6120 UnaExp::semantic(sc); 6106 6121 … … 6466 6481 { 6467 6482 if (t1->ty == Tdelegate) 6468 6483 { TypeDelegate *td = (TypeDelegate *)t1; 6469 6484 assert(td->next->ty == Tfunction); 6470 6485 tf = (TypeFunction *)(td->next); 6471 6486 goto Lcheckargs; 6472 6487 } 6473 6488 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) 6474 6489 { Expression *e; 6475 6490 6476 6491 e = new PtrExp(loc, e1); 6477 6492 t1 = ((TypePointer *)t1)->next; 6478 6493 e->type = t1; 6479 6494 e1 = e; 6480 6495 } 6481 6496 else if (e1->op == TOKtemplate) 6482 6497 { 6483 6498 TemplateExp *te = (TemplateExp *)e1; 6484 6499 f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); 6485 6500 if (!f) 6486 { type = Type::terror; 6501 { if (tierror) 6502 tierror->error("errors instantiating template"); // give better error message 6503 type = Type::terror; 6487 6504 return this; 6488 6505 } 6489 6506 if (f->needThis() && hasThis(sc)) 6490 6507 { 6491 6508 // Supply an implicit 'this', as in 6492 6509 // this.ident 6493 6510 6494 6511 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); 6495 6512 goto Lagain; 6496 6513 } 6497 6514 6498 6515 e1 = new VarExp(loc, f); 6499 6516 goto Lagain; 6500 6517 } 6501 6518 else 6502 6519 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); 6503 6520 type = Type::terror; 6504 6521 return this; 6505 6522 } 6506 6523 } … … 6609 6626 return 1; 6610 6627 } 6611 6628 6612 6629 /* If calling a function or delegate that is typed as nothrow, 6613 6630 * then this expression cannot throw. 6614 6631 * Note that pure functions can throw. 6615 6632 */ 6616 6633 Type *t = e1->type->toBasetype(); 6617 6634 if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow) 6618 6635 return 0; 6619 6636 if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) 6620 6637 return 0; 6621 6638 6622 6639 return 1; 6623 6640 } 6624 6641 #endif 6625 6642 6626 6643 #if V2 6627 6644 int CallExp::isLvalue() 6628 6645 { 6629 if (type->toBasetype()->ty == Tstruct)6630 return 1;6646 // if (type->toBasetype()->ty == Tstruct) 6647 // return 1; 6631 6648 Type *tb = e1->type->toBasetype(); 6632 6649 if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) 6633 6650 return 1; // function returns a reference 6634 6651 return 0; 6635 6652 } 6636 6653 #endif 6637 6654 6638 6655 Expression *CallExp::toLvalue(Scope *sc, Expression *e) 6639 6656 { 6640 6657 if (isLvalue()) 6641 6658 return this; 6642 6659 return Expression::toLvalue(sc, e); 6643 6660 } 6644 6661 6645 6662 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 6646 6663 { int i; 6647 6664 6648 6665 expToCBuffer(buf, hgs, e1, precedence[op]); 6649 6666 buf->writeByte('('); 6650 6667 argsToCBuffer(buf, arguments, hgs); … … 7419 7436 } 7420 7437 else 7421 7438 { Arguments *args = new Arguments; 7422 7439 args->reserve(j2 - j1); 7423 7440 for (size_t i = j1; i < j2; i++) 7424 7441 { Argument *arg = Argument::getNth(tup->arguments, i); 7425 7442 args->push(arg); 7426 7443 } 7427 7444 e = new TypeExp(e1->loc, new TypeTuple(args)); 7428 7445 } 7429 7446 e = e->semantic(sc); 7430 7447 } 7431 7448 else 7432 7449 { 7433 7450 error("string slice [%ju .. %ju] is out of bounds", i1, i2); 7434 7451 e = e1; 7435 7452 } 7436 7453 return e; 7437 7454 } 7438 7455 7439 type = t->nextOf()->arrayOf(); 7456 if (t->ty == Tarray) 7457 { 7458 type = e1->type; 7459 } 7460 else 7461 type = t->nextOf()->arrayOf(); 7440 7462 return e; 7441 7463 7442 7464 Lerror: 7443 7465 char *s; 7444 7466 if (t->ty == Tvoid) 7445 7467 s = e1->toChars(); 7446 7468 else 7447 7469 s = t->toChars(); 7448 7470 error("%s cannot be sliced with []", s); 7449 7471 e = new IntegerExp(0); 7450 7472 return e; 7451 7473 } 7452 7474 7453 7475 void SliceExp::checkEscape() 7454 7476 { 7455 7477 e1->checkEscape(); 7456 7478 } 7457 7479 7458 7480 #if V2 7459 7481 int SliceExp::isLvalue() … … 7756 7778 TypeSArray *tsa = (TypeSArray *)t1; 7757 7779 7758 7780 #if 0 // Don't do now, because it might be short-circuit evaluated 7759 7781 // Do compile time array bounds checking if possible 7760 7782 e2 = e2->optimize(WANTvalue); 7761 7783 if (e2->op == TOKint64) 7762 7784 { 7763 7785 integer_t index = e2->toInteger(); 7764 7786 integer_t length = tsa->dim->toInteger(); 7765 7787 if (index < 0 || index >= length) 7766 7788 error("array index [%lld] is outside array bounds [0 .. %lld]", 7767 7789 index, length); 7768 7790 } 7769 7791 #endif 7770 7792 e->type = t1->nextOf(); 7771 7793 break; 7772 7794 } 7773 7795 7774 7796 case Taarray: 7775 7797 { TypeAArray *taa = (TypeAArray *)t1; 7776 7777 e2 = e2->implicitCastTo(sc, taa->index); // type checking 7798 if (!arrayTypeCompatible(e2->loc, e2->type, taa->index)) 7799 { 7800 e2 = e2->implicitCastTo(sc, taa->index); // type checking 7801 } 7778 7802 type = taa->next; 7779 7803 break; 7780 7804 } 7781 7805 7782 7806 case Ttuple: 7783 7807 { 7784 7808 e2 = e2->implicitCastTo(sc, Type::tsize_t); 7785 7809 e2 = e2->optimize(WANTvalue | WANTinterpret); 7786 7810 uinteger_t index = e2->toUInteger(); 7787 7811 size_t length; 7788 7812 TupleExp *te; 7789 7813 TypeTuple *tup; 7790 7814 7791 7815 if (e1->op == TOKtuple) 7792 7816 { te = (TupleExp *)e1; 7793 7817 length = te->exps->dim; 7794 7818 } 7795 7819 else if (e1->op == TOKtype) 7796 7820 { 7797 7821 tup = (TypeTuple *)t1; … … 9448 9472 9449 9473 if (type) 9450 9474 return this; 9451 9475 9452 9476 BinExp::semanticp(sc); 9453 9477 e = op_overload(sc); 9454 9478 if (e) 9455 9479 return e; 9456 9480 9457 9481 //type = Type::tboolean; 9458 9482 Type *t2b = e2->type->toBasetype(); 9459 9483 if (t2b->ty != Taarray) 9460 9484 { 9461 9485 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); 9462 9486 type = Type::terror; 9463 9487 } 9464 9488 else 9465 9489 { 9466 9490 TypeAArray *ta = (TypeAArray *)t2b; 9467 9491 9468 // Convert key to type of key 9469 e1 = e1->implicitCastTo(sc, ta->index); 9492 // Special handling for array keys 9493 if (!arrayTypeCompatible(e1->loc, e1->type, ta->index)) 9494 { 9495 // Convert key to type of key 9496 e1 = e1->implicitCastTo(sc, ta->index); 9497 } 9470 9498 9471 9499 // Return type is pointer to value 9472 9500 type = ta->nextOf()->pointerTo(); 9473 9501 } 9474 9502 return this; 9475 9503 } 9476 9504 9477 9505 int InExp::isBit() 9478 9506 { 9479 9507 return FALSE; 9480 9508 } 9481 9509 9482 9510 9483 9511 /************************************************************/ 9484 9512 9485 9513 /* This deletes the key e1 from the associative array e2 9486 9514 */ 9487 9515 9488 9516 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) 9489 9517 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) … … 9617 9645 } 9618 9646 9619 9647 //if (e2->op != TOKnull) 9620 9648 { 9621 9649 e = op_overload(sc); 9622 9650 if (e) 9623 9651 { 9624 9652 if (op == TOKnotequal) 9625 9653 { 9626 9654 e = new NotExp(e->loc, e); 9627 9655 e = e->semantic(sc); 9628 9656 } 9629 9657 return e; 9630 9658 } 9631 9659 } 9632 9660 9633 9661 e = typeCombine(sc); 9634 9662 type = Type::tboolean; 9635 9663 9636 9664 // Special handling for array comparisons 9637 t1 = e1->type->toBasetype(); 9638 t2 = e2->type->toBasetype(); 9639 9640 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) && 9641 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer)) 9642 { 9643 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst && 9644 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst && 9645 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid)) 9646 error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars()); 9647 } 9648 else 9665 if (!arrayTypeCompatible(loc, e1->type, e2->type)) 9649 9666 { 9650 9667 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) 9651 9668 { 9652 9669 // Cast both to complex 9653 9670 e1 = e1->castTo(sc, Type::tcomplex80); 9654 9671 e2 = e2->castTo(sc, Type::tcomplex80); 9655 9672 } 9656 9673 } 9657 9674 return e; 9658 9675 } 9659 9676 9660 9677 int EqualExp::isBit() 9661 9678 { 9662 9679 return TRUE; 9663 9680 } 9664 9681 9665 9682 9666 9683 9667 9684 /************************************************************/ 9668 9685 trunk/src/expression.h
r181 r183 72 72 int arrayExpressionCanThrow(Expressions *exps); 73 73 74 74 struct Expression : Object 75 75 { 76 76 Loc loc; // file location 77 77 enum TOK op; // handy to minimize use of dynamic_cast 78 78 Type *type; // !=NULL means that semantic() has been run 79 79 int size; // # of bytes in Expression so we can copy() it 80 80 81 81 Expression(Loc loc, enum TOK op, int size); 82 82 Expression *copy(); 83 83 virtual Expression *syntaxCopy(); 84 84 virtual Expression *semantic(Scope *sc); 85 85 86 86 int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression() 87 87 88 88 void print(); 89 89 char *toChars(); 90 90 virtual void dump(int indent); 91 91 void error(const char *format, ...); 92 void warning(const char *format, ...); 92 93 virtual void rvalue(); 93 94 94 95 static Expression *combine(Expression *e1, Expression *e2); 95 96 static Expressions *arraySyntaxCopy(Expressions *exps); 96 97 97 98 virtual integer_t toInteger(); 98 99 virtual uinteger_t toUInteger(); 99 100 virtual real_t toReal(); 100 101 virtual real_t toImaginary(); 101 102 virtual complex_t toComplex(); 102 103 virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 103 104 virtual void toMangleBuffer(OutBuffer *buf); 104 105 virtual int isLvalue(); 105 106 virtual Expression *toLvalue(Scope *sc, Expression *e); 106 107 virtual Expression *modifiableLvalue(Scope *sc, Expression *e); 107 108 virtual Expression *implicitCastTo(Scope *sc, Type *t); 108 109 virtual MATCH implicitConvTo(Type *t); 109 110 virtual Expression *castTo(Scope *sc, Type *t); 110 111 virtual void checkEscape(); 111 112 void checkScalar(); trunk/src/func.c
r182 r183 356 356 // Append to end of vtbl[] 357 357 //printf("\tintroducing function\n"); 358 358 introducing = 1; 359 359 vi = cd->vtbl.dim; 360 360 cd->vtbl.push(this); 361 361 vtblIndex = vi; 362 362 } 363 363 break; 364 364 365 365 case -2: // can't determine because of fwd refs 366 366 cd->sizeok = 2; // can't finish due to forward reference 367 367 return; 368 368 369 369 default: 370 370 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; 371 371 // This function is covariant with fdv 372 372 if (fdv->isFinal()) 373 373 error("cannot override final function %s", fdv->toPrettyChars()); 374 374 375 375 #if V2 376 if (!isOverride() && global.params.warnings)377 error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());376 if (!isOverride()) 377 warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); 378 378 #endif 379 379 380 380 if (fdv->toParent() == parent) 381 381 { 382 382 // If both are mixins, then error. 383 383 // If either is not, the one that is not overrides 384 384 // the other. 385 385 if (fdv->parent->isClassDeclaration()) 386 386 break; 387 387 if (!this->parent->isClassDeclaration() 388 388 #if !BREAKABI 389 389 && !isDtorDeclaration() 390 390 #endif 391 391 #if V2 392 392 && !isPostBlitDeclaration() 393 393 #endif 394 394 ) 395 395 error("multiple overrides of same function"); 396 396 } 397 397 cd->vtbl.data[vi] = (void *)this; … … 1091 1091 { 1092 1092 int blockexit = fbody ? fbody->blockExit() : 0; 1093 1093 if (f->isnothrow && blockexit & BEthrow) 1094 1094 error("'%s' is nothrow yet may throw", toChars()); 1095 1095 1096 1096 int offend = blockexit & BEfallthru; 1097 1097 1098 1098 if (type->nextOf()->ty == Tvoid) 1099 1099 { 1100 1100 if (offend && isMain()) 1101 1101 { // Add a return 0; statement 1102 1102 Statement *s = new ReturnStatement(0, new IntegerExp(0)); 1103 1103 fbody = new CompoundStatement(0, fbody, s); 1104 1104 } 1105 1105 } 1106 1106 else 1107 1107 { 1108 1108 if (offend) 1109 1109 { Expression *e; 1110 1110 1111 if (global.params.warnings) 1112 { fprintf(stdmsg, "warning - "); 1113 error("no return at end of function"); 1114 } 1111 warning(loc, "no return at end of function"); 1115 1112 1116 1113 if (global.params.useAssert && 1117 1114 !global.params.useInline) 1118 1115 { /* Add an assert(0, msg); where the missing return 1119 1116 * should be. 1120 1117 */ 1121 1118 e = new AssertExp( 1122 1119 endloc, 1123 1120 new IntegerExp(0), 1124 1121 new StringExp(loc, (char *)"missing return expression") 1125 1122 ); 1126 1123 } 1127 1124 else 1128 1125 e = new HaltExp(endloc); 1129 1126 e = new CommaExp(0, e, type->nextOf()->defaultInit()); 1130 1127 e = e->semantic(sc2); 1131 1128 Statement *s = new ExpStatement(0, e); 1132 1129 fbody = new CompoundStatement(0, fbody, s); 1133 1130 } 1134 1131 } … … 1924 1921 { int level; 1925 1922 Dsymbol *s; 1926 1923 Dsymbol *fdparent; 1927 1924 1928 1925 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars()); 1929 1926 fdparent = fd->toParent2(); 1930 1927 if (fdparent == this) 1931 1928 return -1; 1932 1929 s = this; 1933 1930 level = 0; 1934 1931 while (fd != s && fdparent != s->toParent2()) 1935 1932 { 1936 1933 //printf("\ts = '%s'\n", s->toChars()); 1937 1934 FuncDeclaration *thisfd = s->isFuncDeclaration(); 1938 1935 if (thisfd) 1939 1936 { if (!thisfd->isNested() && !thisfd->vthis) 1940 1937 goto Lerr; 1941 1938 } 1942 1939 else 1943 1940 { 1944 ClassDeclaration *thiscd = s->isClassDeclaration();1941 AggregateDeclaration *thiscd = s->isAggregateDeclaration(); 1945 1942 if (thiscd) 1946 1943 { if (!thiscd->isNested()) 1947 1944 goto Lerr; 1948 1945 } 1949 1946 else 1950 1947 goto Lerr; 1951 1948 } 1952 1949 1953 1950 s = s->toParent2(); 1954 1951 assert(s); 1955 1952 level++; 1956 1953 } 1957 1954 return level; 1958 1955 1959 1956 Lerr: 1960 1957 error(loc, "cannot access frame of function %s", fd->toChars()); 1961 1958 return 1; 1962 1959 } 1963 1960 1964 1961 void FuncDeclaration::appendExp(Expression *e) trunk/src/hdrgen.c
r182 r183 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 // Routines to emit header files 12 12 13 13 #ifdef _DH 14 14 15 15 #define PRETTY_PRINT 16 16 #define TEST_EMIT_ALL 0 // For Testing 17 17 18 18 #define LOG 0 19 19 20 20 #include <stdio.h> 21 21 #include <stdlib.h> 22 22 #include <assert.h> 23 23 #if __DMC__ 24 24 #include <complex.h> 25 25 #endif 26 26 27 #ifdef IN_GCC 28 #include "mem.h" 29 #else 30 #if _WIN32 31 #include "..\root\mem.h" 32 #elif linux || __APPLE__ 33 #include "../root/mem.h" 34 #else 35 #error "fix this" 36 #endif 37 #endif 27 #include "rmem.h" 38 28 39 29 #include "id.h" 40 30 #include "init.h" 41 31 42 32 #include "attrib.h" 43 33 #include "cond.h" 44 34 #include "enum.h" 45 35 #include "import.h" 46 36 #include "module.h" 47 37 #include "mtype.h" 48 38 #include "scope.h" 49 39 #include "staticassert.h" 50 40 #include "template.h" 51 41 #include "utf.h" 52 42 #include "version.h" 53 43 54 44 #include "declaration.h" 55 45 #include "aggregate.h" 56 46 #include "expression.h" 57 47 #include "statement.h" trunk/src/inifile.c
r182 r183 1 2 // Copyright (c) 1999-2009 by Digital Mars 3 // All Rights Reserved 4 // written by Walter Bright 5 // http://www.digitalmars.com 6 1 /* 2 * Some portions copyright (c) 1994-1995 by Symantec 3 * Copyright (c) 1999-2009 by Digital Mars 4 * All Rights Reserved 5 * http://www.digitalmars.com 6 * Written by Walter Bright 7 * 8 * This source file is made available for personal use 9 * only. The license is in /dmd/src/dmd/backendlicense.txt 10 * For any other uses, please contact Digital Mars. 11 */ 7 12 8 13 #include <stdio.h> 9 14 #include <string.h> 10 15 #include <stdlib.h> 11 16 #include <ctype.h> 12 17 13 18 #if __APPLE__ 14 19 #include <sys/syslimits.h> 15 20 #endif 16 21 17 22 #include "root.h" 18 #include " mem.h"23 #include "rmem.h" 19 24 20 25 #define LOG 0 21 26 22 27 char *skipspace(const char *p); 23 28 24 29 #if __GNUC__ 25 30 char *strupr(char *s) 26 31 { 27 32 char *t = s; 28 33 29 34 while (*s) 30 35 { 31 36 *s = toupper(*s); 32 37 s++; 33 38 } 34 39 35 40 return t; 36 41 } 37 42 #endif /* unix */ 38 43 trunk/src/interpret.c
r180 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 15 #include " mem.h"15 #include "rmem.h" 16 16 17 17 #include "statement.h" 18 18 #include "expression.h" 19 19 #include "cond.h" 20 20 #include "init.h" 21 21 #include "staticassert.h" 22 22 #include "mtype.h" 23 23 #include "scope.h" 24 24 #include "declaration.h" 25 25 #include "aggregate.h" 26 26 #include "id.h" 27 27 28 28 #define LOG 0 29 29 30 30 struct InterState 31 31 { 32 32 InterState *caller; // calling function's InterState 33 33 FuncDeclaration *fd; // function being interpreted 34 34 Dsymbols vars; // variables used in this function 35 35 Statement *start; // if !=NULL, start execution at this statement trunk/src/lexer.c
r182 r183 9 8 // See the included readme.txt for details. 10 9 11 10 /* Lexical Analyzer */ 12 11 13 12 #include <stdio.h> 14 13 #include <string.h> 15 14 #include <ctype.h> 16 15 #include <stdarg.h> 17 16 #include <errno.h> 18 17 #include <wchar.h> 19 18 #include <stdlib.h> 20 19 #include <assert.h> 21 20 #if _MSC_VER 22 21 #include <time.h> 23 22 #else 24 23 #include <sys/time.h> 25 24 #endif 26 25 #ifdef IN_GCC 27 26 28 27 #include <time.h> 29 #include "mem.h"30 31 28 #else 32 29 33 30 #if __GNUC__ 34 31 #include <time.h> 35 32 #endif 36 37 #if _WIN32 38 #include "..\root\mem.h" 39 #else 40 #include "../root/mem.h" 41 #endif 42 #endif 32 #endif 33 34 #include "rmem.h" 43 35 44 36 #include "stringtable.h" 45 37 46 38 #include "lexer.h" 47 39 #include "utf.h" 48 40 #include "identifier.h" 49 41 #include "id.h" 50 42 #include "module.h" 51 43 52 44 #if _WIN32 && __DMC__ 53 45 // from \dm\src\include\setlocal.h 54 46 extern "C" char * __cdecl __locale_decpoint; 55 47 #endif 56 48 57 49 #if _MSC_VER // workaround VC++ bug, labels and types should be in separate namespaces 58 50 #define Lstring Lstr 59 51 #endif 60 52 61 53 extern int HtmlNamedEntity(unsigned char *p, int length); 62 54 … … 599 591 p++; 600 592 t->value = delimitedStringConstant(t); 601 593 return; 602 594 } 603 595 else if (p[1] == '{') 604 596 { 605 597 p++; 606 598 t->value = tokenStringConstant(t); 607 599 return; 608 600 } 609 601 else 610 602 goto case_ident; 611 603 #endif 612 604 613 605 case '"': 614 606 t->value = escapeStringConstant(t,0); 615 607 return; 616 608 #if ! TEXTUAL_ASSEMBLY_OUT 617 609 case '\\': // escaped string literal 618 610 { unsigned c; 611 unsigned char *pstart = p; 619 612 620 613 stringbuffer.reset(); 621 614 do 622 615 { 623 616 p++; 624 617 switch (*p) 625 618 { 626 619 case 'u': 627 620 case 'U': 628 621 case '&': 629 622 c = escapeSequence(); 630 623 stringbuffer.writeUTF8(c); 631 624 break; 632 625 633 626 default: 634 627 c = escapeSequence(); 635 628 stringbuffer.writeByte(c); 636 629 break; 637 630 } 638 631 } while (*p == '\\'); 639 632 t->len = stringbuffer.offset; 640 633 stringbuffer.writeByte(0); 641 634 t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset); 642 635 memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); 643 636 t->postfix = 0; 644 637 t->value = TOKstring; 638 if (!global.params.useDeprecated) 639 error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart); 645 640 return; 646 641 } 647 642 #endif 648 643 case 'l': 649 644 case 'L': 650 645 #endif 651 646 case 'a': case 'b': case 'c': case 'd': case 'e': 652 647 case 'f': case 'g': case 'h': case 'i': case 'j': 653 648 case 'k': case 'm': case 'n': case 'o': 654 649 #if V2 655 650 case 'p': /*case 'q': case 'r':*/ case 's': case 't': 656 651 #else 657 652 case 'p': case 'q': /*case 'r':*/ case 's': case 't': 658 653 #endif 659 654 case 'u': case 'v': case 'w': /*case 'x':*/ case 'y': 660 655 case 'z': 661 656 case 'A': case 'B': case 'C': case 'D': case 'E': 662 657 case 'F': case 'G': case 'H': case 'I': case 'J': 663 658 case 'K': case 'M': case 'N': case 'O': 664 659 case 'P': case 'Q': case 'R': case 'S': case 'T': trunk/src/libelf.c
r181 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 #include <time.h> 15 15 #include <unistd.h> 16 16 #include <sys/types.h> 17 17 #include <sys/stat.h> 18 18 19 #include " mem.h"19 #include "rmem.h" 20 20 #include "root.h" 21 21 #include "stringtable.h" 22 22 23 23 #include "mars.h" 24 24 #include "lib.h" 25 25 #include "melf.h" 26 26 27 27 #define LOG 0 28 28 29 29 Library::Library() 30 30 { 31 31 libfile = NULL; 32 32 } 33 33 34 34 /*********************************** 35 35 * Set the library file name based on the output directory 36 36 * and the filename. 37 37 * Add default library file name extension. 38 38 */ 39 39 trunk/src/libmach.c
r182 r183 12 12 * module format. While the format is 13 13 * equivalent to the Linux arch format, it differs in many details. 14 14 * This format is described in the Apple document 15 15 * "Mac OS X ABI Mach-O File Format Reference" dated 2007-04-26 16 16 * in the section "Static Archive Libraries". 17 17 * That specification is only about half complete and has numerous 18 18 * errors, so use the source code here as a better guide. 19 19 */ 20 20 21 21 #include <stdio.h> 22 22 #include <stdlib.h> 23 23 #include <assert.h> 24 24 #include <time.h> 25 25 #include <unistd.h> 26 26 #include <sys/types.h> 27 27 #include <sys/stat.h> 28 28 29 29 #undef integer_t 30 30 #include "mach.h" 31 31 32 #include " mem.h"32 #include "rmem.h" 33 33 #include "root.h" 34 34 #include "stringtable.h" 35 35 36 36 #include "mars.h" 37 37 #include "lib.h" 38 38 39 39 #define LOG 0 40 40 41 41 Library::Library() 42 42 { 43 43 libfile = NULL; 44 44 } 45 45 46 46 /*********************************** 47 47 * Set the library file name based on the output directory 48 48 * and the filename. 49 49 * Add default library file name extension. 50 50 */ 51 51 52 52 void Library::setFilename(char *dir, char *filename) trunk/src/link.c
r182 r183 12 12 #include <ctype.h> 13 13 #include <assert.h> 14 14 #include <stdarg.h> 15 15 #include <string.h> 16 16 #include <stdlib.h> 17 17 18 18 #if _WIN32 19 19 #include <process.h> 20 20 #endif 21 21 22 22 #if linux || __APPLE__ 23 23 #include <sys/types.h> 24 24 #include <sys/wait.h> 25 25 #include <unistd.h> 26 26 #endif 27 27 28 28 #include "root.h" 29 29 30 30 #include "mars.h" 31 31 32 #include " mem.h"32 #include "rmem.h" 33 33 34 34 int executecmd(char *cmd, char *args, int useenv); 35 35 int executearg0(char *cmd, char *args); 36 36 37 37 /**************************************** 38 38 * Write filename to cmdbuf, quoting if necessary. 39 39 */ 40 40 41 41 void writeFilename(OutBuffer *buf, char *filename, size_t len) 42 42 { 43 43 /* Loop and see if we need to quote 44 44 */ 45 45 for (size_t i = 0; i < len; i++) 46 46 { char c = filename[i]; 47 47 48 48 if (isalnum(c) || c == '_') 49 49 continue; 50 50 51 51 /* Need to quote 52 52 */ trunk/src/macro.c
r182 r183 1 1 2 2 // Copyright (c) 1999-2006 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 /* Simple macro text processor. 11 11 */ 12 12 13 13 #include <stdio.h> 14 14 #include <string.h> 15 15 #include <time.h> 16 16 #include <ctype.h> 17 17 #include <assert.h> 18 18 19 #ifdef IN_GCC 20 #include "mem.h" 21 #else 22 #if _WIN32 23 #include "..\root\mem.h" 24 #elif linux || __APPLE__ 25 #include "../root/mem.h" 26 #else 27 #error "fix this" 28 #endif 29 #endif 30 19 #include "rmem.h" 31 20 #include "root.h" 32 21 #include "macro.h" 33 22 34 23 #define isidstart(c) (isalpha(c) || (c) == '_') 35 24 #define isidchar(c) (isalnum(c) || (c) == '_') 36 25 37 26 unsigned char *memdup(unsigned char *p, size_t len) 38 27 { 39 28 return (unsigned char *)memcpy(mem.malloc(len), p, len); 40 29 } 41 30 42 31 Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen) 43 32 { 44 33 next = NULL; 45 34 46 35 #if 1 47 36 this->name = name; 48 37 this->namelen = namelen; 49 38 50 39 this->text = text; trunk/src/mars.c
r182 r183 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <ctype.h> 14 14 #include <assert.h> 15 15 #include <limits.h> 16 16 17 17 #if __DMC__ 18 18 #include <dos.h> 19 19 #endif 20 20 21 21 #if linux || __APPLE__ 22 22 #include <errno.h> 23 23 #endif 24 24 25 #include " mem.h"25 #include "rmem.h" 26 26 #include "root.h" 27 27 28 28 #include "mars.h" 29 29 #include "module.h" 30 30 #include "mtype.h" 31 31 #include "id.h" 32 32 #include "cond.h" 33 33 #include "expression.h" 34 34 #include "lexer.h" 35 35 #include "lib.h" 36 36 37 37 #if WINDOWS_SEH 38 38 #include <windows.h> 39 39 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); 40 40 #endif 41 41 42 42 43 43 void browse(const char *url); 44 44 void getenv_setargv(const char *envvar, int *pargc, char** *pargv); 45 45 … … 57 57 ddoc_ext = "ddoc"; 58 58 59 59 #if TARGET_WINDOS 60 60 obj_ext = "obj"; 61 61 #elif TARGET_LINUX || TARGET_OSX 62 62 obj_ext = "o"; 63 63 #else 64 64 #error "fix this" 65 65 #endif 66 66 67 67 #if TARGET_WINDOS 68 68 lib_ext = "lib"; 69 69 #elif TARGET_LINUX || TARGET_OSX 70 70 lib_ext = "a"; 71 71 #else 72 72 #error "fix this" 73 73 #endif 74 74 75 75 copyright = "Copyright (c) 1999-2009 by Digital Mars"; 76 76 written = "written by Walter Bright"; 77 version = "v2.02 5";77 version = "v2.026"; 78 78 global.structalign = 8; 79 79 80 80 memset(¶ms, 0, sizeof(Param)); 81 81 } 82 82 83 83 char *Loc::toChars() 84 84 { 85 85 OutBuffer buf; 86 86 char *p; 87 87 88 88 if (filename) 89 89 { 90 90 buf.printf("%s", filename); 91 91 } 92 92 93 93 if (linnum) 94 94 buf.printf("(%d)", linnum); 95 95 buf.writeByte(0); 96 96 return (char *)buf.extractData(); 97 97 } 98 98 99 99 Loc::Loc(Module *mod, unsigned linnum) 100 100 { 101 101 this->linnum = linnum; 102 102 this->filename = mod ? mod->srcfile->toChars() : NULL; 103 103 } 104 104 105 105 /************************************** 106 106 * Print error message and exit. 107 107 */ 108 108 109 109 void error(Loc loc, const char *format, ...) 110 110 { 111 111 va_list ap; 112 112 va_start(ap, format); 113 113 verror(loc, format, ap); 114 114 va_end( ap ); 115 } 116 117 void warning(Loc loc, const char *format, ...) 118 { 119 if (global.params.warnings && !global.gag) 120 { 121 fprintf(stdmsg, "warning - "); 122 va_list ap; 123 va_start(ap, format); 124 verror(loc, format, ap); 125 va_end( ap ); 126 } 115 127 } 116 128 117 129 void verror(Loc loc, const char *format, va_list ap) 118 130 { 119 131 if (!global.gag) 120 132 { 121 133 char *p = loc.toChars(); 122 134 123 135 if (*p) 124 136 fprintf(stdmsg, "%s: ", p); 125 137 mem.free(p); 126 138 127 139 fprintf(stdmsg, "Error: "); 128 140 #if _MSC_VER 129 141 // MS doesn't recognize %zu format 130 142 OutBuffer tmp; 131 143 tmp.vprintf(format, ap); 132 144 fprintf(stdmsg, "%s", tmp.toChars()); 133 145 #else 134 146 vfprintf(stdmsg, format, ap); … … 218 230 -version=ident compile in version code identified by ident\n\ 219 231 -w enable warnings\n\ 220 232 ", 221 233 #if WIN32 222 234 " @cmdfile read arguments from cmdfile\n" 223 235 #else 224 236 "" 225 237 #endif 226 238 ); 227 239 } 228 240 229 241 int main(int argc, char *argv[]) 230 242 { 231 243 int i; 232 244 Array files; 233 245 Array libmodules; 234 246 char *p; 235 247 Module *m; 236 248 int status = EXIT_SUCCESS; 237 249 int argcstart = argc; 250 int setdebuglib = 0; 238 251 239 252 // Check for malformed input 240 253 if (argc < 1 || !argv) 241 254 { 242 255 Largs: 243 256 error("missing or null command line arguments"); 244 257 fatal(); 245 258 } 246 259 for (i = 0; i < argc; i++) 247 260 { 248 261 if (!argv[i]) 249 262 goto Largs; 250 263 } 251 264 252 265 #if __DMC__ // DMC unique support for response files 253 266 if (response_expand(&argc,&argv)) // expand response files 254 267 error("can't open response file"); 255 268 #endif 256 269 257 270 files.reserve(argc - 1); … … 263 276 global.params.useInvariants = 1; 264 277 global.params.useIn = 1; 265 278 global.params.useOut = 1; 266 279 global.params.useArrayBounds = 1; 267 280 global.params.useSwitchError = 1; 268 281 global.params.useInline = 0; 269 282 global.params.obj = 1; 270 283 global.params.Dversion = 2; 271 284 global.params.quiet = 1; 272 285 273 286 global.params.linkswitches = new Array(); 274 287 global.params.libfiles = new Array(); 275 288 global.params.objfiles = new Array(); 276 289 global.params.ddocfiles = new Array(); 277 290 278 291 #if TARGET_WINDOS 279 292 global.params.defaultlibname = "phobos"; 280 293 #elif TARGET_LINUX || TARGET_OSX 281 294 global.params.defaultlibname = "phobos2"; 282 295 #endif 283 global.params.debuglibname = global.params.defaultlibname;284 296 285 297 // Predefine version identifiers 286 298 VersionCondition::addPredefinedGlobalIdent("DigitalMars"); 287 299 #if TARGET_WINDOS 288 300 VersionCondition::addPredefinedGlobalIdent("Windows"); 289 301 global.params.isWindows = 1; 290 302 #endif 291 303 #if TARGET_LINUX 292 304 VersionCondition::addPredefinedGlobalIdent("Posix"); 293 305 VersionCondition::addPredefinedGlobalIdent("linux"); 294 306 global.params.isLinux = 1; 295 307 #endif 296 308 #if TARGET_OSX 297 309 VersionCondition::addPredefinedGlobalIdent("Posix"); 298 310 VersionCondition::addPredefinedGlobalIdent("OSX"); 299 311 global.params.isOSX = 1; 300 312 301 313 // For legacy compatibility 302 314 VersionCondition::addPredefinedGlobalIdent("darwin"); 303 315 #endif … … 538 550 else if (strcmp(p + 1, "-help") == 0) 539 551 { usage(); 540 552 exit(EXIT_SUCCESS); 541 553 } 542 554 else if (strcmp(p + 1, "-r") == 0) 543 555 global.params.debugr = 1; 544 556 else if (strcmp(p + 1, "-x") == 0) 545 557 global.params.debugx = 1; 546 558 else if (strcmp(p + 1, "-y") == 0) 547 559 global.params.debugy = 1; 548 560 else if (p[1] == 'L') 549 561 { 550 562 global.params.linkswitches->push(p + 2); 551 563 } 552 564 else if (memcmp(p + 1, "defaultlib=", 11) == 0) 553 565 { 554 566 global.params.defaultlibname = p + 1 + 11; 555 567 } 556 568 else if (memcmp(p + 1, "debuglib=", 9) == 0) 557 569 { 570 setdebuglib = 1; 558 571 global.params.debuglibname = p + 1 + 9; 559 572 } 560 573 else if (memcmp(p + 1, "man", 3) == 0) 561 574 { 562 575 #if _WIN32 563 576 #if V1 564 577 browse("http://www.digitalmars.com/d/1.0/dmd-windows.html"); 565 578 #else 566 579 browse("http://www.digitalmars.com/d/2.0/dmd-windows.html"); 567 580 #endif 568 581 #endif 569 582 #if linux 570 583 #if V1 571 584 browse("http://www.digitalmars.com/d/1.0/dmd-linux.html"); 572 585 #else 573 586 browse("http://www.digitalmars.com/d/2.0/dmd-linux.html"); 574 587 #endif 575 588 #endif 576 589 #if __APPLE__ 577 590 #if V1 … … 613 626 #if !TARGET_LINUX && !TARGET_OSX 614 627 char *ext = FileName::ext(p); 615 628 if (ext && stricmp(ext, "exe") == 0) 616 629 { 617 630 global.params.objname = p; 618 631 continue; 619 632 } 620 633 #endif 621 634 files.push(p); 622 635 } 623 636 } 624 637 if (global.errors) 625 638 { 626 639 fatal(); 627 640 } 628 641 if (files.dim == 0) 629 642 { usage(); 630 643 return EXIT_FAILURE; 631 644 } 632 645 646 if (!setdebuglib) 647 global.params.debuglibname = global.params.defaultlibname; 648 633 649 #if TARGET_OSX 634 650 global.params.pic = 1; 635 651 #endif 636 652 637 653 if (global.params.release) 638 654 { global.params.useInvariants = 0; 639 655 global.params.useIn = 0; 640 656 global.params.useOut = 0; 641 657 global.params.useAssert = 0; 642 658 global.params.useArrayBounds = 0; 643 659 global.params.useSwitchError = 0; 644 660 } 645 661 646 662 if (global.params.run) 647 663 global.params.quiet = 1; 648 664 649 665 if (global.params.useUnitTests) 650 666 global.params.useAssert = 1; 651 667 652 668 if (!global.params.obj || global.params.lib) trunk/src/mars.h
r182 r183 329 329 enum DYNCAST 330 330 { 331 331 DYNCAST_OBJECT, 332 332 DYNCAST_EXPRESSION, 333 333 DYNCAST_DSYMBOL, 334 334 DYNCAST_TYPE, 335 335 DYNCAST_IDENTIFIER, 336 336 DYNCAST_TUPLE, 337 337 }; 338 338 339 339 enum MATCH 340 340 { 341 341 MATCHnomatch, // no match 342 342 MATCHconvert, // match with conversions 343 343 #if V2 344 344 MATCHconst, // match with conversion to const 345 345 #endif 346 346 MATCHexact // exact match 347 347 }; 348 348 349 void warning(Loc loc, const char *format, ...); 349 350 void error(Loc loc, const char *format, ...); 350 351 void verror(Loc loc, const char *format, va_list); 351 352 void fatal(); 352 353 void err_nomem(); 353 354 int runLINK(); 354 355 void deleteExeFile(); 355 356 int runProgram(); 356 357 void inifile(const char *argv0, const char *inifile); 357 358 void halt(); 358 359 void util_progress(); 359 360 360 361 /*** Where to send error messages ***/ 361 362 #if IN_GCC 362 363 #define stdmsg stderr 363 364 #else 364 365 #define stdmsg stdout 365 366 #endif 366 367 367 368 struct Dsymbol; 368 369 struct Library; trunk/src/module.c
r180 r183 3 3 // Copyright (c) 1999-2007 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 15 15 #ifdef _MSC_VER 16 16 #include <malloc.h> 17 17 #endif 18 18 19 19 #if IN_GCC 20 20 #include "gdc_alloca.h" 21 21 #endif 22 22 23 #include " mem.h"23 #include "rmem.h" 24 24 25 25 #include "mars.h" 26 26 #include "module.h" 27 27 #include "parse.h" 28 28 #include "scope.h" 29 29 #include "identifier.h" 30 30 #include "id.h" 31 31 #include "import.h" 32 32 #include "dsymbol.h" 33 33 #include "hdrgen.h" 34 34 #include "lexer.h" 35 35 36 36 #define MARS 1 37 37 #include "html.h" 38 38 39 39 #ifdef IN_GCC 40 40 #include "d-dmd-gcc.h" 41 41 #endif 42 42 43 43 ClassDeclaration *Module::moduleinfo; … … 58 58 : Package(ident) 59 59 { 60 60 FileName *srcfilename; 61 61 FileName *cfilename; 62 62 FileName *hfilename; 63 63 FileName *objfilename; 64 64 FileName *symfilename; 65 65 66 66 // printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars()); 67 67 this->arg = filename; 68 68 md = NULL; 69 69 errors = 0; 70 70 numlines = 0; 71 71 members = NULL; 72 72 isHtml = 0; 73 73 isDocFile = 0; 74 74 needmoduleinfo = 0; 75 75 #ifdef IN_GCC 76 76 strictlyneedmoduleinfo = 0; 77 77 #endif 78 selfimports = 0; 78 79 insearch = 0; 79 80 searchCacheIdent = NULL; 80 81 searchCacheSymbol = NULL; 81 82 searchCacheFlags = 0; 82 83 semanticstarted = 0; 83 84 semanticdone = 0; 84 85 decldefs = NULL; 85 86 vmoduleinfo = NULL; 86 87 massert = NULL; 87 88 marray = NULL; 88 89 sictor = NULL; 89 90 sctor = NULL; 90 91 sdtor = NULL; 91 92 stest = NULL; 92 93 sfilename = NULL; 93 94 root = 0; 94 95 importedFrom = NULL; 95 96 srcfile = NULL; 96 97 docfile = NULL; 97 98 … … 898 899 */ 899 900 900 901 int Module::imports(Module *m) 901 902 { 902 903 //printf("%s Module::imports(%s)\n", toChars(), m->toChars()); 903 904 int aimports_dim = aimports.dim; 904 905 #if 0 905 906 for (int i = 0; i < aimports.dim; i++) 906 907 { Module *mi = (Module *)aimports.data[i]; 907 908 printf("\t[%d] %s\n", i, mi->toChars()); 908 909 } 909 910 #endif 910 911 for (int i = 0; i < aimports.dim; i++) 911 912 { Module *mi = (Module *)aimports.data[i]; 912 913 if (mi == m) 913 914 return TRUE; 914 915 if (!mi->insearch) 915 916 { 916 917 mi->insearch = 1; 917 918 int r = mi->imports(m); 918 mi->insearch = 0;919 919 if (r) 920 920 return r; 921 921 } 922 922 } 923 923 return FALSE; 924 924 } 925 926 /************************************* 927 * Return !=0 if module imports itself. 928 */ 929 930 int Module::selfImports() 931 { 932 //printf("Module::selfImports() %s\n", toChars()); 933 if (!selfimports) 934 { 935 for (int i = 0; i < amodules.dim; i++) 936 { Module *mi = (Module *)amodules.data[i]; 937 //printf("\t[%d] %s\n", i, mi->toChars()); 938 mi->insearch = 0; 939 } 940 941 selfimports = imports(this) + 1; 942 943 for (int i = 0; i < amodules.dim; i++) 944 { Module *mi = (Module *)amodules.data[i]; 945 //printf("\t[%d] %s\n", i, mi->toChars()); 946 mi->insearch = 0; 947 } 948 } 949 return selfimports - 1; 950 } 951 925 952 926 953 /* =========================== ModuleDeclaration ===================== */ 927 954 928 955 ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id, bool safe) 929 956 { 930 957 this->packages = packages; 931 958 this->id = id; 932 959 this->safe = safe; 933 960 } 934 961 935 962 char *ModuleDeclaration::toChars() 936 963 { 937 964 OutBuffer buf; 938 965 int i; 939 966 940 967 if (packages && packages->dim) 941 968 { 942 969 for (i = 0; i < packages->dim; i++) 943 970 { Identifier *pid = (Identifier *)packages->data[i]; 944 971 trunk/src/module.h
r180 r183 55 55 static void init(); 56 56 57 57 static ClassDeclaration *moduleinfo; 58 58 59 59 60 60 const char *arg; // original argument name 61 61 ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration 62 62 File *srcfile; // input source file 63 63 File *objfile; // output .obj file 64 64 File *hdrfile; // 'header' file 65 65 File *symfile; // output symbol file 66 66 File *docfile; // output documentation file 67 67 unsigned errors; // if any errors in file 68 68 unsigned numlines; // number of lines in source file 69 69 int isHtml; // if it is an HTML file 70 70 int isDocFile; // if it is a documentation input file, not D source 71 71 int needmoduleinfo; 72 72 #ifdef IN_GCC 73 73 int strictlyneedmoduleinfo; 74 74 #endif 75 76 int selfimports; // 0: don't know, 1: does not, 2: does 77 int selfImports(); // returns !=0 if module imports itself 75 78 76 79 int insearch; 77 80 Identifier *searchCacheIdent; 78 81 Dsymbol *searchCacheSymbol; // cached value of search 79 82 int searchCacheFlags; // cached flags 80 83 81 84 int semanticstarted; // has semantic() been started? 82 85 int semanticdone; // has semantic() been done? 83 86 int root; // != 0 if this is a 'root' module, 84 87 // i.e. a module that will be taken all the 85 88 // way to an object file 86 89 Module *importedFrom; // module from command line we're imported from, 87 90 // i.e. a module that will be taken all the 88 91 // way to an object file 89 92 90 93 Array *decldefs; // top level declarations for this Module 91 94 92 95 Array aimports; // all imported modules 93 96 94 97 ModuleInfoDeclaration *vmoduleinfo; trunk/src/mtype.c
r182 r183 22 22 #if _MSC_VER 23 23 #include <malloc.h> 24 24 #include <complex> 25 25 #include <limits> 26 26 #elif __DMC__ 27 27 #include <complex.h> 28 28 #else 29 29 //#define signbit 56 30 30 #endif 31 31 32 32 #if __APPLE__ 33 33 #include <math.h> 34 34 static double zero = 0; 35 35 #elif __GNUC__ 36 36 #include <math.h> 37 37 #include <bits/nan.h> 38 38 #include <bits/mathdef.h> 39 39 static double zero = 0; 40 40 #endif 41 41 42 #include " mem.h"42 #include "rmem.h" 43 43 44 44 #include "dsymbol.h" 45 45 #include "mtype.h" 46 46 #include "scope.h" 47 47 #include "init.h" 48 48 #include "expression.h" 49 49 #include "attrib.h" 50 50 #include "declaration.h" 51 51 #include "template.h" 52 52 #include "id.h" 53 53 #include "enum.h" 54 54 #include "import.h" 55 55 #include "aggregate.h" 56 56 #include "hdrgen.h" 57 57 58 58 FuncDeclaration *hasThis(Scope *sc); 59 59 60 60 61 61 #define LOGDOTEXP 0 // log ::dotExp() 62 62 #define LOGDEFAULTINIT 0 // log ::defaultInit() … … 1365 1365 { char *s = e->toChars(); 1366 1366 e = new StringExp(e->loc, s, strlen(s), 'c'); 1367 1367 Scope sc; 1368 1368 e = e->semantic(&sc); 1369 1369 return e; 1370 1370 } 1371 1371 return getProperty(e->loc, ident); 1372 1372 } 1373 1373 1374 1374 unsigned Type::memalign(unsigned salign) 1375 1375 { 1376 1376 return salign; 1377 1377 } 1378 1378 1379 1379 void Type::error(Loc loc, const char *format, ...) 1380 1380 { 1381 1381 va_list ap; 1382 1382 va_start(ap, format); 1383 1383 ::verror(loc, format, ap); 1384 1384 va_end( ap ); 1385 } 1386 1387 void Type::warning(Loc loc, const char *format, ...) 1388 { 1389 if (global.params.warnings && !global.gag) 1390 { 1391 fprintf(stdmsg, "warning - "); 1392 va_list ap; 1393 va_start(ap, format); 1394 ::verror(loc, format, ap); 1395 va_end( ap ); 1396 } 1385 1397 } 1386 1398 1387 1399 Identifier *Type::getTypeInfoIdent(int internal) 1388 1400 { 1389 1401 // _init_10TypeInfo_%s 1390 1402 OutBuffer buf; 1391 1403 Identifier *id; 1392 1404 char *name; 1393 1405 int len; 1394 1406 1395 1407 if (internal) 1396 1408 { buf.writeByte(mangleChar[ty]); 1397 1409 if (ty == Tarray) 1398 1410 buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]); 1399 1411 } 1400 1412 else 1401 1413 toDecoBuffer(&buf); 1402 1414 len = buf.offset; 1403 1415 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1); 1404 1416 buf.writeByte(0); … … 2624 2636 error(loc, "index %jd overflow for static array", d1); 2625 2637 dim = new IntegerExp(0, 1, tsize_t); 2626 2638 } 2627 2639 } 2628 2640 } 2629 2641 switch (tbn->ty) 2630 2642 { 2631 2643 case Ttuple: 2632 2644 { // Index the tuple to get the type 2633 2645 assert(dim); 2634 2646 TypeTuple *tt = (TypeTuple *)tbn; 2635 2647 uinteger_t d = dim->toUInteger(); 2636 2648 2637 2649 if (d >= tt->arguments->dim) 2638 2650 { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); 2639 2651 return Type::terror; 2640 2652 } 2641 2653 Argument *arg = (Argument *)tt->arguments->data[(size_t)d]; 2642 2654 return arg->type; 2643 2655 } 2656 case Tstruct: 2657 { TypeStruct *ts = (TypeStruct *)tbn; 2658 if (ts->sym->isnested) 2659 error(loc, "cannot have array of inner structs %s", ts->toChars()); 2660 break; 2661 } 2644 2662 case Tfunction: 2645 2663 case Tnone: 2646 2664 error(loc, "can't have array of %s", tbn->toChars()); 2647 2665 tbn = next = tint32; 2648 2666 break; 2649 2667 } 2650 2668 if (tbn->isauto()) 2651 2669 error(loc, "cannot have array of auto %s", tbn->toChars()); 2652 2670 return merge(); 2653 2671 } 2654 2672 2655 2673 void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag) 2656 2674 { 2657 2675 Type::toDecoBuffer(buf, flag); 2658 2676 if (dim) 2659 2677 buf->printf("%ju", dim->toInteger()); 2660 2678 if (next) 2661 2679 /* Note that static arrays are value types, so 2662 2680 * for a parameter, propagate the 0x100 to the next 2663 2681 * level, since for T[4][3], any const should apply to the T, … … 2835 2853 unsigned TypeDArray::alignsize() 2836 2854 { 2837 2855 // A DArray consists of two ptr-sized values, so align it on pointer size 2838 2856 // boundary 2839 2857 return PTRSIZE; 2840 2858 } 2841 2859 2842 2860 Type *TypeDArray::semantic(Loc loc, Scope *sc) 2843 2861 { Type *tn = next; 2844 2862 2845 2863 tn = next->semantic(loc,sc); 2846 2864 Type *tbn = tn->toBasetype(); 2847 2865 switch (tbn->ty) 2848 2866 { 2849 2867 case Tfunction: 2850 2868 case Tnone: 2851 2869 case Ttuple: 2852 2870 error(loc, "can't have array of %s", tbn->toChars()); 2853 2871 tn = next = tint32; 2854 2872 break; 2873 case Tstruct: 2874 { TypeStruct *ts = (TypeStruct *)tbn; 2875 if (ts->sym->isnested) 2876 error(loc, "cannot have array of inner structs %s", ts->toChars()); 2877 break; 2878 } 2855 2879 } 2856 2880 if (tn->isauto()) 2857 2881 error(loc, "cannot have array of auto %s", tn->toChars()); 2858 2882 2859 2883 next = tn; 2860 2884 transitive(); 2861 2885 return merge(); 2862 2886 } 2863 2887 2864 2888 void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag) 2865 2889 { 2866 2890 Type::toDecoBuffer(buf, flag); 2867 2891 if (next) 2868 2892 next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); 2869 2893 } 2870 2894 2871 2895 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 2872 2896 { 2873 2897 if (mod != this->mod) 2874 2898 { toCBuffer3(buf, hgs, mod); … … 3651 3675 buf->writeByte(mc); 3652 3676 if (ispure || isnothrow || isref) 3653 3677 { 3654 3678 if (ispure) 3655 3679 buf->writestring("Na"); 3656 3680 if (isnothrow) 3657 3681 buf->writestring("Nb"); 3658 3682 if (isref) 3659 3683 buf->writestring("Nc"); 3660 3684 } 3661 3685 // Write argument types 3662 3686 Argument::argsToDecoBuffer(buf, parameters); 3663 3687 //if (buf->data[buf->offset - 1] == '@') halt(); 3664 3688 buf->writeByte('Z' - varargs); // mark end of arg list 3665 3689 next->toDecoBuffer(buf); 3666 3690 inuse--; 3667 3691 } 3668 3692 3669 3693 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) 3670 3694 { 3671 //printf("TypeFunction::toCBuffer() this = %p %s\n", this, toChars());3695 //printf("TypeFunction::toCBuffer() this = %p\n", this); 3672 3696 const char *p = NULL; 3673 3697 3674 3698 if (inuse) 3675 3699 { inuse = 2; // flag error to caller 3676 3700 return; 3677 3701 } 3678 3702 inuse++; 3679 3703 3680 3704 /* Use 'storage class' style for attributes 3681 3705 */ 3682 3706 if (mod & MODconst) 3683 3707 buf->writestring("const "); 3684 3708 if (mod & MODinvariant) 3685 3709 buf->writestring("immutable "); 3686 3710 if (mod & MODshared) 3687 3711 buf->writestring("shared "); 3688 3712 3689 3713 if (ispure) 3690 3714 buf->writestring("pure "); 3691 3715 if (isnothrow) … … 3704 3728 case LINKwindows: p = "Windows "; break; 3705 3729 case LINKpascal: p = "Pascal "; break; 3706 3730 case LINKcpp: p = "C++ "; break; 3707 3731 default: 3708 3732 assert(0); 3709 3733 } 3710 3734 } 3711 3735 3712 3736 if (!hgs->hdrgen && p) 3713 3737 buf->writestring(p); 3714 3738 if (ident) 3715 3739 { buf->writeByte(' '); 3716 3740 buf->writestring(ident->toHChars2()); 3717 3741 } 3718 3742 Argument::argsToCBuffer(buf, hgs, parameters, varargs); 3719 3743 inuse--; 3720 3744 } 3721 3745 3722 3746 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 3723 3747 { 3724 //printf("TypeFunction::toCBuffer2() this = %p %s\n", this, toChars());3748 //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref); 3725 3749 const char *p = NULL; 3726 3750 3727 3751 if (inuse) 3728 3752 { inuse = 2; // flag error to caller 3729 3753 return; 3730 3754 } 3731 3755 inuse++; 3732 3756 if (next) 3733 3757 next->toCBuffer2(buf, hgs, 0); 3734 3758 if (hgs->ddoc != 1) 3735 3759 { 3736 3760 switch (linkage) 3737 3761 { 3738 3762 case LINKd: p = NULL; break; 3739 3763 case LINKc: p = "C "; break; 3740 3764 case LINKwindows: p = "Windows "; break; 3741 3765 case LINKpascal: p = "Pascal "; break; 3742 3766 case LINKcpp: p = "C++ "; break; 3743 3767 default: 3744 3768 assert(0); … … 4983 5007 buf->printf("%s", name); 4984 5008 } 4985 5009 4986 5010 void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) 4987 5011 { 4988 5012 if (mod != this->mod) 4989 5013 { toCBuffer3(buf, hgs, mod); 4990 5014 return; 4991 5015 } 4992 5016 buf->writestring(sym->toChars()); 4993 5017 } 4994 5018 4995 5019 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) 4996 5020 { 4997 5021 #if LOGDOTEXP 4998 5022 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); 4999 5023 #endif 5000 5024 Dsymbol *s = sym->search(e->loc, ident, 0); 5001 5025 if (!s) 5002 5026 { 5003 return getProperty(e->loc, ident); 5027 if (ident == Id::max || 5028 ident == Id::min || 5029 ident == Id::init || 5030 ident == Id::stringof || 5031 !sym->memtype 5032 ) 5033 { 5034 return getProperty(e->loc, ident); 5035 } 5036 return sym->memtype->dotExp(sc, e, ident); 5004 5037 } 5005 5038 EnumMember *m = s->isEnumMember(); 5006 5039 Expression *em = m->value->copy(); 5007 5040 em->loc = e->loc; 5008 5041 return em; 5009 5042 } 5010 5043 5011 5044 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident) 5012 5045 { Expression *e; 5013 5046 5014 5047 if (ident == Id::max) 5015 5048 { 5016 5049 if (!sym->maxval) 5017 5050 goto Lfwd; 5018 5051 e = sym->maxval; 5019 5052 } 5020 5053 else if (ident == Id::min) 5021 5054 { 5022 5055 if (!sym->minval) 5023 5056 goto Lfwd; … … 5684 5717 { 5685 5718 /* If any of the fields are const or invariant, 5686 5719 * then one cannot assign this struct. 5687 5720 */ 5688 5721 for (size_t i = 0; i < sym->fields.dim; i++) 5689 5722 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i]; 5690 5723 if (v->isConst() || v->isInvariant()) 5691 5724 return FALSE; 5692 5725 } 5693 5726 return TRUE; 5694 5727 } 5695 5728 5696 5729 int TypeStruct::hasPointers() 5697 5730 { 5698 5731 StructDeclaration *s = sym; 5699 5732 5700 5733 sym->size(0); // give error for forward references 5701 5734 for (size_t i = 0; i < s->fields.dim; i++) 5702 5735 { 5703 5736 Dsymbol *sm = (Dsymbol *)s->fields.data[i]; 5704 if (sm->hasPointers()) 5737 Declaration *d = sm->isDeclaration(); 5738 if (d->storage_class & STCref || d->hasPointers()) 5705 5739 return TRUE; 5706 5740 } 5707 5741 return FALSE; 5708 5742 } 5709 5743 5710 5744 MATCH TypeStruct::implicitConvTo(Type *to) 5711 5745 { MATCH m; 5712 5746 5713 5747 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars()); 5714 5748 if (ty == to->ty && sym == ((TypeStruct *)to)->sym) 5715 5749 { m = MATCHexact; // exact match 5716 5750 if (mod != to->mod) 5717 5751 { 5718 5752 if (to->mod == MODconst) 5719 5753 m = MATCHconst; 5720 5754 else 5721 5755 { /* Check all the fields. If they can all be converted, 5722 5756 * allow the conversion. 5723 5757 */ 5724 5758 for (int i = 0; i < sym->fields.dim; i++) trunk/src/mtype.h
r182 r183 266 266 virtual ClassDeclaration *isClassHandle(); 267 267 virtual Expression *getProperty(Loc loc, Identifier *ident); 268 268 virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); 269 269 virtual unsigned memalign(unsigned salign); 270 270 virtual Expression *defaultInit(Loc loc = 0); 271 271 virtual int isZeroInit(); // if initializer is 0 272 272 virtual dt_t **toDt(dt_t **pdt); 273 273 Identifier *getTypeInfoIdent(int internal); 274 274 virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); 275 275 virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); 276 276 Expression *getInternalTypeInfo(Scope *sc); 277 277 Expression *getTypeInfo(Scope *sc); 278 278 virtual TypeInfoDeclaration *getTypeInfoDeclaration(); 279 279 virtual int builtinTypeInfo(); 280 280 virtual Type *reliesOnTident(); 281 281 virtual Expression *toExpression(); 282 282 virtual int hasPointers(); 283 283 virtual Type *nextOf(); 284 284 285 285 static void error(Loc loc, const char *format, ...); 286 static void warning(Loc loc, const char *format, ...); 286 287 287 288 // For backend 288 289 virtual unsigned totym(); 289 290 virtual type *toCtype(); 290 291 virtual type *toCParamtype(); 291 292 virtual Symbol *toSymbol(); 292 293 293 294 // For eliminating dynamic_cast 294 295 virtual TypeBasic *isTypeBasic(); 295 296 }; 296 297 297 298 struct TypeNext : Type 298 299 { 299 300 Type *next; 300 301 301 302 TypeNext(TY ty, Type *next); 302 303 void toDecoBuffer(OutBuffer *buf, int flag); 303 304 void checkDeprecated(Loc loc, Scope *sc); 304 305 Type *reliesOnTident(); 305 306 Type *nextOf(); … … 794 795 Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg); 795 796 Argument *syntaxCopy(); 796 797 Type *isLazyArray(); 797 798 void toDecoBuffer(OutBuffer *buf); 798 799 static Arguments *arraySyntaxCopy(Arguments *args); 799 800 static char *argsTypesToChars(Arguments *args, int varargs); 800 801 static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs); 801 802 static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs); 802 803 static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments); 803 804 static int isTPL(Arguments *arguments); 804 805 static size_t dim(Arguments *arguments); 805 806 static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL); 806 807 }; 807 808 808 809 extern int PTRSIZE; 809 810 extern int REALSIZE; 810 811 extern int REALPAD; 811 812 extern int Tsize_t; 812 813 extern int Tptrdiff_t; 813 814 815 int arrayTypeCompatible(Loc loc, Type *t1, Type *t2); 816 814 817 #endif /* DMD_MTYPE_H */ trunk/src/opover.c
r182 r183 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <ctype.h> 14 14 #include <assert.h> 15 15 #if _MSC_VER 16 16 #include <complex> 17 17 #else 18 18 #include <complex.h> 19 19 #endif 20 20 21 21 #ifdef __APPLE__ 22 22 #define integer_t dmd_integer_t 23 23 #endif 24 24 25 #if IN_GCC 26 #include "mem.h" 27 #elif linux || __APPLE__ 28 #include "../root/mem.h" 29 #elif _WIN32 30 #include "..\root\mem.h" 31 #endif 25 #include "rmem.h" 32 26 33 27 //#include "port.h" 34 28 #include "mtype.h" 35 29 #include "init.h" 36 30 #include "expression.h" 37 31 #include "id.h" 38 32 #include "declaration.h" 39 33 #include "aggregate.h" 40 34 #include "template.h" 41 35 42 36 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments); 43 37 static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Arguments *arguments); 44 38 static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments); 45 39 static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments); 46 40 47 41 /******************************** Expression **************************/ 48 42 49 43 50 44 /*********************************** 51 45 * Determine if operands of binary op can be reversed trunk/src/parse.c
r181 r183 1 1 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 // This is the D parser 12 12 13 13 #include <stdio.h> 14 14 #include <assert.h> 15 15 16 #include " mem.h"16 #include "rmem.h" 17 17 #include "lexer.h" 18 18 #include "parse.h" 19 19 #include "init.h" 20 20 #include "attrib.h" 21 21 #include "cond.h" 22 22 #include "mtype.h" 23 23 #include "template.h" 24 24 #include "staticassert.h" 25 25 #include "expression.h" 26 26 #include "statement.h" 27 27 #include "module.h" 28 28 #include "dsymbol.h" 29 29 #include "import.h" 30 30 #include "declaration.h" 31 31 #include "aggregate.h" 32 32 #include "enum.h" 33 33 #include "id.h" 34 34 #include "version.h" 35 35 36 36 // How multiple declarations are parsed. … … 370 370 break; 371 371 } 372 372 373 373 /* Look for auto initializers: 374 374 * storage_class identifier = initializer; 375 375 */ 376 376 if (token.value == TOKidentifier && 377 377 peek(&token)->value == TOKassign) 378 378 { 379 379 a = parseAutoDeclarations(storageClass, comment); 380 380 decldefs->append(a); 381 381 continue; 382 382 } 383 383 384 384 /* Look for return type inference for template functions. 385 385 */ 386 386 Token *tk; 387 387 if (token.value == TOKidentifier && 388 388 (tk = peek(&token))->value == TOKlparen && 389 389 skipParens(tk, &tk) && 390 peek(tk)->value == TOKlparen) 390 (peek(tk)->value == TOKlparen || 391 peek(tk)->value == TOKlcurly) 392 ) 391 393 { 392 394 a = parseDeclarations(storageClass); 393 395 decldefs->append(a); 394 396 continue; 395 397 } 396 398 a = parseBlock(); 397 399 s = new StorageClassDeclaration(storageClass, a); 398 400 break; 399 401 400 402 case TOKextern: 401 403 if (peek(&token)->value != TOKlparen) 402 404 { stc = STCextern; 403 405 goto Lstc; 404 406 } 405 407 { 406 408 enum LINK linksave = linkage; 407 409 linkage = parseLinkage(); 408 410 a = parseBlock(); 409 411 s = new LinkDeclaration(linkage, a); 410 412 linkage = linksave; … … 1731 1733 /****************************************** 1732 1734 * Parse template argument list. 1733 1735 * Input: 1734 1736 * current token is opening '(' 1735 1737 * Output: 1736 1738 * current token is one after closing ')' 1737 1739 */ 1738 1740 1739 1741 Objects *Parser::parseTemplateArgumentList() 1740 1742 { 1741 1743 //printf("Parser::parseTemplateArgumentList()\n"); 1742 1744 if (token.value != TOKlparen && token.value != TOKlcurly) 1743 1745 { error("!(TemplateArgumentList) expected following TemplateIdentifier"); 1744 1746 return new Objects(); 1745 1747 } 1746 1748 return parseTemplateArgumentList2(); 1747 1749 } 1748 1750 1749 1751 Objects *Parser::parseTemplateArgumentList2() 1750 1752 { 1753 //printf("Parser::parseTemplateArgumentList2()\n"); 1751 1754 Objects *tiargs = new Objects(); 1752 1755 enum TOK endtok = TOKrparen; 1753 1756 nextToken(); 1754 1757 1755 1758 // Get TemplateArgumentList 1756 1759 if (token.value != endtok) 1757 1760 { 1758 1761 while (1) 1759 1762 { 1760 1763 // See if it is an Expression or a Type 1761 1764 if (isDeclaration(&token, 0, TOKreserved, NULL)) 1762 1765 { // Template argument is a type 1763 1766 Type *ta = parseType(); 1764 1767 tiargs->push(ta); 1765 1768 } 1766 1769 else 1767 1770 { // Template argument is an expression 1768 1771 Expression *ea = parseAssignExp(); 1769 1772 tiargs->push(ea); 1770 1773 } … … 3889 3892 if (token.value != value) 3890 3893 error("found '%s' when expecting '%s' following '%s'", 3891 3894 token.toChars(), Token::toChars(value), string); 3892 3895 nextToken(); 3893 3896 } 3894 3897 3895 3898 /************************************ 3896 3899 * Determine if the scanner is sitting on the start of a declaration. 3897 3900 * Input: 3898 3901 * needId 0 no identifier 3899 3902 * 1 identifier optional 3900 3903 * 2 must have identifier 3901 3904 */ 3902 3905 3903 3906 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) 3904 3907 { 3905 3908 //printf("isDeclaration(needId = %d)\n", needId); 3906 3909 int haveId = 0; 3907 3910 3908 3911 #if V2 3909 if ((t->value == TOKconst || t->value == TOKinvariant || token.value == TOKimmutable || token.value == TOKshared) && 3912 if ((t->value == TOKconst || 3913 t->value == TOKinvariant || 3914 t->value == TOKimmutable || 3915 t->value == TOKshared) && 3910 3916 peek(t)->value != TOKlparen) 3911 3917 { /* const type 3912 3918 * immutable type 3913 3919 * shared type 3914 3920 */ 3915 3921 t = peek(t); 3916 3922 } 3917 3923 #endif 3918 3924 3919 3925 if (!isBasicType(&t)) 3926 { 3920 3927 goto Lisnot; 3928 } 3921 3929 if (!isDeclarator(&t, &haveId, endtok)) 3922 3930 goto Lisnot; 3923 3931 if ( needId == 1 || 3924 3932 (needId == 0 && !haveId) || 3925 3933 (needId == 2 && haveId)) 3926 3934 { if (pt) 3927 3935 *pt = t; 3928 3936 goto Lis; 3929 3937 } 3930 3938 else 3931 3939 goto Lisnot; 3932 3940 3933 3941 Lis: 3934 3942 //printf("\tis declaration\n"); 3935 3943 return TRUE; 3936 3944 3937 3945 Lisnot: 3938 3946 //printf("\tis not declaration\n"); 3939 3947 return FALSE; 3940 3948 } … … 4024 4032 case TOKtypeof: 4025 4033 /* typeof(exp).identifier... 4026 4034 */ 4027 4035 t = peek(t); 4028 4036 if (t->value != TOKlparen) 4029 4037 goto Lfalse; 4030 4038 if (!skipParens(t, &t)) 4031 4039 goto Lfalse; 4032 4040 goto L2; 4033 4041 4034 4042 case TOKconst: 4035 4043 case TOKinvariant: 4036 4044 case TOKimmutable: 4037 4045 case TOKshared: 4038 4046 // const(type) or immutable(type) or shared(type) 4039 4047 t = peek(t); 4040 4048 if (t->value != TOKlparen) 4041 4049 goto Lfalse; 4042 4050 t = peek(t); 4043 4051 if (!isDeclaration(t, 0, TOKrparen, &t)) 4052 { 4044 4053 goto Lfalse; 4054 } 4045 4055 t = peek(t); 4046 4056 break; 4047 4057 4048 4058 default: 4049 4059 goto Lfalse; 4050 4060 } 4051 4061 *pt = t; 4052 4062 //printf("is\n"); 4053 4063 return TRUE; 4054 4064 4055 4065 Lfalse: 4056 4066 //printf("is not\n"); 4057 4067 return FALSE; 4058 4068 } 4059 4069 4060 4070 int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) 4061 4071 { // This code parallels parseDeclarator() 4062 4072 Token *t = *pt; 4063 4073 int parens; 4064 4074 trunk/src/readme.txt
r5 r183 1 1 2 2 The D Programming Language 3 3 Compiler Front End Source 4 Copyright (c) 1999-200 2, by Digital Mars5 www.digitalmars.com4 Copyright (c) 1999-2009, by Digital Mars 5 http://www.digitalmars.com 6 6 All Rights Reserved 7 7 8 8 9 9 This is the source code to the front end Digital Mars D compiler. 10 10 It covers the lexical analysis, parsing, and semantic analysis 11 11 of the D Programming Language defined in the documents at 12 www.digitalmars.com/d/ 13 14 The optimizer, code generator, and object file generator are not part 15 of this source, hence the source does not currently constitute a complete, 16 compilable program. However, many people have expressed a strong interested 17 in producing a D compiler with the GNU compiler sources. This release should 18 enable that. 12 http://www.digitalmars.com/d/ 19 13 20 14 These sources are free, they are redistributable and modifiable 21 15 under the terms of the GNU General Public License (attached as gpl.txt), 22 16 or the Artistic License (attached as artistic.txt). 23 17 18 The optimizer and code generator sources are 19 covered under a separate license, backendlicense.txt. 20 24 21 It does not apply to anything else distributed by Digital Mars, 25 22 including D compiler executables. 26 23 27 24 -Walter Bright trunk/src/root/array.c
r103 r183 20 20 #if IN_GCC 21 21 #include "gdc_alloca.h" 22 22 #endif 23 23 24 24 #if _WIN32 25 25 #include <windows.h> 26 26 #endif 27 27 28 28 #ifndef _WIN32 29 29 #include <sys/types.h> 30 30 #include <sys/stat.h> 31 31 #include <fcntl.h> 32 32 #include <errno.h> 33 33 #include <unistd.h> 34 34 #include <utime.h> 35 35 #endif 36 36 37 37 #include "port.h" 38 38 #include "root.h" 39 39 #include "dchar.h" 40 #include " mem.h"40 #include "rmem.h" 41 41 42 42 43 43 /********************************* Array ****************************/ 44 44 45 45 Array::Array() 46 46 { 47 47 data = NULL; 48 48 dim = 0; 49 49 allocdim = 0; 50 50 } 51 51 52 52 Array::~Array() 53 53 { 54 54 mem.free(data); 55 55 } 56 56 57 57 void Array::mark() 58 58 { unsigned u; 59 59 60 60 mem.mark(data); trunk/src/root/dchar.c
r111 r183 1 1 2 2 // Copyright (c) 1999-2006 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <stdint.h> 14 14 #include <assert.h> 15 15 16 16 #include "dchar.h" 17 #include " mem.h"17 #include "rmem.h" 18 18 19 19 #if M_UNICODE 20 20 21 21 // Converts a char string to Unicode 22 22 23 23 dchar *Dchar::dup(char *p) 24 24 { 25 25 dchar *s; 26 26 size_t len; 27 27 28 28 if (!p) 29 29 return NULL; 30 30 len = strlen(p); 31 31 s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); 32 32 for (unsigned i = 0; i < len; i++) 33 33 { 34 34 s[i] = (dchar)(p[i] & 0xFF); 35 35 } 36 36 s[len] = 0; 37 37 return s; trunk/src/root/lstring.c
r179 r183 1 1 // lstring.c 2 2 3 3 // Copyright (c) 1999-2002 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdlib.h> 12 12 13 13 #include "dchar.h" 14 #include " mem.h"14 #include "rmem.h" 15 15 #include "lstring.h" 16 16 17 17 #ifdef _MSC_VER // prevent compiler internal crash 18 18 Lstring Lstring::zero; 19 19 #else 20 20 Lstring Lstring::zero = LSTRING_EMPTY(); 21 21 #endif 22 22 23 23 Lstring *Lstring::ctor(const dchar *p, unsigned length) 24 24 { 25 25 Lstring *s; 26 26 27 27 s = alloc(length); 28 28 memcpy(s->string, p, length * sizeof(dchar)); 29 29 return s; 30 30 } 31 31 32 32 Lstring *Lstring::alloc(unsigned length) 33 33 { 34 34 Lstring *s; trunk/src/root/rmem.c
r182 r183 1 1 2 2 /* Copyright (c) 2000 Digital Mars */ 3 3 /* All Rights Reserved */ 4 4 5 5 #include <stdio.h> 6 6 #include <stdlib.h> 7 7 #include <string.h> 8 8 9 9 #if linux || __APPLE__ || __FreeBSD__ 10 #include "../root/ mem.h"10 #include "../root/rmem.h" 11 11 #else 12 #include " mem.h"12 #include "rmem.h" 13 13 #endif 14 14 15 15 /* This implementation of the storage allocator uses the standard C allocation package. 16 16 */ 17 17 18 18 Mem mem; 19 19 20 20 void Mem::init() 21 21 { 22 22 } 23 23 24 24 char *Mem::strdup(const char *s) 25 25 { 26 26 char *p; 27 27 28 28 if (s) 29 29 { 30 30 p = ::strdup(s); 31 31 if (p) 32 32 return p; trunk/src/root/root.c
r182 r183 19 19 #include <string> 20 20 #endif 21 21 22 22 #if _WIN32 23 23 #include <windows.h> 24 24 #include <direct.h> 25 25 #endif 26 26 27 27 #if linux || __APPLE__ || __FreeBSD__ 28 28 #include <sys/types.h> 29 29 #include <sys/stat.h> 30 30 #include <fcntl.h> 31 31 #include <errno.h> 32 32 #include <unistd.h> 33 33 #include <utime.h> 34 34 #endif 35 35 36 36 #include "port.h" 37 37 #include "root.h" 38 38 #include "dchar.h" 39 #include " mem.h"39 #include "rmem.h" 40 40 41 41 #if 0 //__SC__ //def DEBUG 42 42 extern "C" void __cdecl _assert(void *e, void *f, unsigned line) 43 43 { 44 44 printf("Assert('%s','%s',%d)\n",e,f,line); 45 45 fflush(stdout); 46 46 *(char *)0 = 0; 47 47 } 48 48 #endif 49 49 50 50 51 51 /************************************* 52 52 * Convert wchar string to ascii string. 53 53 */ 54 54 55 55 char *wchar2ascii(wchar_t *us) 56 56 { 57 57 return wchar2ascii(us, wcslen(us)); 58 58 } 59 59 trunk/src/root/stringtable.c
r172 r183 1 1 2 2 // Copyright (c) 1999-2008 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 11 11 #include <stdio.h> 12 12 #include <string.h> 13 13 #include <stdlib.h> 14 14 15 15 #include "root.h" 16 #include " mem.h"16 #include "rmem.h" 17 17 #include "dchar.h" 18 18 #include "lstring.h" 19 19 #include "stringtable.h" 20 20 21 21 StringTable::StringTable(unsigned size) 22 22 { 23 23 table = (void **)mem.calloc(size, sizeof(void *)); 24 24 tabledim = size; 25 25 count = 0; 26 26 } 27 27 28 28 StringTable::~StringTable() 29 29 { 30 30 unsigned i; 31 31 32 32 // Zero out dangling pointers to help garbage collector. 33 33 // Should zero out StringEntry's too. 34 34 for (i = 0; i < count; i++) 35 35 table[i] = NULL; 36 36 trunk/src/scope.c
r169 r183 236 236 } 237 237 return NULL; 238 238 } 239 239 240 240 for (sc = this; sc; sc = sc->enclosing) 241 241 { 242 242 assert(sc != sc->enclosing); 243 243 if (sc->scopesym) 244 244 { 245 245 //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind()); 246 246 s = sc->scopesym->search(loc, ident, 0); 247 247 if (s) 248 248 { 249 249 if ((global.params.warnings || 250 250 global.params.Dversion > 1) && 251 251 ident == Id::length && 252 252 sc->scopesym->isArrayScopeSymbol() && 253 253 sc->enclosing && 254 254 sc->enclosing->search(loc, ident, NULL)) 255 255 { 256 if (global.params.warnings) 257 fprintf(stdmsg, "warning - "); 258 error(s->loc, "array 'length' hides other 'length' name in outer scope"); 256 warning(s->loc, "array 'length' hides other 'length' name in outer scope"); 259 257 } 260 258 261 259 //printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind()); 262 260 if (pscopesym) 263 261 *pscopesym = sc->scopesym; 264 262 return s; 265 263 } 266 264 } 267 265 } 268 266 269 267 return NULL; 270 268 } 271 269 272 270 Dsymbol *Scope::insert(Dsymbol *s) 273 271 { Scope *sc; 274 272 275 273 for (sc = this; sc; sc = sc->enclosing) 276 274 { 277 275 //printf("\tsc = %p\n", sc); 278 276 if (sc->scopesym) trunk/src/statement.c
r182 r183 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-200 8by Digital Mars3 // Copyright (c) 1999-2009 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <assert.h> 14 14 15 #include " mem.h"15 #include "rmem.h" 16 16 17 17 #include "statement.h" 18 18 #include "expression.h" 19 19 #include "cond.h" 20 20 #include "init.h" 21 21 #include "staticassert.h" 22 22 #include "mtype.h" 23 23 #include "scope.h" 24 24 #include "declaration.h" 25 25 #include "aggregate.h" 26 26 #include "id.h" 27 27 #include "hdrgen.h" 28 28 #include "parse.h" 29 29 #include "template.h" 30 30 31 31 /******************************** Statement ***************************/ 32 32 33 33 Statement::Statement(Loc loc) 34 34 : loc(loc) 35 35 { … … 77 77 Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue) 78 78 { Scope *scd; 79 79 Statement *s; 80 80 81 81 scd = sc->push(); 82 82 if (sbreak) 83 83 scd->sbreak = sbreak; 84 84 if (scontinue) 85 85 scd->scontinue = scontinue; 86 86 s = semantic(scd); 87 87 scd->pop(); 88 88 return s; 89 89 } 90 90 91 91 void Statement::error(const char *format, ...) 92 92 { 93 93 va_list ap; 94 94 va_start(ap, format); 95 95 ::verror(loc, format, ap); 96 96 va_end( ap ); 97 } 98 99 void Statement::warning(const char *format, ...) 100 { 101 if (global.params.warnings && !global.gag) 102 { 103 fprintf(stdmsg, "warning - "); 104 va_list ap; 105 va_start(ap, format); 106 ::verror(loc, format, ap); 107 va_end( ap ); 108 } 97 109 } 98 110 99 111 int Statement::hasBreak() 100 112 { 101 113 //printf("Statement::hasBreak()\n"); 102 114 return FALSE; 103 115 } 104 116 105 117 int Statement::hasContinue() 106 118 { 107 119 return FALSE; 108 120 } 109 121 110 122 // TRUE if statement uses exception handling 111 123 112 124 int Statement::usesEH() 113 125 { 114 126 return FALSE; 115 127 } 116 128 … … 526 538 for (int i = 0; i < statements->dim; i++) 527 539 { Statement *s = (Statement *) statements->data[i]; 528 540 if (s && s->usesEH()) 529 541 return TRUE; 530 542 } 531 543 return FALSE; 532 544 } 533 545 534 546 int CompoundStatement::blockExit() 535 547 { 536 548 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); 537 549 int result = BEfallthru; 538 550 for (size_t i = 0; i < statements->dim; i++) 539 551 { Statement *s = (Statement *) statements->data[i]; 540 552 if (s) 541 553 { 542 554 //printf("result = x%x\n", result); 543 555 //printf("%s\n", s->toChars()); 544 556 if (!(result & BEfallthru) && !s->comeFrom()) 545 557 { 546 if (global.params.warnings) 547 { fprintf(stdmsg, "warning - "); 548 s->error("statement is not reachable"); 549 } 558 s->warning("statement is not reachable"); 550 559 } 551 560 552 561 result &= ~BEfallthru; 553 562 result |= s->blockExit(); 554 563 } 555 564 } 556 565 return result; 557 566 } 558 567 559 568 560 569 int CompoundStatement::comeFrom() 561 570 { int comefrom = FALSE; 562 571 563 572 //printf("CompoundStatement::comeFrom()\n"); 564 573 for (int i = 0; i < statements->dim; i++) 565 574 { Statement *s = (Statement *)statements->data[i]; 566 575 567 576 if (!s) 568 577 continue; 569 578 … … 1073 1082 { 1074 1083 return (init && init->usesEH()) || body->usesEH(); 1075 1084 } 1076 1085 1077 1086 int ForStatement::blockExit() 1078 1087 { int result = BEfallthru; 1079 1088 1080 1089 if (init) 1081 1090 { result = init->blockExit(); 1082 1091 if (!(result & BEfallthru)) 1083 1092 return result; 1084 1093 } 1085 1094 if (condition) 1086 1095 { if (condition->canThrow()) 1087 1096 result |= BEthrow; 1088 1097 } 1089 1098 else 1090 1099 result &= ~BEfallthru; // the body must do the exiting 1091 1100 if (body) 1092 1101 { int r = body->blockExit(); 1093 if (r & BEbreak)1102 if (r & (BEbreak | BEgoto)) 1094 1103 result |= BEfallthru; 1095 result |= r & ~(BE break | BEcontinue);1104 result |= r & ~(BEfallthru | BEbreak | BEcontinue); 1096 1105 } 1097 1106 if (increment && increment->canThrow()) 1098 1107 result |= BEthrow; 1099 1108 return result; 1100 1109 } 1101 1110 1102 1111 1103 1112 int ForStatement::comeFrom() 1104 1113 { 1105 1114 //printf("ForStatement::comeFrom()\n"); 1106 1115 if (body) 1107 1116 { int result = body->comeFrom(); 1108 1117 //printf("result = %d\n", result); 1109 1118 return result; 1110 1119 } 1111 1120 return FALSE; 1112 1121 } 1113 1122 1114 1123 void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1115 1124 { … … 1435 1444 ? (AggregateDeclaration *)((TypeClass *)tab)->sym 1436 1445 : (AggregateDeclaration *)((TypeStruct *)tab)->sym; 1437 1446 Identifier *idhead; 1438 1447 Identifier *idnext; 1439 1448 if (op == TOKforeach) 1440 1449 { idhead = Id::Fhead; 1441 1450 idnext = Id::Fnext; 1442 1451 } 1443 1452 else 1444 1453 { idhead = Id::Ftoe; 1445 1454 idnext = Id::Fretreat; 1446 1455 } 1447 1456 Dsymbol *shead = search_function(ad, idhead); 1448 1457 if (!shead) 1449 1458 goto Lapply; 1450 1459 1451 1460 /* Generate a temporary __r and initialize it with the aggregate. 1452 1461 */ 1453 1462 Identifier *id = Identifier::generateId("__r"); 1454 1463 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); 1455 r->semantic(sc); 1464 // r->semantic(sc); 1465 //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars()); 1456 1466 Statement *init = new DeclarationStatement(loc, r); 1467 //printf("init: %s\n", init->toChars()); 1457 1468 1458 1469 // !__r.empty 1459 1470 Expression *e = new VarExp(loc, r); 1460 1471 e = new DotIdExp(loc, e, Id::Fempty); 1461 1472 Expression *condition = new NotExp(loc, e); 1462 1473 1463 1474 // __r.next 1464 1475 e = new VarExp(loc, r); 1465 1476 Expression *increment = new DotIdExp(loc, e, idnext); 1466 1477 1467 1478 /* Declaration statement for e: 1468 1479 * auto e = __r.idhead; 1469 1480 */ 1470 1481 e = new VarExp(loc, r); 1471 1482 Expression *einit = new DotIdExp(loc, e, idhead); 1472 einit = einit->semantic(sc);1483 // einit = einit->semantic(sc); 1473 1484 Argument *arg = (Argument *)arguments->data[0]; 1474 1485 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); 1475 1486 ve->storage_class |= STCforeach; 1476 1487 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); 1477 1488 1478 1489 DeclarationExp *de = new DeclarationExp(loc, ve); 1479 1490 1480 1491 Statement *body = new CompoundStatement(loc, 1481 1492 new DeclarationStatement(loc, de), this->body); 1482 1493 1483 1494 s = new ForStatement(loc, init, condition, increment, body); 1484 1495 s = s->semantic(sc); 1485 1496 break; 1486 1497 } 1487 1498 #endif 1488 1499 case Tdelegate: 1489 1500 Lapply: 1490 1501 { FuncDeclaration *fdapply; 1491 1502 Arguments *args; 1492 1503 Expression *ec; … … 2438 2449 for (int j = 0; j < scx->sw->cases->dim; j++) 2439 2450 { 2440 2451 CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j]; 2441 2452 2442 2453 if (cs->exp->equals(gcs->exp)) 2443 2454 { 2444 2455 gcs->cs = cs; 2445 2456 goto Lfoundcase; 2446 2457 } 2447 2458 } 2448 2459 } 2449 2460 gcs->error("case %s not found", gcs->exp->toChars()); 2450 2461 2451 2462 Lfoundcase: 2452 2463 ; 2453 2464 } 2454 2465 2455 2466 if (!sc->sw->sdefault) 2456 2467 { hasNoDefault = 1; 2457 2468 2458 if (global.params.warnings) 2459 { fprintf(stdmsg, "warning - "); 2460 error("switch statement has no default"); 2461 } 2469 warning("switch statement has no default"); 2462 2470 2463 2471 // Generate runtime error if the default is hit 2464 2472 Statements *a = new Statements(); 2465 2473 CompoundStatement *cs; 2466 2474 Statement *s; 2467 2475 2468 2476 if (global.params.useSwitchError) 2469 2477 s = new SwitchErrorStatement(loc); 2470 2478 else 2471 2479 { Expression *e = new HaltExp(loc); 2472 2480 s = new ExpStatement(loc, e); 2473 2481 } 2474 2482 2475 2483 a->reserve(4); 2476 2484 a->push(body); 2477 2485 a->push(new BreakStatement(loc, NULL)); 2478 2486 sc->sw->sdefault = new DefaultStatement(loc, s); 2479 2487 a->push(sc->sw->sdefault); 2480 2488 cs = new CompoundStatement(loc, a); 2481 2489 body = cs; trunk/src/statement.h
r180 r183 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2008 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #ifndef DMD_STATEMENT_H 12 12 #define DMD_STATEMENT_H 13 13 14 14 #ifdef __DMC__ 15 15 #pragma once 16 16 #endif /* __DMC__ */ 17 17 18 18 #include "root.h" 19 19 20 20 #include "arraytypes.h" 21 21 #include "dsymbol.h" 22 #include "lexer.h" 22 23 23 24 struct OutBuffer; 24 25 struct Scope; 25 26 struct Expression; 26 27 struct LabelDsymbol; 27 28 struct Identifier; 28 29 struct IfStatement; 29 30 struct DeclarationStatement; 30 31 struct DefaultStatement; 31 32 struct VarDeclaration; 32 33 struct Condition; 33 34 struct Module; 34 35 struct Token; 35 36 struct InlineCostState; 36 37 struct InlineDoState; 37 38 struct InlineScanState; 38 39 struct ReturnStatement; 39 40 struct CompoundStatement; 40 41 struct Argument; 41 42 struct StaticAssert; … … 70 71 BEthrow = 2, 71 72 BEreturn = 4, 72 73 BEgoto = 8, 73 74 BEhalt = 0x10, 74 75 BEbreak = 0x20, 75 76 BEcontinue = 0x40, 76 77 BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt), 77 78 }; 78 79 79 80 struct Statement : Object 80 81 { 81 82 Loc loc; 82 83 83 84 Statement(Loc loc); 84 85 virtual Statement *syntaxCopy(); 85 86 86 87 void print(); 87 88 char *toChars(); 88 89 89 90 void error(const char *format, ...); 91 void warning(const char *format, ...); 90 92 virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 91 93 virtual TryCatchStatement *isTryCatchStatement() { return NULL; } 92 94 virtual GotoStatement *isGotoStatement() { return NULL; } 93 95 virtual AsmStatement *isAsmStatement() { return NULL; } 94 96 #ifdef _DH 95 97 int incontract; 96 98 #endif 97 99 virtual ScopeStatement *isScopeStatement() { return NULL; } 98 100 virtual Statement *semantic(Scope *sc); 99 101 Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue); 100 102 virtual int hasBreak(); 101 103 virtual int hasContinue(); 102 104 virtual int usesEH(); 103 105 virtual int blockExit(); 104 106 virtual int comeFrom(); 105 107 virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); 106 108 virtual Statements *flatten(Scope *sc); 107 109 virtual Expression *interpret(InterState *istate); 108 110 109 111 virtual int inlineCost(InlineCostState *ics); trunk/src/struct.c
r182 r183 2 2 // Compiler implementation of the D programming language 3 3 // Copyright (c) 1999-2009 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <assert.h> 13 13 14 14 #include "root.h" 15 15 #include "aggregate.h" 16 16 #include "scope.h" 17 17 #include "mtype.h" 18 18 #include "declaration.h" 19 19 #include "module.h" 20 20 #include "id.h" 21 21 #include "statement.h" 22 #include "template.h" 22 23 23 24 /********************************* AggregateDeclaration ****************************/ 24 25 25 26 AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) 26 27 : ScopeDsymbol(id) 27 28 { 28 29 this->loc = loc; 29 30 30 31 storage_class = 0; 31 32 protection = PROTpublic; 32 33 type = NULL; 33 34 handle = NULL; 34 35 structsize = 0; // size of struct 35 36 alignsize = 0; // size of struct for alignment purposes 36 37 structalign = 0; // struct member alignment in effect 37 38 hasUnions = 0; 38 39 sizeok = 0; // size not determined yet 39 40 isdeprecated = 0; 40 41 inv = NULL; 41 42 aggNew = NULL; 42 43 aggDelete = NULL; 43 44 44 45 stag = NULL; 45 46 sinit = NULL; 46 47 scope = NULL; 48 isnested = 0; 49 vthis = NULL; 50 47 51 #if V2 48 dtor = NULL;49 50 52 ctor = NULL; 51 53 defaultCtor = NULL; 52 54 #endif 55 dtor = NULL; 53 56 } 54 57 55 58 enum PROT AggregateDeclaration::prot() 56 59 { 57 60 return protection; 58 61 } 59 62 60 63 void AggregateDeclaration::semantic2(Scope *sc) 61 64 { 62 65 //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); 63 66 if (scope) 64 67 { error("has forward references"); 65 68 return; 66 69 } 67 70 if (members) 68 71 { 69 72 sc = sc->push(this); 70 73 for (size_t i = 0; i < members->dim; i++) 71 74 { 72 75 Dsymbol *s = (Dsymbol *)members->data[i]; … … 146 149 int sa = size; 147 150 if (sa == 0 || salign < sa) 148 151 sa = salign; 149 152 *poffset = (*poffset + sa - 1) & ~(sa - 1); 150 153 } 151 154 //printf("result = %d\n",offset); 152 155 } 153 156 154 157 155 158 void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) 156 159 { 157 160 unsigned memsize; // size of member 158 161 unsigned memalignsize; // size of member for alignment purposes 159 162 unsigned xalign; // alignment boundaries 160 163 161 164 //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); 162 165 assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls))); 163 166 164 167 // Check for forward referenced types which will fail the size() call 165 168 Type *t = v->type->toBasetype(); 169 if (v->storage_class & STCref) 170 { // References are the size of a pointer 171 t = Type::tvoidptr; 172 } 166 173 if (t->ty == Tstruct /*&& isStructDeclaration()*/) 167 174 { TypeStruct *ts = (TypeStruct *)t; 168 175 #if V2 169 176 if (ts->sym == this) 170 177 { 171 178 error("cannot have field %s with same struct type", v->toChars()); 172 179 } 173 180 #endif 174 181 175 182 if (ts->sym->sizeok != 1) 176 183 { 177 184 sizeok = 2; // cannot finish; flag as forward referenced 178 185 return; 179 186 } 180 187 } 181 188 if (t->ty == Tident) 182 189 { 183 190 sizeok = 2; // cannot finish; flag as forward referenced 184 191 return; 185 192 } 186 193 187 memsize = v->type->size(loc);188 memalignsize = v->type->alignsize();189 xalign = v->type->memalign(sc->structalign);194 memsize = t->size(loc); 195 memalignsize = t->alignsize(); 196 xalign = t->memalign(sc->structalign); 190 197 alignmember(xalign, memalignsize, &sc->offset); 191 198 v->offset = sc->offset; 192 199 sc->offset += memsize; 193 200 if (sc->offset > structsize) 194 201 structsize = sc->offset; 195 202 if (sc->structalign < memalignsize) 196 203 memalignsize = sc->structalign; 197 204 if (alignsize < memalignsize) 198 205 alignsize = memalignsize; 199 206 //printf("\talignsize = %d\n", alignsize); 200 207 201 208 v->storage_class |= STCfield; 202 209 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); 203 210 fields.push(v); 211 } 212 213 214 /**************************************** 215 * Returns !=0 if there's an extra member which is the 'this' 216 * pointer to the enclosing context (enclosing aggregate or function) 217 */ 218 219 int AggregateDeclaration::isNested() 220 { 221 return isnested; 204 222 } 205 223 206 224 207 225 /********************************* StructDeclaration ****************************/ 208 226 209 227 StructDeclaration::StructDeclaration(Loc loc, Identifier *id) 210 228 : AggregateDeclaration(loc, id) 211 229 { 212 230 zeroInit = 0; // assume false until we do semantic processing 213 231 #if V2 214 232 hasIdentityAssign = 0; 215 233 cpctor = NULL; 216 234 postblit = NULL; 217 235 #endif 218 236 219 237 // For forward references 220 238 type = new TypeStruct(this); 221 239 } 222 240 223 241 Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) … … 264 282 #else 265 283 handle = type->pointerTo(); 266 284 #endif 267 285 structalign = sc->structalign; 268 286 protection = sc->protection; 269 287 storage_class |= sc->stc; 270 288 if (sc->stc & STCdeprecated) 271 289 isdeprecated = 1; 272 290 assert(!isAnonymous()); 273 291 if (sc->stc & STCabstract) 274 292 error("structs, unions cannot be abstract"); 275 293 #if V2 276 294 if (storage_class & STCinvariant) 277 295 type = type->invariantOf(); 278 296 else if (storage_class & STCconst) 279 297 type = type->constOf(); 280 298 #endif 281 299 282 300 if (sizeok == 0) // if not already done the addMember step 283 301 { 302 int hasfunctions = 0; 284 303 for (i = 0; i < members->dim; i++) 285 304 { 286 305 Dsymbol *s = (Dsymbol *)members->data[i]; 287 306 //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); 288 307 s->addMember(sc, this, 1); 289 } 308 if (s->isFuncDeclaration()) 309 hasfunctions = 1; 310 } 311 312 // If nested struct, add in hidden 'this' pointer to outer scope 313 if (hasfunctions && !(storage_class & STCstatic)) 314 { Dsymbol *s = toParent2(); 315 if (s) 316 { 317 AggregateDeclaration *ad = s->isAggregateDeclaration(); 318 FuncDeclaration *fd = s->isFuncDeclaration(); 319 320 TemplateInstance *ti; 321 if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd) 322 { isnested = 1; 323 Type *t; 324 if (ad) 325 t = ad->handle; 326 else if (fd) 327 { AggregateDeclaration *ad = fd->isMember2(); 328 if (ad) 329 t = ad->handle; 330 else 331 t = Type::tvoidptr; 332 } 333 else 334 assert(0); 335 if (t->ty == Tstruct) 336 t = Type::tvoidptr; // t should not be a ref type 337 assert(!vthis); 338 vthis = new ThisDeclaration(t); 339 //vthis->storage_class |= STCref; 340 members->push(vthis); 341 } 342 } 343 } 290 344 } 291 345 292 346 sizeok = 0; 293 347 sc2 = sc->push(this); 294 348 sc2->stc &= storage_class & (STCconst | STCinvariant); 295 349 sc2->parent = this; 296 350 if (isUnionDeclaration()) 297 351 sc2->inunion = 1; 298 352 sc2->protection = PROTpublic; 299 353 sc2->explicitProtection = 0; 300 354 301 355 int members_dim = members->dim; 302 356 for (i = 0; i < members_dim; i++) 303 357 { 304 358 Dsymbol *s = (Dsymbol *)members->data[i]; 305 359 s->semantic(sc2); 306 360 if (isUnionDeclaration()) 307 361 sc2->offset = 0; 308 362 #if 0 309 363 if (sizeok == 2) 310 364 { //printf("forward reference\n"); 311 365 break; 312 366 } 313 367 #endif 368 Type *t; 369 if (s->isDeclaration() && 370 (t = s->isDeclaration()->type) != NULL && 371 t->toBasetype()->ty == Tstruct) 372 { StructDeclaration *sd = (StructDeclaration *)t->toDsymbol(sc); 373 if (sd->isnested) 374 error("inner struct %s cannot be a field", sd->toChars()); 375 } 314 376 } 315 377 316 378 /* The TypeInfo_Struct is expecting an opEquals and opCmp with 317 379 * a parameter that is a pointer to the struct. But if there 318 380 * isn't one, but is an opEquals or opCmp with a value, write 319 381 * another that is a shell around the value: 320 382 * int opCmp(struct *p) { return opCmp(*p); } 321 383 */ 322 384 323 385 TypeFunction *tfeqptr; 324 386 { 325 387 Arguments *arguments = new Arguments; 326 388 Argument *arg = new Argument(STCin, handle, Id::p, NULL); 327 389 328 390 arguments->push(arg); 329 391 tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); 330 392 tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); 331 393 } 332 394 333 395 TypeFunction *tfeq; trunk/src/template.c
r181 r183 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-200 8by Digital Mars3 // Copyright (c) 1999-2009 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 // Handle template implementation 12 12 13 13 #include <stdio.h> 14 14 #include <assert.h> 15 15 16 16 #include "root.h" 17 #include " mem.h"17 #include "rmem.h" 18 18 #include "stringtable.h" 19 19 20 20 #include "mtype.h" 21 21 #include "template.h" 22 22 #include "init.h" 23 23 #include "expression.h" 24 24 #include "scope.h" 25 25 #include "module.h" 26 26 #include "aggregate.h" 27 27 #include "declaration.h" 28 28 #include "dsymbol.h" 29 29 #include "mars.h" 30 30 #include "dsymbol.h" 31 31 #include "identifier.h" 32 32 #include "hdrgen.h" 33 33 34 34 #if WINDOWS_SEH 35 35 #include <windows.h> 36 36 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); 37 37 #endif … … 169 169 { 170 170 printf("match %d\n", e1->equals(e2)); 171 171 e1->print(); 172 172 e2->print(); 173 173 e1->type->print(); 174 174 e2->type->print(); 175 175 } 176 176 #endif 177 177 if (!e2) 178 178 goto Lnomatch; 179 179 if (!e1->equals(e2)) 180 180 goto Lnomatch; 181 181 } 182 182 else if (s1) 183 183 { 184 184 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars()); 185 185 if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) 186 186 { 187 187 goto Lnomatch; 188 188 } 189 #if V2 189 190 VarDeclaration *v1 = s1->isVarDeclaration(); 190 191 VarDeclaration *v2 = s2->isVarDeclaration(); 191 192 if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest) 192 193 { ExpInitializer *ei1 = v1->init->isExpInitializer(); 193 194 ExpInitializer *ei2 = v2->init->isExpInitializer(); 194 195 if (ei1 && ei2 && !ei1->exp->equals(ei2->exp)) 195 196 goto Lnomatch; 196 197 } 198 #endif 197 199 } 198 200 else if (v1) 199 201 { 200 202 if (!v2) 201 203 goto Lnomatch; 202 204 if (v1->objects.dim != v2->objects.dim) 203 205 goto Lnomatch; 204 206 for (size_t i = 0; i < v1->objects.dim; i++) 205 207 { 206 208 if (!match((Object *)v1->objects.data[i], 207 209 (Object *)v2->objects.data[i], 208 210 tempdecl, sc)) 209 211 goto Lnomatch; 210 212 } 211 213 } 212 214 //printf("match\n"); 213 215 return 1; // match 214 216 Lnomatch: 215 217 //printf("nomatch\n"); 216 218 return 0; // nomatch; … … 244 246 { 245 247 if (i) 246 248 buf->writeByte(','); 247 249 Object *o = (Object *)args->data[i]; 248 250 ObjectToCBuffer(buf, hgs, o); 249 251 } 250 252 } 251 253 else if (!oarg) 252 254 { 253 255 buf->writestring("NULL"); 254 256 } 255 257 else 256 258 { 257 259 #ifdef DEBUG 258 260 printf("bad Object = %p\n", oarg); 259 261 #endif 260 262 assert(0); 261 263 } 262 264 } 263 265 266 #if V2 264 267 Object *objectSyntaxCopy(Object *o) 265 268 { 266 269 if (!o) 267 270 return NULL; 268 271 Type *t = isType(o); 269 272 if (t) 270 273 return t->syntaxCopy(); 271 274 Expression *e = isExpression(o); 272 275 if (e) 273 276 return e->syntaxCopy(); 274 277 return o; 275 278 } 279 #endif 276 280 277 281 278 282 /* ======================== TemplateDeclaration ============================= */ 279 283 280 284 TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, 281 285 TemplateParameters *parameters, Expression *constraint, Array *decldefs) 282 286 : ScopeDsymbol(id) 283 287 { 284 288 #if LOG 285 289 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars()); 286 290 #endif 287 291 #if 0 288 292 if (parameters) 289 293 for (int i = 0; i < parameters->dim; i++) 290 294 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; 291 295 //printf("\tparameter[%d] = %p\n", i, tp); 292 296 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); 293 297 294 298 if (ttp) 295 299 { 296 300 printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); 297 301 } 298 302 } 299 303 #endif 300 304 this->loc = loc; 301 305 this->parameters = parameters; 302 306 this->origParameters = parameters; 307 #if V2 303 308 this->constraint = constraint; 309 #endif 304 310 this->members = decldefs; 305 311 this->overnext = NULL; 306 312 this->overroot = NULL; 307 313 this->scope = NULL; 308 314 this->onemember = NULL; 309 315 } 310 316 311 317 Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) 312 318 { 313 319 //printf("TemplateDeclaration::syntaxCopy()\n"); 314 320 TemplateDeclaration *td; 315 321 TemplateParameters *p; 316 322 Array *d; 317 323 318 324 p = NULL; 319 325 if (parameters) 320 326 { 321 327 p = new TemplateParameters(); 322 328 p->setDim(parameters->dim); 323 329 for (int i = 0; i < p->dim; i++) 324 330 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; 325 331 p->data[i] = (void *)tp->syntaxCopy(); 326 332 } 327 333 } 334 #if V2 328 335 Expression *e = NULL; 329 336 if (constraint) 330 337 e = constraint->syntaxCopy(); 338 #endif 331 339 d = Dsymbol::arraySyntaxCopy(members); 332 340 td = new TemplateDeclaration(loc, ident, p, e, d); 333 341 return td; 334 342 } 335 343 336 344 void TemplateDeclaration::semantic(Scope *sc) 337 345 { 338 346 #if LOG 339 347 printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars()); 340 348 #endif 341 349 if (scope) 342 350 return; // semantic() already run 343 351 344 352 if (sc->func) 345 353 { 346 354 #if V1 347 355 error("cannot declare template at function scope %s", sc->func->toChars()); 348 356 #endif 349 357 } 350 358 … … 356 364 } 357 365 358 366 if (/*global.params.useAssert &&*/ sc->module) 359 367 { 360 368 // Generate this function as it may be used 361 369 // when template is instantiated in other modules 362 370 sc->module->toModuleAssert(); 363 371 } 364 372 365 373 /* Remember Scope for later instantiations, but make 366 374 * a copy since attributes can change. 367 375 */ 368 376 this->scope = new Scope(*sc); 369 377 this->scope->setNoFree(); 370 378 371 379 // Set up scope for parameters 372 380 ScopeDsymbol *paramsym = new ScopeDsymbol(); 373 381 paramsym->parent = sc->parent; 374 382 Scope *paramscope = sc->push(paramsym); 375 383 paramscope->parameterSpecialization = 1; 384 paramscope->stc = 0; 376 385 377 386 if (global.params.doDocComments) 378 387 { 379 388 origParameters = new TemplateParameters(); 380 389 origParameters->setDim(parameters->dim); 381 390 for (int i = 0; i < parameters->dim; i++) 382 391 { 383 392 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; 384 393 origParameters->data[i] = (void *)tp->syntaxCopy(); 385 394 } 386 395 } 387 396 388 397 for (int i = 0; i < parameters->dim; i++) 389 398 { 390 399 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; 391 400 392 401 tp->declareParameter(paramscope); 393 402 } 394 403 395 404 for (int i = 0; i < parameters->dim; i++) … … 516 525 int parameters_dim = parameters->dim; 517 526 int variadic = isVariadic() != NULL; 518 527 519 528 // If more arguments than parameters, no match 520 529 if (ti->tiargs->dim > parameters_dim && !variadic) 521 530 { 522 531 #if LOGM 523 532 printf(" no match: more arguments than parameters\n"); 524 533 #endif 525 534 return MATCHnomatch; 526 535 } 527 536 528 537 assert(dedtypes_dim == parameters_dim); 529 538 assert(dedtypes_dim >= ti->tiargs->dim || variadic); 530 539 531 540 // Set up scope for parameters 532 541 assert((size_t)scope > 0x10000); 533 542 ScopeDsymbol *paramsym = new ScopeDsymbol(); 534 543 paramsym->parent = scope->parent; 535 544 Scope *paramscope = scope->push(paramsym); 545 paramscope->stc = 0; 536 546 537 547 // Attempt type deduction 538 548 m = MATCHexact; 539 549 for (int i = 0; i < dedtypes_dim; i++) 540 550 { MATCH m2; 541 551 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; 542 552 Declaration *sparam; 543 553 544 554 //printf("\targument [%d]\n", i); 545 555 #if LOGM 546 556 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); 547 557 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); 548 558 if (ttp) 549 559 printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : ""); 550 560 #endif 551 561 552 562 #if V1 553 563 m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam); 554 564 #else 555 565 m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0); … … 805 815 806 816 assert(fd->type->ty == Tfunction); 807 817 fdtype = (TypeFunction *)fd->type; 808 818 809 819 nfparams = Argument::dim(fdtype->parameters); // number of function parameters 810 820 nfargs = fargs->dim; // number of function arguments 811 821 812 822 /* Check for match of function arguments with variadic template 813 823 * parameter, such as: 814 824 * 815 825 * template Foo(T, A...) { void Foo(T t, A a); } 816 826 * void main() { Foo(1,2,3); } 817 827 */ 818 828 if (tp) // if variadic 819 829 { 820 830 if (nfparams == 0) // if no function parameters 821 831 { 822 832 Tuple *t = new Tuple(); 823 833 //printf("t = %p\n", t); 824 834 dedargs->data[parameters->dim - 1] = (void *)t; 835 declareParameter(paramscope, tp, t); 825 836 goto L2; 826 837 } 827 838 else if (nfargs < nfparams - 1) 828 839 goto L1; 829 840 else 830 841 { 831 842 /* Figure out which of the function parameters matches 832 843 * the tuple template parameter. Do this by matching 833 844 * type identifiers. 834 845 * Set the index of this function parameter to fptupindex. 835 846 */ 836 847 for (fptupindex = 0; fptupindex < nfparams; fptupindex++) 837 848 { 838 849 Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex]; 839 850 if (fparam->type->ty != Tident) 840 851 continue; 841 852 TypeIdentifier *tid = (TypeIdentifier *)fparam->type; 842 853 if (!tp->ident->equals(tid->ident) || tid->idents.dim) 843 854 continue; 844 855 845 856 if (fdtype->varargs) // variadic function doesn't 846 857 goto Lnomatch; // go with variadic template 847 858 848 859 /* The types of the function arguments 849 860 * now form the tuple argument. 850 861 */ 851 862 Tuple *t = new Tuple(); 852 863 dedargs->data[parameters->dim - 1] = (void *)t; 853 864 854 865 tuple_dim = nfargs - (nfparams - 1); 855 866 t->objects.setDim(tuple_dim); 856 867 for (i = 0; i < tuple_dim; i++) 857 868 { Expression *farg = (Expression *)fargs->data[fptupindex + i]; 858 869 t->objects.data[i] = (void *)farg->type; 859 870 } 871 declareParameter(paramscope, tp, t); 860 872 goto L2; 861 873 } 862 874 fptupindex = -1; 863 875 } 864 876 } 865 877 866 878 L1: 867 879 if (nfparams == nfargs) 868 880 ; 869 881 else if (nfargs > nfparams) 870 882 { 871 883 if (fdtype->varargs == 0) 872 884 goto Lnomatch; // too many args, no match 873 885 match = MATCHconvert; // match ... with a conversion 874 886 } 875 887 876 888 L2: 877 889 #if V2 878 890 // Match 'ethis' to any TemplateThisParameter's 879 891 if (ethis) … … 1868 1880 else if (tempinst->tempdecl != tp->tempinst->tempdecl) 1869 1881 goto Lnomatch; 1870 1882 1871 1883 L2: 1872 1884 if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) 1873 1885 goto Lnomatch; 1874 1886 1875 1887 for (int i = 0; i < tempinst->tiargs->dim; i++) 1876 1888 { 1877 1889 //printf("\ttest: tempinst->tiargs[%d]\n", i); 1878 1890 int j; 1879 1891 Object *o1 = (Object *)tempinst->tiargs->data[i]; 1880 1892 Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; 1881 1893 1882 1894 Type *t1 = isType(o1); 1883 1895 Type *t2 = isType(o2); 1884 1896 1885 1897 Expression *e1 = isExpression(o1); 1886 1898 Expression *e2 = isExpression(o2); 1887 1899 1900 Dsymbol *s1 = isDsymbol(o1); 1901 Dsymbol *s2 = isDsymbol(o2); 1902 1903 Tuple *v1 = isTuple(o1); 1904 Tuple *v2 = isTuple(o2); 1888 1905 #if 0 1889 1906 if (t1) printf("t1 = %s\n", t1->toChars()); 1890 1907 if (t2) printf("t2 = %s\n", t2->toChars()); 1891 1908 if (e1) printf("e1 = %s\n", e1->toChars()); 1892 1909 if (e2) printf("e2 = %s\n", e2->toChars()); 1910 if (s1) printf("s1 = %s\n", s1->toChars()); 1911 if (s2) printf("s2 = %s\n", s2->toChars()); 1912 if (v1) printf("v1 = %s\n", v1->toChars()); 1913 if (v2) printf("v2 = %s\n", v2->toChars()); 1893 1914 #endif 1894 1915 1895 1916 if (t1 && t2) 1896 1917 { 1897 1918 if (!t1->deduceType(sc, t2, parameters, dedtypes)) 1898 1919 goto Lnomatch; 1899 1920 } 1900 1921 else if (e1 && e2) 1901 1922 { 1902 1923 if (!e1->equals(e2)) 1903 1924 { if (e2->op == TOKvar) 1904 1925 { 1905 1926 /* 1906 1927 * (T:Number!(e2), int e2) 1907 1928 */ 1908 1929 j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters); 1909 1930 goto L1; 1910 1931 } 1911 1932 goto Lnomatch; 1912 1933 } … … 1919 1940 goto Lnomatch; 1920 1941 TemplateParameter *tp = (TemplateParameter *)parameters->data[j]; 1921 1942 // BUG: use tp->matchArg() instead of the following 1922 1943 TemplateValueParameter *tv = tp->isTemplateValueParameter(); 1923 1944 if (!tv) 1924 1945 goto Lnomatch; 1925 1946 Expression *e = (Expression *)dedtypes->data[j]; 1926 1947 if (e) 1927 1948 { 1928 1949 if (!e1->equals(e)) 1929 1950 goto Lnomatch; 1930 1951 } 1931 1952 else 1932 1953 { Type *vt = tv->valType->semantic(0, sc); 1933 1954 MATCH m = (MATCH)e1->implicitConvTo(vt); 1934 1955 if (!m) 1935 1956 goto Lnomatch; 1936 1957 dedtypes->data[j] = e1; 1937 1958 } 1938 1959 } 1939 // BUG: Need to handle alias and tuple parameters 1960 else if (s1 && t2 && t2->ty == Tident) 1961 { 1962 j = templateParameterLookup(t2, parameters); 1963 if (j == -1) 1964 goto Lnomatch; 1965 TemplateParameter *tp = (TemplateParameter *)parameters->data[j]; 1966 // BUG: use tp->matchArg() instead of the following 1967 TemplateAliasParameter *ta = tp->isTemplateAliasParameter(); 1968 if (!ta) 1969 goto Lnomatch; 1970 Dsymbol *s = (Dsymbol *)dedtypes->data[j]; 1971 if (s) 1972 { 1973 if (!s1->equals(s)) 1974 goto Lnomatch; 1975 } 1976 else 1977 { 1978 dedtypes->data[j] = s1; 1979 } 1980 } 1981 else if (s1 && s2) 1982 { 1983 if (!s1->equals(s2)) 1984 goto Lnomatch; 1985 } 1986 // BUG: Need to handle tuple parameters 1940 1987 else 1941 1988 goto Lnomatch; 1942 1989 } 1943 1990 } 1944 1991 return Type::deduceType(sc, tparam, parameters, dedtypes); 1945 1992 1946 1993 Lnomatch: 1947 1994 return MATCHnomatch; 1948 1995 } 1949 1996 1950 1997 MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) 1951 1998 { 1952 1999 //printf("TypeStruct::deduceType()\n"); 1953 2000 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print(); 1954 2001 //printf("\ttparam = %d, ", tparam->ty); tparam->print(); 1955 2002 1956 2003 /* If this struct is a template struct, and we're matching 1957 2004 * it against a template instance, convert the struct type 1958 2005 * to a template instance, too, and try again. 1959 2006 */ … … 2553 2600 dedtypes->data[i] = sa; 2554 2601 2555 2602 s = isDsymbol(sa); 2556 2603 if (s) 2557 2604 *psparam = new AliasDeclaration(loc, ident, s); 2558 2605 else 2559 2606 { 2560 2607 assert(ea); 2561 2608 2562 2609 // Declare manifest constant 2563 2610 Initializer *init = new ExpInitializer(loc, ea); 2564 2611 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init); 2565 2612 v->storage_class = STCmanifest; 2566 2613 v->semantic(sc); 2567 2614 *psparam = v; 2568 2615 } 2569 2616 return MATCHexact; 2570 2617 2571 2618 Lnomatch: 2572 2619 *psparam = NULL; 2620 //printf("\tm = %d\n", MATCHnomatch); 2573 2621 return MATCHnomatch; 2574 2622 } 2575 2623 2576 2624 2577 2625 void TemplateAliasParameter::print(Object *oarg, Object *oded) 2578 2626 { 2579 2627 printf(" %s\n", ident->toChars()); 2580 2628 2581 2629 Dsymbol *sa = isDsymbol(oded); 2582 2630 assert(sa); 2583 2631 2584 2632 printf("\tArgument alias: %s\n", sa->toChars()); 2585 2633 } 2586 2634 2587 2635 void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2588 2636 { 2589 2637 buf->writestring("alias "); 2590 2638 if (specType) 2591 2639 { HdrGenState hgs; 2592 2640 specType->toCBuffer(buf, ident, &hgs); … … 3155 3203 return; 3156 3204 } 3157 3205 } 3158 3206 else 3159 3207 { 3160 3208 /* Run semantic on each argument, place results in tiargs[] 3161 3209 * (if we havetempdecl, then tiargs is already evaluated) 3162 3210 */ 3163 3211 semanticTiargs(sc); 3164 3212 3165 3213 tempdecl = findTemplateDeclaration(sc); 3166 3214 if (tempdecl) 3167 3215 tempdecl = findBestMatch(sc); 3168 3216 if (!tempdecl || global.errors) 3169 3217 { inst = this; 3170 3218 //printf("error return %p, %d\n", tempdecl, global.errors); 3171 3219 return; // error recovery 3172 3220 } 3173 3221 } 3174 3222 3175 isNested(tiargs);3223 hasNestedArgs(tiargs); 3176 3224 3177 3225 /* See if there is an existing TemplateInstantiation that already 3178 3226 * implements the typeargs. If so, just refer to that one instead. 3179 3227 */ 3180 3228 3181 3229 for (size_t i = 0; i < tempdecl->instances.dim; i++) 3182 3230 { 3183 3231 TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i]; 3184 3232 #if LOG 3185 3233 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars()); 3186 3234 #endif 3187 3235 assert(tdtypes.dim == ti->tdtypes.dim); 3188 3236 3189 3237 // Nesting must match 3190 3238 if (isnested != ti->isnested) 3191 3239 continue; 3192 3240 #if 0 3193 3241 if (isnested && sc->parent != ti->parent) 3194 3242 continue; 3195 3243 #endif … … 3238 3286 int dosemantic3 = 0; 3239 3287 { Array *a; 3240 3288 3241 3289 Scope *scx = sc; 3242 3290 #if 0 3243 3291 for (scx = sc; scx; scx = scx->enclosing) 3244 3292 if (scx->scopesym) 3245 3293 break; 3246 3294 #endif 3247 3295 3248 3296 //if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars()); 3249 3297 if (scx && scx->scopesym && 3250 3298 scx->scopesym->members && !scx->scopesym->isTemplateMixin() 3251 3299 #if 0 // removed because it bloated compile times 3252 3300 /* The problem is if A imports B, and B imports A, and both A 3253 3301 * and B instantiate the same template, does the compilation of A 3254 3302 * or the compilation of B do the actual instantiation? 3255 3303 * 3256 3304 * see bugzilla 2500. 3257 3305 */ 3258 && !scx->module-> imports(scx->module)3306 && !scx->module->selfImports() 3259 3307 #endif 3260 3308 ) 3261 3309 { 3262 3310 //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars()); 3263 3311 a = scx->scopesym->members; 3264 3312 } 3265 3313 else 3266 3314 { Module *m = sc->module->importedFrom; 3267 3315 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); 3268 3316 a = m->members; 3269 3317 if (m->semanticdone >= 3) 3270 3318 dosemantic3 = 1; 3271 3319 } 3272 3320 for (int i = 0; 1; i++) 3273 3321 { 3274 3322 if (i == a->dim) 3275 3323 { 3276 3324 a->push(this); 3277 3325 break; 3278 3326 } … … 3282 3330 } 3283 3331 #endif 3284 3332 3285 3333 // Copy the syntax trees from the TemplateDeclaration 3286 3334 members = Dsymbol::arraySyntaxCopy(tempdecl->members); 3287 3335 3288 3336 // Create our own scope for the template parameters 3289 3337 Scope *scope = tempdecl->scope; 3290 3338 if (!scope) 3291 3339 { 3292 3340 error("forward reference to template declaration %s\n", tempdecl->toChars()); 3293 3341 return; 3294 3342 } 3295 3343 3296 3344 #if LOG 3297 3345 printf("\tcreate scope for template parameters '%s'\n", toChars()); 3298 3346 #endif 3299 3347 argsym = new ScopeDsymbol(); 3300 3348 argsym->parent = scope->parent; 3301 3349 scope = scope->push(argsym); 3350 // scope->stc = 0; 3302 3351 3303 3352 // Declare each template parameter as an alias for the argument type 3304 declareParameters(scope); 3353 Scope *paramscope = scope->push(); 3354 paramscope->stc = 0; 3355 declareParameters(paramscope); 3356 paramscope->pop(); 3305 3357 3306 3358 // Add members of template instance to template instance symbol table 3307 3359 // parent = scope->scopesym; 3308 3360 symtab = new DsymbolTable(); 3309 3361 int memnum = 0; 3310 3362 for (int i = 0; i < members->dim; i++) 3311 3363 { 3312 3364 Dsymbol *s = (Dsymbol *)members->data[i]; 3313 3365 #if LOG 3314 3366 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum); 3315 3367 #endif 3316 3368 memnum |= s->addMember(scope, this, memnum); 3317 3369 } 3318 3370 #if LOG 3319 3371 printf("adding members done\n"); 3320 3372 #endif 3321 3373 3322 3374 /* See if there is only one member of template instance, and that 3323 3375 * member has the same name as the template instance. 3324 3376 * If so, this template instance becomes an alias for that member. … … 3754 3806 assert(ea); 3755 3807 ea = ea->castTo(tvp->valType); 3756 3808 ea = ea->optimize(WANTvalue | WANTinterpret); 3757 3809 tiargs->data[i] = (Object *)ea; 3758 3810 } 3759 3811 } 3760 3812 #endif 3761 3813 3762 3814 #if LOG 3763 3815 printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars()); 3764 3816 #endif 3765 3817 return tempdecl; 3766 3818 } 3767 3819 3768 3820 3769 3821 /***************************************** 3770 3822 * Determines if a TemplateInstance will need a nested 3771 3823 * generation of the TemplateDeclaration. 3772 3824 */ 3773 3825 3774 int TemplateInstance:: isNested(Objects *args)3826 int TemplateInstance::hasNestedArgs(Objects *args) 3775 3827 { int nested = 0; 3776 //printf("TemplateInstance:: isNested('%s')\n", tempdecl->ident->toChars());3828 //printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars()); 3777 3829 3778 3830 /* A nested instance happens when an argument references a local 3779 3831 * symbol that is on the stack. 3780 3832 */ 3781 3833 for (size_t i = 0; i < args->dim; i++) 3782 3834 { Object *o = (Object *)args->data[i]; 3783 3835 Expression *ea = isExpression(o); 3784 3836 Dsymbol *sa = isDsymbol(o); 3785 3837 Tuple *va = isTuple(o); 3786 3838 if (ea) 3787 3839 { 3788 3840 if (ea->op == TOKvar) 3789 3841 { 3790 3842 sa = ((VarExp *)ea)->var; 3791 3843 goto Lsa; 3792 3844 } 3793 3845 if (ea->op == TOKfunction) 3794 3846 { 3795 3847 sa = ((FuncExp *)ea)->fd; 3796 3848 goto Lsa; … … 3825 3877 for (Dsymbol *p = dparent; p; p = p->parent) 3826 3878 { 3827 3879 if (p == isnested) 3828 3880 { isnested = dparent; 3829 3881 goto L1; // dparent is most nested 3830 3882 } 3831 3883 } 3832 3884 error("%s is nested in both %s and %s", 3833 3885 toChars(), isnested->toChars(), dparent->toChars()); 3834 3886 } 3835 3887 L1: 3836 3888 //printf("\tnested inside %s\n", isnested->toChars()); 3837 3889 nested |= 1; 3838 3890 } 3839 3891 else 3840 3892 error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars()); 3841 3893 } 3842 3894 } 3843 3895 else if (va) 3844 3896 { 3845 nested |= isNested(&va->objects);3897 nested |= hasNestedArgs(&va->objects); 3846 3898 } 3847 3899 } 3848 3900 return nested; 3849 3901 } 3850 3902 3851 3903 /**************************************** 3852 3904 * This instance needs an identifier for name mangling purposes. 3853 3905 * Create one by taking the template declaration name and adding 3854 3906 * the type signature for it. 3855 3907 */ 3856 3908 3857 3909 Identifier *TemplateInstance::genIdent() 3858 3910 { OutBuffer buf; 3859 3911 char *id; 3860 3912 Objects *args; 3861 3913 3862 3914 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); 3863 3915 id = tempdecl->ident->toChars(); 3864 3916 buf.printf("__T%zu%s", strlen(id), id); 3865 3917 args = tiargs; trunk/src/template.h
r174 r183 34 34 struct Scope; 35 35 struct Expression; 36 36 struct AliasDeclaration; 37 37 struct FuncDeclaration; 38 38 struct HdrGenState; 39 39 enum MATCH; 40 40 41 41 struct Tuple : Object 42 42 { 43 43 Objects objects; 44 44 45 45 int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType() 46 46 }; 47 47 48 48 49 49 struct TemplateDeclaration : ScopeDsymbol 50 50 { 51 51 TemplateParameters *parameters; // array of TemplateParameter's 52 52 53 53 TemplateParameters *origParameters; // originals for Ddoc 54 54 #if V2 55 55 Expression *constraint; 56 56 #endif 57 57 Array instances; // array of TemplateInstance's 58 58 59 59 TemplateDeclaration *overnext; // next overloaded TemplateDeclaration 60 60 TemplateDeclaration *overroot; // first in overnext list 61 61 62 62 Scope *scope; 63 63 Dsymbol *onemember; // if !=NULL then one member of this template 64 64 65 65 TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, 66 Expression *constraint, Array *decldefs); 66 #if V2 67 Expression *constraint, 68 #endif 69 Array *decldefs); 67 70 Dsymbol *syntaxCopy(Dsymbol *); 68 71 void semantic(Scope *sc); 69 72 int overloadInsert(Dsymbol *s); 70 73 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 71 74 const char *kind(); 72 75 char *toChars(); 73 76 74 77 void emitComment(Scope *sc); 75 78 // void toDocBuffer(OutBuffer *buf); 76 79 77 80 MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag); 78 81 MATCH leastAsSpecialized(TemplateDeclaration *td2); 79 82 80 83 MATCH deduceFunctionTemplateMatch(Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs); 81 84 FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0); 82 85 void declareParameter(Scope *sc, TemplateParameter *tp, Object *o); 83 86 84 87 TemplateDeclaration *isTemplateDeclaration() { return this; } 85 88 86 89 TemplateTupleParameter *isVariadic(); … … 94 97 * template Foo(ident : specType) 95 98 * For value-parameter: 96 99 * template Foo(valType ident) // specValue is set to NULL 97 100 * template Foo(valType ident : specValue) 98 101 * For alias-parameter: 99 102 * template Foo(alias ident) 100 103 * For this-parameter: 101 104 * template Foo(this ident) 102 105 */ 103 106 104 107 Loc loc; 105 108 Identifier *ident; 106 109 107 110 Declaration *sparam; 108 111 109 112 TemplateParameter(Loc loc, Identifier *ident); 110 113 111 114 virtual TemplateTypeParameter *isTemplateTypeParameter(); 112 115 virtual TemplateValueParameter *isTemplateValueParameter(); 113 116 virtual TemplateAliasParameter *isTemplateAliasParameter(); 117 #if V2 114 118 virtual TemplateThisParameter *isTemplateThisParameter(); 119 #endif 115 120 virtual TemplateTupleParameter *isTemplateTupleParameter(); 116 121 117 122 virtual TemplateParameter *syntaxCopy() = 0; 118 123 virtual void declareParameter(Scope *sc) = 0; 119 124 virtual void semantic(Scope *) = 0; 120 125 virtual void print(Object *oarg, Object *oded) = 0; 121 126 virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; 122 127 virtual Object *specialization() = 0; 123 128 virtual Object *defaultArg(Loc loc, Scope *sc) = 0; 124 129 125 130 /* If TemplateParameter's match as far as overloading goes. 126 131 */ 127 132 virtual int overloadMatch(TemplateParameter *) = 0; 128 133 129 134 /* Match actual argument against parameter. 130 135 */ 131 136 virtual MATCH matchArg(Scope *sc, Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0; 132 137 133 138 /* Create dummy argument based on parameter. 134 139 */ … … 291 296 Dsymbol *syntaxCopy(Dsymbol *); 292 297 void semantic(Scope *sc); 293 298 void semantic2(Scope *sc); 294 299 void semantic3(Scope *sc); 295 300 void inlineScan(); 296 301 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 297 302 Dsymbol *toAlias(); // resolve real symbol 298 303 const char *kind(); 299 304 int oneMember(Dsymbol **ps); 300 305 char *toChars(); 301 306 char *mangle(); 302 307 303 308 void toObjFile(int multiobj); // compile to .obj file 304 309 305 310 // Internal 306 311 static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); 307 312 void semanticTiargs(Scope *sc); 308 313 TemplateDeclaration *findTemplateDeclaration(Scope *sc); 309 314 TemplateDeclaration *findBestMatch(Scope *sc); 310 315 void declareParameters(Scope *sc); 311 int isNested(Objects *tiargs);316 int hasNestedArgs(Objects *tiargs); 312 317 Identifier *genIdent(); 313 318 314 319 TemplateInstance *isTemplateInstance() { return this; } 315 320 AliasDeclaration *isAliasDeclaration(); 316 321 }; 317 322 318 323 struct TemplateMixin : TemplateInstance 319 324 { 320 325 Array *idents; 321 326 Type *tqual; 322 327 323 328 Scope *scope; // for forward referencing 324 329 325 330 TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs); 326 331 Dsymbol *syntaxCopy(Dsymbol *s); 327 332 void semantic(Scope *sc); 328 333 void semantic2(Scope *sc); 329 334 void semantic3(Scope *sc); 330 335 void inlineScan(); 331 336 const char *kind(); trunk/src/tocsym.c
r182 r183 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stddef.h> 13 13 #include <time.h> 14 14 #include <assert.h> 15 15 16 16 #include "mars.h" 17 17 #include "module.h" 18 18 #include "mtype.h" 19 19 #include "declaration.h" 20 20 #include "statement.h" 21 21 #include "enum.h" 22 22 #include "aggregate.h" 23 23 #include "init.h" 24 24 #include "attrib.h" 25 25 #include "lexer.h" 26 26 #include "dsymbol.h" 27 27 #include "id.h" 28 28 29 #include <mem.h>29 #include "rmem.h" 30 30 31 31 // Back end 32 32 #include "cc.h" 33 33 #include "global.h" 34 34 #include "oper.h" 35 35 #include "code.h" 36 36 #include "type.h" 37 37 #include "dt.h" 38 38 #include "cgcv.h" 39 39 #include "outbuf.h" 40 40 #include "irstate.h" 41 41 42 42 void slist_add(Symbol *s); 43 43 void slist_reset(); 44 44 45 45 Classsym *fake_classsym(Identifier *id); 46 46 47 47 /********************************* SymbolDeclaration ****************************/ 48 48 49 49 SymbolDeclaration::SymbolDeclaration(Loc loc, Symbol *s, StructDeclaration *dsym) trunk/src/todt.c
r182 r183 875 875 876 876 if (offset < structsize) 877 877 dtnzeros(pdt, structsize - offset); 878 878 879 879 #undef LOG 880 880 } 881 881 882 882 void StructDeclaration::toDt(dt_t **pdt) 883 883 { 884 884 unsigned offset; 885 885 unsigned i; 886 886 dt_t *dt; 887 887 888 888 //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); 889 889 offset = 0; 890 890 891 891 // Note equivalence of this loop to class's 892 892 for (i = 0; i < fields.dim; i++) 893 893 { 894 894 VarDeclaration *v = (VarDeclaration *)fields.data[i]; 895 Initializer *init;896 897 895 //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); 898 896 dt = NULL; 899 init = v->init; 900 if (init) 901 { //printf("\t\thas initializer %s\n", init->toChars()); 902 ExpInitializer *ei = init->isExpInitializer(); 903 Type *tb = v->type->toBasetype(); 904 if (ei && tb->ty == Tsarray) 905 ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); 906 else 907 dt = init->toDt(); 908 } 909 else if (v->offset >= offset) 910 v->type->toDt(&dt); 897 int sz; 898 899 if (v->storage_class & STCref) 900 { 901 sz = PTRSIZE; 902 if (v->offset >= offset) 903 dtnzeros(&dt, sz); 904 } 905 else 906 { 907 sz = v->type->size(); 908 Initializer *init = v->init; 909 if (init) 910 { //printf("\t\thas initializer %s\n", init->toChars()); 911 ExpInitializer *ei = init->isExpInitializer(); 912 Type *tb = v->type->toBasetype(); 913 if (ei && tb->ty == Tsarray) 914 ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); 915 else 916 dt = init->toDt(); 917 } 918 else if (v->offset >= offset) 919 v->type->toDt(&dt); 920 } 911 921 if (dt) 912 922 { 913 923 if (v->offset < offset) 914 924 error("overlapping initialization for struct %s.%s", toChars(), v->toChars()); 915 925 else 916 926 { 917 927 if (offset < v->offset) 918 928 dtnzeros(pdt, v->offset - offset); 919 929 dtcat(pdt, dt); 920 offset = v->offset + v->type->size();930 offset = v->offset + sz; 921 931 } 922 932 } 923 933 } 924 934 925 935 if (offset < structsize) 926 936 dtnzeros(pdt, structsize - offset); 927 937 928 938 dt_optimize(*pdt); 929 939 } 930 940 931 941 /* ================================================================= */ 932 942 933 943 dt_t **Type::toDt(dt_t **pdt) 934 944 { 935 945 //printf("Type::toDt()\n"); 936 946 Expression *e = defaultInit(); 937 947 return e->toDt(pdt); 938 948 } 939 949 940 950 dt_t **TypeSArray::toDt(dt_t **pdt) trunk/src/toir.c
r182 r183 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <time.h> 18 18 #include <complex.h> 19 19 20 20 #include "lexer.h" 21 21 #include "expression.h" 22 22 #include "mtype.h" 23 23 #include "dsymbol.h" 24 24 #include "declaration.h" 25 25 #include "enum.h" 26 26 #include "aggregate.h" 27 27 #include "attrib.h" 28 28 #include "module.h" 29 29 #include "init.h" 30 30 #include "template.h" 31 31 32 32 #if _WIN32 33 33 #include "..\tk\mem.h" // for mem_malloc 34 #el if linux || __APPLE__34 #else 35 35 #include "../tk/mem.h" // for mem_malloc 36 36 #endif 37 37 38 38 #include "cc.h" 39 39 #include "el.h" 40 40 #include "oper.h" 41 41 #include "global.h" 42 42 #include "code.h" 43 43 #include "type.h" 44 44 #include "dt.h" 45 45 #include "irstate.h" 46 46 #include "id.h" 47 47 #include "type.h" 48 48 #include "toir.h" 49 49 50 50 static char __file__[] = __FILE__; /* for tassert.h */ 51 51 #include "tassert.h" 52 52 53 53 /********************************************* 54 54 * Produce elem which increments the usage count for a particular line. … … 170 170 */ 171 171 if (fdparent == s->toParent2()) 172 172 break; 173 173 if (thisfd->isNested()) 174 174 { 175 175 FuncDeclaration *p = s->toParent2()->isFuncDeclaration(); 176 176 #if V2 177 177 if (!p || p->closureVars.dim) 178 178 #else 179 179 if (!p || p->nestedFrameRef) 180 180 #endif 181 181 ethis = el_una(OPind, TYnptr, ethis); 182 182 } 183 183 else if (thisfd->vthis) 184 184 { 185 185 } 186 186 else 187 187 assert(0); 188 188 } 189 189 else 190 { /* Enclosed by a class. That means the current191 * function must be a member function of that class.190 { /* Enclosed by an aggregate. That means the current 191 * function must be a member function of that aggregate. 192 192 */ 193 ClassDeclaration *cd = s->isClassDeclaration(); 194 if (!cd) 193 ClassDeclaration *cd; 194 StructDeclaration *sd; 195 AggregateDeclaration *ad = s->isAggregateDeclaration(); 196 if (!ad) 195 197 goto Lnoframe; 196 if (//cd->baseClass == fd ||197 fd->isClassDeclaration() &&198 cd = s->isClassDeclaration(); 199 if (cd && fd->isClassDeclaration() && 198 200 fd->isClassDeclaration()->isBaseOf(cd, NULL)) 199 201 break; 200 if (!cd->isNested() || !cd->vthis) 202 sd = s->isStructDeclaration(); 203 if (fd == sd) 204 break; 205 if (!ad->isNested() || !ad->vthis) 201 206 { 202 207 Lnoframe: 203 208 irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars()); 204 209 return el_long(TYnptr, 0); // error recovery 205 210 } 206 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, cd->vthis->offset));211 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, ad->vthis->offset)); 207 212 ethis = el_una(OPind, TYnptr, ethis); 208 213 if (fdparent == s->toParent2()) 209 214 break; 210 215 if (fd == s->toParent2()) 211 216 { 212 217 /* Remember that frames for functions that have no 213 218 * nested references are skipped in the linked list 214 219 * of frames. 215 220 */ 216 221 #if V2 217 222 if (s->toParent2()->isFuncDeclaration()->closureVars.dim) 218 223 #else 219 224 if (s->toParent2()->isFuncDeclaration()->nestedFrameRef) 220 225 #endif 221 226 ethis = el_una(OPind, TYnptr, ethis); 222 227 break; 223 228 } 224 229 if (s->toParent2()->isFuncDeclaration()) 225 230 { 226 231 /* Remember that frames for functions that have no … … 232 237 #else 233 238 if (s->toParent2()->isFuncDeclaration()->nestedFrameRef) 234 239 #endif 235 240 ethis = el_una(OPind, TYnptr, ethis); 236 241 } 237 242 } 238 243 s = s->toParent2(); 239 244 assert(s); 240 245 } 241 246 } 242 247 } 243 248 #if 0 244 249 printf("ethis:\n"); 245 250 elem_print(ethis); 246 251 printf("\n"); 247 252 #endif 248 253 return ethis; 249 254 } 250 255 251 256 257 /************************* 258 * Initialize the hidden aggregate member, vthis, with 259 * the context pointer. 260 * Returns: 261 * *(ey + ad.vthis.offset) = this; 262 */ 263 elem *setEthis(Loc loc, IRState *irs, elem *ey, AggregateDeclaration *ad) 264 { 265 elem *ethis; 266 FuncDeclaration *thisfd = irs->getFunc(); 267 int offset = 0; 268 Dsymbol *cdp = ad->toParent2(); // class/func we're nested in 269 270 //printf("setEthis(ad = %s, cdp = %s, thisfd = %s)\n", ad->toChars(), cdp->toChars(), thisfd->toChars()); 271 272 if (cdp == thisfd) 273 { /* Class we're new'ing is a local class in this function: 274 * void thisfd() { class ad { } } 275 */ 276 if (irs->sclosure) 277 ethis = el_var(irs->sclosure); 278 else if (irs->sthis) 279 { 280 #if V2 281 if (thisfd->closureVars.dim) 282 #else 283 if (thisfd->nestedFrameRef) 284 #endif 285 { 286 ethis = el_ptr(irs->sthis); 287 } 288 else 289 ethis = el_var(irs->sthis); 290 } 291 else 292 { 293 ethis = el_long(TYnptr, 0); 294 #if V2 295 if (thisfd->closureVars.dim) 296 #else 297 if (thisfd->nestedFrameRef) 298 #endif 299 { 300 ethis->Eoper = OPframeptr; 301 } 302 } 303 } 304 else if (thisfd->vthis && 305 (cdp == thisfd->toParent2() || 306 (cdp->isClassDeclaration() && 307 cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset) 308 ) 309 ) 310 ) 311 { /* Class we're new'ing is at the same level as thisfd 312 */ 313 assert(offset == 0); // BUG: should handle this case 314 ethis = el_var(irs->sthis); 315 } 316 else 317 { 318 ethis = getEthis(loc, irs, ad->toParent2()); 319 ethis = el_una(OPaddr, TYnptr, ethis); 320 } 321 322 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, ad->vthis->offset)); 323 ey = el_una(OPind, TYnptr, ey); 324 ey = el_bin(OPeq, TYnptr, ey, ethis); 325 return ey; 326 } 327 252 328 /******************************************* 253 329 * Convert intrinsic function to operator. 254 330 * Returns that operator, -1 if not an intrinsic function. 255 331 */ 256 332 257 333 int intrinsic_op(char *name) 258 334 { 335 //printf("intrinsic_op(%s)\n", name); 259 336 static const char *namearray[] = 260 337 { 338 #if V1 261 339 "4math3cosFeZe", 262 340 "4math3sinFeZe", 263 341 "4math4fabsFeZe", 264 342 "4math4rintFeZe", 265 343 "4math4sqrtFdZd", 266 344 "4math4sqrtFeZe", 267 345 "4math4sqrtFfZf", 268 346 "4math5ldexpFeiZe", 269 347 "4math6rndtolFeZl", 270 348 271 #if V1272 349 "9intrinsic2btFPkkZi", 273 #else274 "9intrinsic2btFxPkkZi",275 #endif276 350 "9intrinsic3bsfFkZi", 277 351 "9intrinsic3bsrFkZi", 278 352 "9intrinsic3btcFPkkZi", 279 353 "9intrinsic3btrFPkkZi", 280 354 "9intrinsic3btsFPkkZi", 281 355 "9intrinsic3inpFkZh", 282 356 "9intrinsic4inplFkZk", 283 357 "9intrinsic4inpwFkZt", 284 358 "9intrinsic4outpFkhZh", 285 359 "9intrinsic5bswapFkZk", 286 360 "9intrinsic5outplFkkZk", 287 361 "9intrinsic5outpwFktZt", 362 #elif V2 363 /* The names are mangled differently because of the pure and 364 * nothrow attributes. 365 */ 366 "4math3cosFNaNbeZe", 367 "4math3sinFNaNbeZe", 368 "4math4fabsFNaNbeZe", 369 "4math4rintFNaNbeZe", 370 "4math4sqrtFNaNbdZd", 371 "4math4sqrtFNaNbeZe", 372 "4math4sqrtFNaNbfZf", 373 "4math5ldexpFNaNbeiZe", 374 "4math6rndtolFNaNbeZl", 375 376 "9intrinsic2btFNaNbxPkkZi", 377 "9intrinsic3bsfFNaNbkZi", 378 "9intrinsic3bsrFNaNbkZi", 379 "9intrinsic3btcFNbPkkZi", 380 "9intrinsic3btrFNbPkkZi", 381 "9intrinsic3btsFNbPkkZi", 382 "9intrinsic3inpFNbkZh", 383 "9intrinsic4inplFNbkZk", 384 "9intrinsic4inpwFNbkZt", 385 "9intrinsic4outpFNbkhZh", 386 "9intrinsic5bswapFNaNbkZk", 387 "9intrinsic5outplFNbkkZk", 388 "9intrinsic5outpwFNbktZt", 389 #endif 288 390 }; 289 391 static unsigned char ioptab[] = 290 392 { 291 393 OPcos, 292 394 OPsin, 293 395 OPabs, 294 396 OPrint, 295 397 OPsqrt, 296 398 OPsqrt, 297 399 OPsqrt, 298 400 OPscale, 299 401 OPrndtol, 300 402 301 403 OPbt, 302 404 OPbsf, 303 405 OPbsr, 304 406 OPbtc, 305 407 OPbtr, 306 408 OPbts, 307 409 OPinp, … … 312 414 OPoutp, 313 415 OPoutp, 314 416 }; 315 417 316 418 int i; 317 419 size_t length; 318 420 319 421 #ifdef DEBUG 320 422 assert(sizeof(namearray) / sizeof(char *) == sizeof(ioptab)); 321 423 for (i = 0; i < sizeof(namearray) / sizeof(char *) - 1; i++) 322 424 { 323 425 if (strcmp(namearray[i], namearray[i + 1]) >= 0) 324 426 { 325 427 printf("namearray[%d] = '%s'\n", i, namearray[i]); 326 428 assert(0); 327 429 } 328 430 } 329 431 #endif 330 432 331 433 length = strlen(name); 332 if (length < 11 || memcmp(name, "_D3std", 6) != 0) 434 if (length < 11 || 435 !(name[7] == 'm' || name[7] == 'i') || 436 memcmp(name, "_D3std", 6) != 0) 333 437 return -1; 334 438 335 439 i = binary(name + 6, namearray, sizeof(namearray) / sizeof(char *)); 336 440 return (i == -1) ? i : ioptab[i]; 337 441 } 338 442 339 443 340 444 /************************************** 341 445 * Given an expression e that is an array, 342 446 * determine and set the 'length' variable. 343 447 * Input: 344 448 * lengthVar Symbol of 'length' variable 345 449 * &e expression that is the array 346 450 * t1 Type of the array 347 451 * Output: 348 452 * e is rewritten to avoid side effects 349 453 * Returns: 350 454 * expression that initializes 'length' 351 455 */ 352 456 trunk/src/toir.h
r125 r183 1 1 2 // Copyright (c) 1999-200 6by Digital Mars2 // Copyright (c) 1999-2009 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 8 // See the included readme.txt for details. 9 9 10 10 /* Code to help convert to the intermediate representation 11 11 * of the compiler back end. 12 12 * It's specific to the Digital Mars back end, but can serve 13 13 * as a guide to hooking up to other back ends. 14 14 */ 15 15 16 16 elem *incUsageElem(IRState *irs, Loc loc); 17 17 elem *getEthis(Loc loc, IRState *irs, Dsymbol *fd); 18 elem *setEthis(Loc loc, IRState *irs, elem *ey, AggregateDeclaration *ad); 18 19 int intrinsic_op(char *name); 19 20 elem *resolveLengthVar(VarDeclaration *lengthVar, elem **pe, Type *t1); 20 21 trunk/src/toobj.c
r182 r183 8 8 // See the included readme.txt for details. 9 9 10 10 #include <stdio.h> 11 11 #include <stddef.h> 12 12 #include <time.h> 13 13 #include <assert.h> 14 14 15 15 #include "mars.h" 16 16 #include "module.h" 17 17 #include "mtype.h" 18 18 #include "declaration.h" 19 19 #include "statement.h" 20 20 #include "enum.h" 21 21 #include "aggregate.h" 22 22 #include "init.h" 23 23 #include "attrib.h" 24 24 #include "id.h" 25 25 #include "import.h" 26 26 #include "template.h" 27 27 28 #include <mem.h>28 #include "rmem.h" 29 29 #include "cc.h" 30 30 #include "global.h" 31 31 #include "oper.h" 32 32 #include "code.h" 33 33 #include "type.h" 34 34 #include "dt.h" 35 35 #include "cgcv.h" 36 36 #include "outbuf.h" 37 37 #include "irstate.h" 38 38 39 39 void obj_lzext(Symbol *s1,Symbol *s2); 40 40 41 41 /* ================================================================== */ 42 42 43 43 // Put out instance of ModuleInfo for this Module 44 44 45 45 void Module::genmoduleinfo() 46 46 { 47 47 //printf("Module::genmoduleinfo() %s\n", toChars()); 48 48 … … 139 139 #if V2 140 140 FuncDeclaration *sgetmembers = findGetMembers(); 141 141 if (sgetmembers) 142 142 dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr); 143 143 else 144 144 #endif 145 145 dtdword(&dt, 0); // xgetMembers 146 146 147 147 if (sictor) 148 148 dtxoff(&dt, sictor, 0, TYnptr); 149 149 else 150 150 dtdword(&dt, 0); 151 151 152 152 ////////////////////////////////////////////// 153 153 154 154 for (int i = 0; i < aimports.dim; i++) 155 155 { Module *m = (Module *)aimports.data[i]; 156 156 157 157 if (m->needModuleInfo()) 158 158 { Symbol *s = m->toSymbol(); 159 160 /* Weak references don't pull objects in from the library, 161 * they resolve to 0 if not pulled in by something else. 162 * Don't pull in a module just because it was imported. 163 */ 164 #if !OMFOBJ // Optlink crashes with weak symbols at EIP 41AFE7, 402000 159 165 s->Sflags |= SFLweak; 166 #endif 160 167 dtxoff(&dt, s, 0, TYnptr); 161 168 } 162 169 } 163 170 164 171 for (int i = 0; i < aclasses.dim; i++) 165 172 { 166 173 ClassDeclaration *cd = (ClassDeclaration *)aclasses.data[i]; 167 174 dtxoff(&dt, cd->toSymbol(), 0, TYnptr); 168 175 } 169 176 170 177 csym->Sdt = dt; 171 178 #if ELFOBJ || MACHOBJ 172 179 // Cannot be CONST because the startup code sets flag bits in it 173 180 csym->Sseg = DATA; 174 181 #endif 175 182 outdata(csym); 176 183 177 184 ////////////////////////////////////////////// 178 185 179 186 obj_moduleinfo(msym); … … 625 632 626 633 //printf("\tvtbl[%d] = %p\n", i, fd); 627 634 if (fd && (fd->fbody || !isAbstract())) 628 635 { Symbol *s = fd->toSymbol(); 629 636 630 637 #if V2 631 638 if (isFuncHidden(fd)) 632 639 { /* fd is hidden from the view of this class. 633 640 * If fd overlaps with any function in the vtbl[], then 634 641 * issue 'hidden' error. 635 642 */ 636 643 for (int j = 1; j < vtbl.dim; j++) 637 644 { if (j == i) 638 645 continue; 639 646 FuncDeclaration *fd2 = ((Dsymbol *)vtbl.data[j])->isFuncDeclaration(); 640 647 if (!fd2->ident->equals(fd->ident)) 641 648 continue; 642 649 if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd)) 643 650 { 644 651 if (global.params.warnings) 645 { fprintf(stdmsg, "warning - ");652 { 646 653 TypeFunction *tf = (TypeFunction *)fd->type; 647 654 if (tf->ty == Tfunction) 648 error("%s%s is hidden by %s\n", fd->toPrettyChars(), Argument::argsTypesToChars(tf->parameters, tf->varargs), toChars());655 warning("%s%s is hidden by %s\n", fd->toPrettyChars(), Argument::argsTypesToChars(tf->parameters, tf->varargs), toChars()); 649 656 else 650 error("%s is hidden by %s\n", fd->toPrettyChars(), toChars());657 warning("%s is hidden by %s\n", fd->toPrettyChars(), toChars()); 651 658 } 652 659 s = rtlsym[RTLSYM_DHIDDENFUNC]; 653 660 break; 654 661 } 655 662 } 656 663 } 657 664 #endif 658 665 dtxoff(&dt, s, 0, TYnptr); 659 666 } 660 667 else 661 668 dtdword(&dt, 0); 662 669 } 663 670 vtblsym->Sdt = dt; 664 671 vtblsym->Sclass = scclass; 665 672 vtblsym->Sfl = FLdata; 666 673 #if ELFOBJ 667 674 vtblsym->Sseg = CDATA; 668 675 #endif 669 676 #if MACHOBJ 670 677 vtblsym->Sseg = DATA; … … 909 916 { obj_append(this); 910 917 return; 911 918 } 912 919 913 920 // Anonymous structs/unions only exist as part of others, 914 921 // do not output forward referenced structs's 915 922 if (!isAnonymous() && members) 916 923 { 917 924 if (global.params.symdebug) 918 925 toDebug(); 919 926 920 927 type->getTypeInfo(NULL); // generate TypeInfo 921 928 922 929 if (1) 923 930 { 924 931 // Generate static initializer 925 932 toInitializer(); 926 933 #if 0 927 934 sinit->Sclass = SCcomdat; 928 935 #else 929 if (parent && parent->isTemplateInstance()) 936 if (inTemplateInstance()) 937 { 930 938 sinit->Sclass = SCcomdat; 939 } 931 940 else 941 { 932 942 sinit->Sclass = SCglobal; 943 } 933 944 #endif 934 945 sinit->Sfl = FLdata; 935 946 toDt(&sinit->Sdt); 936 947 937 948 #if OMFOBJ 938 949 /* For OMF, common blocks aren't pulled in from the library. 939 950 */ 940 951 /* ELF comdef's generate multiple 941 952 * definition errors for them from the gnu linker. 942 953 * Need to figure out how to generate proper comdef's for ELF. 943 954 */ 944 955 // See if we can convert a comdat to a comdef, 945 956 // which saves on exe file space. 946 957 if (sinit->Sclass == SCcomdat && 947 958 sinit->Sdt && 948 959 sinit->Sdt->dt == DT_azeros && 949 960 sinit->Sdt->DTnext == NULL && 950 961 !global.params.multiobj) 951 962 { 952 963 sinit->Sclass = SCglobal; trunk/src/traits.c
r171 r183 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-200 7by Digital Mars3 // Copyright (c) 1999-2009 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 13 #include <ctype.h> 14 14 #include <assert.h> 15 #if _MSC_VER 16 #include <complex> 17 #else 15 18 #include <complex.h> 19 #endif 16 20 #include <math.h> 17 21 18 22 #if IN_GCC 19 23 // Issues with using -include total.h (defines integer_t) and then complex.h fails... 20 24 #undef integer_t 21 25 #endif 22 26 23 27 #ifdef __APPLE__ 24 28 #define integer_t dmd_integer_t 25 29 #endif 26 30 27 #if IN_GCC 28 #include "mem.h" 29 #elif _WIN32 30 #include "..\root\mem.h" 31 #elif linux 32 #include "../root/mem.h" 33 #endif 31 #include "rmem.h" 34 32 35 33 //#include "port.h" 36 34 #include "mtype.h" 37 35 #include "init.h" 38 36 #include "expression.h" 39 37 #include "template.h" 40 38 #include "utf.h" 41 39 #include "enum.h" 42 40 #include "scope.h" 43 41 #include "statement.h" 44 42 #include "declaration.h" 45 43 #include "aggregate.h" 46 44 #include "import.h" 47 45 #include "id.h" 48 46 #include "dsymbol.h" 49 47 #include "module.h" 50 48 #include "attrib.h" 51 49 #include "hdrgen.h" 52 50 #include "parse.h" 53 51 54 52 #define LOGSEMANTIC 0 55 53 54 #if V2 55 56 56 /************************************************ 57 57 * Delegate to be passed to overloadApply() that looks 58 58 * for virtual functions. 59 59 */ 60 60 61 61 struct Pvirtuals 62 62 { 63 63 Expression *e1; 64 64 Expressions *exps; 65 65 }; 66 66 67 67 static int fpvirtuals(void *param, FuncDeclaration *f) 68 68 { Pvirtuals *p = (Pvirtuals *)param; 69 69 70 70 if (f->isVirtual()) 71 71 { Expression *e; 72 72 73 73 if (p->e1->op == TOKdotvar) 74 74 { DotVarExp *dve = (DotVarExp *)p->e1; 75 75 e = new DotVarExp(0, dve->e1, f); … … 421 421 422 422 return NULL; 423 423 424 424 Lnottype: 425 425 error("%s is not a type", o->toChars()); 426 426 goto Lfalse; 427 427 428 428 Ldimerror: 429 429 error("wrong number of arguments %d", dim); 430 430 goto Lfalse; 431 431 432 432 433 433 Lfalse: 434 434 return new IntegerExp(loc, 0, Type::tbool); 435 435 436 436 Ltrue: 437 437 return new IntegerExp(loc, 1, Type::tbool); 438 438 } 439 439 440 440 441 #endif trunk/src/typinf.c
r182 r183 10 10 11 11 #include <stdio.h> 12 12 #include <assert.h> 13 13 14 14 //#include "mem.h" 15 15 16 16 #include "mars.h" 17 17 #include "module.h" 18 18 #include "mtype.h" 19 19 #include "scope.h" 20 20 #include "init.h" 21 21 #include "expression.h" 22 22 #include "attrib.h" 23 23 #include "declaration.h" 24 24 #include "template.h" 25 25 #include "id.h" 26 26 #include "enum.h" 27 27 #include "import.h" 28 28 #include "aggregate.h" 29 29 30 #include <mem.h>30 #include "rmem.h" 31 31 #include "cc.h" 32 32 #include "global.h" 33 33 #include "oper.h" 34 34 #include "code.h" 35 35 #include "type.h" 36 36 #include "dt.h" 37 37 #include "cgcv.h" 38 38 #include "outbuf.h" 39 39 #include "irstate.h" 40 40 41 41 extern Symbol *static_sym(); 42 42 43 43 /******************************************* 44 44 * Get a canonicalized form of the TypeInfo for use with the internal 45 45 * runtime library routines. Canonicalized in that static arrays are 46 46 * represented as dynamic arrays, enums are represented by their 47 47 * underlying type, etc. This reduces the number of TypeInfo's needed, 48 48 * so we can use the custom internal ones more. 49 49 */ 50 50
