Mercurial > projects > ldc
comparison dmd/func.c @ 336:aaade6ded589 trunk
[svn r357] Merged DMD 1.033
author | lindquist |
---|---|
date | Sat, 12 Jul 2008 19:38:31 +0200 |
parents | f7190d9eb70c |
children | d8234836b40f |
comparison
equal
deleted
inserted
replaced
335:17b844102023 | 336:aaade6ded589 |
---|---|
101 void FuncDeclaration::semantic(Scope *sc) | 101 void FuncDeclaration::semantic(Scope *sc) |
102 { TypeFunction *f; | 102 { TypeFunction *f; |
103 StructDeclaration *sd; | 103 StructDeclaration *sd; |
104 ClassDeclaration *cd; | 104 ClassDeclaration *cd; |
105 InterfaceDeclaration *id; | 105 InterfaceDeclaration *id; |
106 Dsymbol *pd; | |
106 | 107 |
107 #if 0 | 108 #if 0 |
108 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage); | 109 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage); |
109 if (isFuncLiteralDeclaration()) | 110 if (isFuncLiteralDeclaration()) |
110 printf("\tFuncLiteralDeclaration()\n"); | 111 printf("\tFuncLiteralDeclaration()\n"); |
204 isInvariantDeclaration() || | 205 isInvariantDeclaration() || |
205 isUnitTestDeclaration() || isNewDeclaration() || isDelete()) | 206 isUnitTestDeclaration() || isNewDeclaration() || isDelete()) |
206 error("special function not allowed in interface %s", id->toChars()); | 207 error("special function not allowed in interface %s", id->toChars()); |
207 if (fbody) | 208 if (fbody) |
208 error("function body is not abstract in interface %s", id->toChars()); | 209 error("function body is not abstract in interface %s", id->toChars()); |
210 } | |
211 | |
212 /* Template member functions aren't virtual: | |
213 * interface TestInterface { void tpl(T)(); } | |
214 * and so won't work in interfaces | |
215 */ | |
216 if ((pd = toParent()) != NULL && | |
217 pd->isTemplateInstance() && | |
218 (pd = toParent2()) != NULL && | |
219 (id = pd->isInterfaceDeclaration()) != NULL) | |
220 { | |
221 error("template member function not allowed in interface %s", id->toChars()); | |
209 } | 222 } |
210 | 223 |
211 cd = parent->isClassDeclaration(); | 224 cd = parent->isClassDeclaration(); |
212 if (cd) | 225 if (cd) |
213 { int vi; | 226 { int vi; |
304 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; | 317 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; |
305 // This function is covariant with fdv | 318 // This function is covariant with fdv |
306 if (fdv->isFinal()) | 319 if (fdv->isFinal()) |
307 error("cannot override final function %s", fdv->toPrettyChars()); | 320 error("cannot override final function %s", fdv->toPrettyChars()); |
308 | 321 |
309 #if V2 | 322 #if DMDV2 |
310 if (!isOverride() && global.params.warnings) | 323 if (!isOverride() && global.params.warnings) |
311 warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars() fdv->toPrettyChars()); | 324 warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars() fdv->toPrettyChars()); |
312 #endif | 325 #endif |
313 | 326 |
314 if (fdv->toParent() == parent) | 327 if (fdv->toParent() == parent) |
320 break; | 333 break; |
321 if (!this->parent->isClassDeclaration() | 334 if (!this->parent->isClassDeclaration() |
322 #if !BREAKABI | 335 #if !BREAKABI |
323 && !isDtorDeclaration() | 336 && !isDtorDeclaration() |
324 #endif | 337 #endif |
325 #if V2 | 338 #if DMDV2 |
326 && !isPostBlitDeclaration() | 339 && !isPostBlitDeclaration() |
327 #endif | 340 #endif |
328 ) | 341 ) |
329 error("multiple overrides of same function"); | 342 error("multiple overrides of same function"); |
330 } | 343 } |
976 type = type->semantic(loc, sc); | 989 type = type->semantic(loc, sc); |
977 } | 990 } |
978 f = (TypeFunction *)type; | 991 f = (TypeFunction *)type; |
979 } | 992 } |
980 | 993 |
981 int offend = fbody ? fbody->fallOffEnd() : TRUE; | 994 int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE; |
995 //int offend = fbody ? fbody->fallOffEnd() : TRUE; | |
982 | 996 |
983 if (isStaticCtorDeclaration()) | 997 if (isStaticCtorDeclaration()) |
984 { /* It's a static constructor. Ensure that all | 998 { /* It's a static constructor. Ensure that all |
985 * ctor consts were initialized. | 999 * ctor consts were initialized. |
986 */ | 1000 */ |
1469 if (t->equals(f->type)) | 1483 if (t->equals(f->type)) |
1470 { p->f = f; | 1484 { p->f = f; |
1471 return 1; | 1485 return 1; |
1472 } | 1486 } |
1473 | 1487 |
1474 #if V2 | 1488 #if DMDV2 |
1475 /* Allow covariant matches, if it's just a const conversion | 1489 /* Allow covariant matches, if it's just a const conversion |
1476 * of the return type | 1490 * of the return type |
1477 */ | 1491 */ |
1478 if (t->ty == Tfunction) | 1492 if (t->ty == Tfunction) |
1479 { TypeFunction *tf = (TypeFunction *)f->type; | 1493 { TypeFunction *tf = (TypeFunction *)f->type; |
1775 s = new LabelDsymbol(ident); | 1789 s = new LabelDsymbol(ident); |
1776 labtab->insert(s); | 1790 labtab->insert(s); |
1777 } | 1791 } |
1778 return (LabelDsymbol *)s; | 1792 return (LabelDsymbol *)s; |
1779 } | 1793 } |
1794 | |
1780 /**************************************** | 1795 /**************************************** |
1781 * If non-static member function that has a 'this' pointer, | 1796 * If non-static member function that has a 'this' pointer, |
1782 * return the aggregate it is a member of. | 1797 * return the aggregate it is a member of. |
1783 * Otherwise, return NULL. | 1798 * Otherwise, return NULL. |
1784 */ | 1799 */ |
2029 st->insert(fd); | 2044 st->insert(fd); |
2030 } | 2045 } |
2031 return fd; | 2046 return fd; |
2032 } | 2047 } |
2033 | 2048 |
2034 char *FuncDeclaration::kind() | 2049 const char *FuncDeclaration::kind() |
2035 { | 2050 { |
2036 return "function"; | 2051 return "function"; |
2037 } | 2052 } |
2053 | |
2038 /******************************* | 2054 /******************************* |
2039 * Look at all the variables in this function that are referenced | 2055 * Look at all the variables in this function that are referenced |
2040 * by nested functions, and determine if a closure needs to be | 2056 * by nested functions, and determine if a closure needs to be |
2041 * created for them. | 2057 * created for them. |
2042 */ | 2058 */ |
2043 | 2059 |
2044 #if V2 | 2060 #if DMDV2 |
2045 int FuncDeclaration::needsClosure() | 2061 int FuncDeclaration::needsClosure() |
2046 { | 2062 { |
2047 /* Need a closure for all the closureVars[] if any of the | 2063 /* Need a closure for all the closureVars[] if any of the |
2048 * closureVars[] are accessed by a | 2064 * closureVars[] are accessed by a |
2049 * function that escapes the scope of this function. | 2065 * function that escapes the scope of this function. |
2050 * We take the conservative approach and decide that any function that: | 2066 * We take the conservative approach and decide that any function that: |
2051 * 1) is a virtual function | 2067 * 1) is a virtual function |
2052 * 2) has its address taken | 2068 * 2) has its address taken |
2053 * 3) has a parent that escapes | 2069 * 3) has a parent that escapes |
2054 * escapes. | 2070 * |
2071 * Note that since a non-virtual function can be called by | |
2072 * a virtual one, if that non-virtual function accesses a closure | |
2073 * var, the closure still has to be taken. Hence, we check for isThis() | |
2074 * instead of isVirtual(). (thanks to David Friedman) | |
2055 */ | 2075 */ |
2056 | 2076 |
2057 //printf("FuncDeclaration::needsClosure() %s\n", toChars()); | 2077 //printf("FuncDeclaration::needsClosure() %s\n", toChars()); |
2058 for (int i = 0; i < closureVars.dim; i++) | 2078 for (int i = 0; i < closureVars.dim; i++) |
2059 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; | 2079 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; |
2063 for (int j = 0; j < v->nestedrefs.dim; j++) | 2083 for (int j = 0; j < v->nestedrefs.dim; j++) |
2064 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j]; | 2084 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j]; |
2065 assert(f != this); | 2085 assert(f != this); |
2066 | 2086 |
2067 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf); | 2087 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf); |
2068 if (f->isVirtual() || f->tookAddressOf) | 2088 if (f->isThis() || f->tookAddressOf) |
2069 goto Lyes; // assume f escapes this function's scope | 2089 goto Lyes; // assume f escapes this function's scope |
2070 | 2090 |
2071 // Look to see if any parents of f that are below this escape | 2091 // Look to see if any parents of f that are below this escape |
2072 for (Dsymbol *s = f->parent; s != this; s = s->parent) | 2092 for (Dsymbol *s = f->parent; s != this; s = s->parent) |
2073 { | 2093 { |
2074 f = s->isFuncDeclaration(); | 2094 f = s->isFuncDeclaration(); |
2075 if (f && (f->isVirtual() || f->tookAddressOf)) | 2095 if (f && (f->isThis() || f->tookAddressOf)) |
2076 goto Lyes; | 2096 goto Lyes; |
2077 } | 2097 } |
2078 } | 2098 } |
2079 } | 2099 } |
2080 return 0; | 2100 return 0; |
2095 { | 2115 { |
2096 assert(funcalias != this); | 2116 assert(funcalias != this); |
2097 this->funcalias = funcalias; | 2117 this->funcalias = funcalias; |
2098 } | 2118 } |
2099 | 2119 |
2100 char *FuncAliasDeclaration::kind() | 2120 const char *FuncAliasDeclaration::kind() |
2101 { | 2121 { |
2102 return "function alias"; | 2122 return "function alias"; |
2103 } | 2123 } |
2104 | 2124 |
2105 | 2125 |
2140 { | 2160 { |
2141 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars()); | 2161 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars()); |
2142 return (tok == TOKdelegate); | 2162 return (tok == TOKdelegate); |
2143 } | 2163 } |
2144 | 2164 |
2145 char *FuncLiteralDeclaration::kind() | 2165 int FuncLiteralDeclaration::isVirtual() |
2166 { | |
2167 return FALSE; | |
2168 } | |
2169 | |
2170 const char *FuncLiteralDeclaration::kind() | |
2146 { | 2171 { |
2147 // GCC requires the (char*) casts | 2172 // GCC requires the (char*) casts |
2148 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function"; | 2173 return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function"; |
2149 } | 2174 } |
2150 | 2175 |
2212 tret = Type::tvoid; | 2237 tret = Type::tvoid; |
2213 } | 2238 } |
2214 else | 2239 else |
2215 tret = cd->type; //->referenceTo(); | 2240 tret = cd->type; //->referenceTo(); |
2216 type = new TypeFunction(arguments, tret, varargs, LINKd); | 2241 type = new TypeFunction(arguments, tret, varargs, LINKd); |
2242 if (!originalType) | |
2243 originalType = type; | |
2217 | 2244 |
2218 sc->flags |= SCOPEctor; | 2245 sc->flags |= SCOPEctor; |
2219 type = type->semantic(loc, sc); | 2246 type = type->semantic(loc, sc); |
2220 sc->flags &= ~SCOPEctor; | 2247 sc->flags &= ~SCOPEctor; |
2221 | 2248 |
2238 // See if it's the default constructor | 2265 // See if it's the default constructor |
2239 if (cd && varargs == 0 && Argument::dim(arguments) == 0) | 2266 if (cd && varargs == 0 && Argument::dim(arguments) == 0) |
2240 cd->defaultCtor = this; | 2267 cd->defaultCtor = this; |
2241 } | 2268 } |
2242 | 2269 |
2243 char *CtorDeclaration::kind() | 2270 const char *CtorDeclaration::kind() |
2244 { | 2271 { |
2245 return "constructor"; | 2272 return "constructor"; |
2246 } | 2273 } |
2247 | 2274 |
2248 char *CtorDeclaration::toChars() | 2275 char *CtorDeclaration::toChars() |
2374 void StaticCtorDeclaration::semantic(Scope *sc) | 2401 void StaticCtorDeclaration::semantic(Scope *sc) |
2375 { | 2402 { |
2376 //printf("StaticCtorDeclaration::semantic()\n"); | 2403 //printf("StaticCtorDeclaration::semantic()\n"); |
2377 | 2404 |
2378 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); | 2405 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); |
2406 | |
2407 /* If the static ctor appears within a template instantiation, | |
2408 * it could get called multiple times by the module constructors | |
2409 * for different modules. Thus, protect it with a gate. | |
2410 */ | |
2411 if (inTemplateInstance()) | |
2412 { | |
2413 /* Add this prefix to the function: | |
2414 * static int gate; | |
2415 * if (++gate != 1) return; | |
2416 * Note that this is not thread safe; should not have threads | |
2417 * during static construction. | |
2418 */ | |
2419 Identifier *id = Lexer::idPool("__gate"); | |
2420 VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL); | |
2421 v->storage_class = STCstatic; | |
2422 Statements *sa = new Statements(); | |
2423 Statement *s = new DeclarationStatement(0, v); | |
2424 sa->push(s); | |
2425 Expression *e = new IdentifierExp(0, id); | |
2426 e = new AddAssignExp(0, e, new IntegerExp(1)); | |
2427 e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1)); | |
2428 s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL); | |
2429 sa->push(s); | |
2430 if (fbody) | |
2431 sa->push(fbody); | |
2432 fbody = new CompoundStatement(0, sa); | |
2433 } | |
2379 | 2434 |
2380 FuncDeclaration::semantic(sc); | 2435 FuncDeclaration::semantic(sc); |
2381 | 2436 |
2382 // We're going to need ModuleInfo | 2437 // We're going to need ModuleInfo |
2383 Module *m = getModule(); | 2438 Module *m = getModule(); |
2430 | 2485 |
2431 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc) | 2486 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc) |
2432 : FuncDeclaration(loc, endloc, | 2487 : FuncDeclaration(loc, endloc, |
2433 Identifier::generateId("_staticDtor"), STCstatic, NULL) | 2488 Identifier::generateId("_staticDtor"), STCstatic, NULL) |
2434 { | 2489 { |
2490 vgate = NULL; | |
2435 } | 2491 } |
2436 | 2492 |
2437 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) | 2493 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s) |
2438 { | 2494 { |
2439 StaticDtorDeclaration *sdd; | 2495 StaticDtorDeclaration *sdd; |
2452 cd = sc->scopesym->isClassDeclaration(); | 2508 cd = sc->scopesym->isClassDeclaration(); |
2453 if (!cd) | 2509 if (!cd) |
2454 { | 2510 { |
2455 } | 2511 } |
2456 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); | 2512 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); |
2513 | |
2514 /* If the static ctor appears within a template instantiation, | |
2515 * it could get called multiple times by the module constructors | |
2516 * for different modules. Thus, protect it with a gate. | |
2517 */ | |
2518 if (inTemplateInstance()) | |
2519 { | |
2520 /* Add this prefix to the function: | |
2521 * static int gate; | |
2522 * if (--gate != 0) return; | |
2523 * Increment gate during constructor execution. | |
2524 * Note that this is not thread safe; should not have threads | |
2525 * during static destruction. | |
2526 */ | |
2527 Identifier *id = Lexer::idPool("__gate"); | |
2528 VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL); | |
2529 v->storage_class = STCstatic; | |
2530 Statements *sa = new Statements(); | |
2531 Statement *s = new DeclarationStatement(0, v); | |
2532 sa->push(s); | |
2533 Expression *e = new IdentifierExp(0, id); | |
2534 e = new AddAssignExp(0, e, new IntegerExp(-1)); | |
2535 e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1)); | |
2536 s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL); | |
2537 sa->push(s); | |
2538 if (fbody) | |
2539 sa->push(fbody); | |
2540 fbody = new CompoundStatement(0, sa); | |
2541 vgate = v; | |
2542 } | |
2457 | 2543 |
2458 FuncDeclaration::semantic(sc); | 2544 FuncDeclaration::semantic(sc); |
2459 | 2545 |
2460 // We're going to need ModuleInfo | 2546 // We're going to need ModuleInfo |
2461 Module *m = getModule(); | 2547 Module *m = getModule(); |
2581 * instances per module. | 2667 * instances per module. |
2582 */ | 2668 */ |
2583 | 2669 |
2584 static Identifier *unitTestId() | 2670 static Identifier *unitTestId() |
2585 { | 2671 { |
2586 static int n; | 2672 return Lexer::uniqueId("__unittest"); |
2587 char buffer[10 + sizeof(n)*3 + 1]; | |
2588 | |
2589 sprintf(buffer,"__unittest%d", n); | |
2590 n++; | |
2591 return Lexer::idPool(buffer); | |
2592 } | 2673 } |
2593 | 2674 |
2594 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc) | 2675 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc) |
2595 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL) | 2676 : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL) |
2596 { | 2677 { |
2711 } | 2792 } |
2712 | 2793 |
2713 FuncDeclaration::semantic(sc); | 2794 FuncDeclaration::semantic(sc); |
2714 } | 2795 } |
2715 | 2796 |
2716 char *NewDeclaration::kind() | 2797 const char *NewDeclaration::kind() |
2717 { | 2798 { |
2718 return "allocator"; | 2799 return "allocator"; |
2719 } | 2800 } |
2720 | 2801 |
2721 int NewDeclaration::isVirtual() | 2802 int NewDeclaration::isVirtual() |
2795 } | 2876 } |
2796 | 2877 |
2797 FuncDeclaration::semantic(sc); | 2878 FuncDeclaration::semantic(sc); |
2798 } | 2879 } |
2799 | 2880 |
2800 char *DeleteDeclaration::kind() | 2881 const char *DeleteDeclaration::kind() |
2801 { | 2882 { |
2802 return "deallocator"; | 2883 return "deallocator"; |
2803 } | 2884 } |
2804 | 2885 |
2805 int DeleteDeclaration::isDelete() | 2886 int DeleteDeclaration::isDelete() |