comparison dmd/func.c @ 1602:a413ae7329bf

Merge DMD r243: some harmonization with D2 dmd --- dmd/aggregate.h | 24 ++++- dmd/attrib.c | 63 ++++++---- dmd/attrib.h | 10 +- dmd/declaration.h | 5 +- dmd/func.c | 337 ++++++++++++++++++++++------------------------------- dmd/mars.c | 2 +- dmd/mars.h | 7 + dmd/mtype.h | 13 ++- dmd/parse.c | 32 ++++- dmd/parse.h | 14 ++- dmd/scope.h | 2 +- 11 files changed, 263 insertions(+), 246 deletions(-)
author Leandro Lucarella <llucax@gmail.com>
date Wed, 06 Jan 2010 15:18:19 -0300
parents def7a1d494fd
children 207a8a438dea
comparison
equal deleted inserted replaced
1601:49722e6e6e05 1602:a413ae7329bf
29 #include "d-dmd-gcc.h" 29 #include "d-dmd-gcc.h"
30 #endif 30 #endif
31 31
32 /********************************* FuncDeclaration ****************************/ 32 /********************************* FuncDeclaration ****************************/
33 33
34 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type) 34 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
35 : Declaration(id) 35 : Declaration(id)
36 { 36 {
37 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type); 37 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
38 //printf("storage_class = x%x\n", storage_class); 38 //printf("storage_class = x%x\n", storage_class);
39 this->storage_class = storage_class; 39 this->storage_class = storage_class;
122 122
123 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars()); 123 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
124 if (s) 124 if (s)
125 f = (FuncDeclaration *)s; 125 f = (FuncDeclaration *)s;
126 else 126 else
127 f = new FuncDeclaration(loc, endloc, ident, (enum STC) storage_class, type->syntaxCopy()); 127 f = new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
128 f->outId = outId; 128 f->outId = outId;
129 f->frequire = frequire ? frequire->syntaxCopy() : NULL; 129 f->frequire = frequire ? frequire->syntaxCopy() : NULL;
130 f->fensure = fensure ? fensure->syntaxCopy() : NULL; 130 f->fensure = fensure ? fensure->syntaxCopy() : NULL;
131 f->fbody = fbody ? fbody->syntaxCopy() : NULL; 131 f->fbody = fbody ? fbody->syntaxCopy() : NULL;
132 assert(!fthrows); // deprecated 132 assert(!fthrows); // deprecated
444 * If this function is covariant with any members of those interface 444 * If this function is covariant with any members of those interface
445 * functions, set the tintro. 445 * functions, set the tintro.
446 */ 446 */
447 for (int i = 0; i < cd->interfaces_dim; i++) 447 for (int i = 0; i < cd->interfaces_dim; i++)
448 { 448 {
449 #if 1
450 BaseClass *b = cd->interfaces[i]; 449 BaseClass *b = cd->interfaces[i];
451 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim); 450 vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
452 switch (vi) 451 switch (vi)
453 { 452 {
454 case -1: 453 case -1:
497 tintro = ti; 496 tintro = ti;
498 } 497 }
499 goto L2; 498 goto L2;
500 } 499 }
501 } 500 }
502 #else
503 BaseClass *b = cd->interfaces[i];
504 for (vi = 0; vi < b->base->vtbl.dim; vi++)
505 {
506 Dsymbol *s = (Dsymbol *)b->base->vtbl.data[vi];
507 //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
508 FuncDeclaration *fdv = s->isFuncDeclaration();
509 if (fdv && fdv->ident == ident)
510 {
511 int cov = type->covariant(fdv->type);
512 //printf("\tcov = %d\n", cov);
513 if (cov == 2)
514 {
515 //type->print();
516 //fdv->type->print();
517 //printf("%s %s\n", type->deco, fdv->type->deco);
518 error("of type %s overrides but is not covariant with %s of type %s",
519 type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
520 }
521 if (cov == 1)
522 { Type *ti = NULL;
523
524 if (fdv->tintro)
525 ti = fdv->tintro;
526 else if (!type->equals(fdv->type))
527 {
528 /* Only need to have a tintro if the vptr
529 * offsets differ
530 */
531 int offset;
532 if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
533 {
534 ti = fdv->type;
535 #if 0
536 if (offset)
537 ti = fdv->type;
538 else if (type->nextOf()->ty == Tclass)
539 { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
540 if (cdn && cdn->sizeok != 1)
541 ti = fdv->type;
542 }
543 #endif
544 }
545 }
546 if (ti)
547 {
548 if (tintro && !tintro->equals(ti))
549 {
550 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
551 }
552 tintro = ti;
553 }
554 goto L2;
555 }
556 if (cov == 3)
557 {
558 cd->sizeok = 2; // can't finish due to forward reference
559 return;
560 }
561 }
562 }
563 #endif
564 } 501 }
565 502
566 if (introducing && isOverride()) 503 if (introducing && isOverride())
567 { 504 {
568 error("does not override any function"); 505 error("does not override any function");
1310 #if IN_GCC 1247 #if IN_GCC
1311 // Handled in FuncDeclaration::toObjFile 1248 // Handled in FuncDeclaration::toObjFile
1312 v_argptr = argptr; 1249 v_argptr = argptr;
1313 v_argptr->init = new VoidInitializer(loc); 1250 v_argptr->init = new VoidInitializer(loc);
1314 #else 1251 #else
1315 Expression *e1;
1316 Expression *e;
1317 Type *t = argptr->type; 1252 Type *t = argptr->type;
1318 VarDeclaration *p; 1253 VarDeclaration *p;
1319 unsigned offset; 1254 unsigned offset;
1320 1255
1321 e1 = new VarExp(0, argptr); 1256 Expression *e1 = new VarExp(0, argptr);
1322 if (parameters && parameters->dim) 1257 if (parameters && parameters->dim)
1323 p = (VarDeclaration *)parameters->data[parameters->dim - 1]; 1258 p = (VarDeclaration *)parameters->data[parameters->dim - 1];
1324 else 1259 else
1325 p = v_arguments; // last parameter is _arguments[] 1260 p = v_arguments; // last parameter is _arguments[]
1326 if (p->storage_class & STClazy) 1261 if (p->storage_class & STClazy)
1327 // If the last parameter is lazy, it's the size of a delegate 1262 // If the last parameter is lazy, it's the size of a delegate
1328 offset = PTRSIZE * 2; 1263 offset = PTRSIZE * 2;
1329 else 1264 else
1330 offset = p->type->size(); 1265 offset = p->type->size();
1331 offset = (offset + 3) & ~3; // assume stack aligns on 4 1266 offset = (offset + 3) & ~3; // assume stack aligns on 4
1332 e = new SymOffExp(0, p, offset); 1267 Expression *e = new SymOffExp(0, p, offset);
1333 e = new AssignExp(0, e1, e); 1268 e = new AssignExp(0, e1, e);
1334 e->type = t; 1269 e->type = t;
1335 a->push(new ExpStatement(0, e)); 1270 a->push(new ExpStatement(0, e));
1336 #endif // IN_GCC 1271 #endif // IN_GCC
1337 } 1272 }
1916 p.f = NULL; 1851 p.f = NULL;
1917 overloadApply(from, this, &fp1, &p); 1852 overloadApply(from, this, &fp1, &p);
1918 return p.f; 1853 return p.f;
1919 } 1854 }
1920 1855
1921 #if 0
1922 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
1923 {
1924 FuncDeclaration *f;
1925 Declaration *d;
1926 Declaration *next;
1927
1928 for (d = this; d; d = next)
1929 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
1930
1931 if (fa)
1932 {
1933 FuncDeclaration *f2 = fa->funcalias->overloadExactMatch(t);
1934 if (f2)
1935 return f2;
1936 next = fa->overnext;
1937 }
1938 else
1939 {
1940 AliasDeclaration *a = d->isAliasDeclaration();
1941
1942 if (a)
1943 {
1944 Dsymbol *s = a->toAlias();
1945 next = s->isDeclaration();
1946 if (next == a)
1947 break;
1948 }
1949 else
1950 {
1951 f = d->isFuncDeclaration();
1952 if (!f)
1953 break; // BUG: should print error message?
1954 if (t->equals(d->type))
1955 return f;
1956 next = f->overnext;
1957 }
1958 }
1959 }
1960 return NULL;
1961 }
1962 #endif
1963 1856
1964 /******************************************** 1857 /********************************************
1965 * Decide which function matches the arguments best. 1858 * Decide which function matches the arguments best.
1966 */ 1859 */
1967 1860
1968 struct Param2 1861 struct Param2
1969 { 1862 {
1970 Match *m; 1863 Match *m;
1864 #if DMDV2
1865 Expression *ethis;
1866 #endif
1971 Expressions *arguments; 1867 Expressions *arguments;
1972 }; 1868 };
1973 1869
1974 int fp2(void *param, FuncDeclaration *f) 1870 int fp2(void *param, FuncDeclaration *f)
1975 { Param2 *p = (Param2 *)param; 1871 { Param2 *p = (Param2 *)param;
1996 if (m->lastf->overrides(f)) 1892 if (m->lastf->overrides(f))
1997 goto LlastIsBetter; 1893 goto LlastIsBetter;
1998 else if (f->overrides(m->lastf)) 1894 else if (f->overrides(m->lastf))
1999 goto LfIsBetter; 1895 goto LfIsBetter;
2000 1896
1897 #if DMDV2
1898 /* Try to disambiguate using template-style partial ordering rules.
1899 * In essence, if f() and g() are ambiguous, if f() can call g(),
1900 * but g() cannot call f(), then pick f().
1901 * This is because f() is "more specialized."
1902 */
1903 {
1904 MATCH c1 = f->leastAsSpecialized(m->lastf);
1905 MATCH c2 = m->lastf->leastAsSpecialized(f);
1906 //printf("c1 = %d, c2 = %d\n", c1, c2);
1907 if (c1 > c2)
1908 goto LfIsBetter;
1909 if (c1 < c2)
1910 goto LlastIsBetter;
1911 }
1912 #endif
2001 Lambiguous: 1913 Lambiguous:
2002 m->nextf = f; 1914 m->nextf = f;
2003 m->count++; 1915 m->count++;
2004 return 0; 1916 return 0;
2005 1917
2024 p.m = m; 1936 p.m = m;
2025 p.arguments = arguments; 1937 p.arguments = arguments;
2026 overloadApply(from, fstart, &fp2, &p); 1938 overloadApply(from, fstart, &fp2, &p);
2027 } 1939 }
2028 1940
2029 #if 0
2030 // Recursive helper function
2031
2032 void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments)
2033 {
2034 MATCH match;
2035 Declaration *d;
2036 Declaration *next;
2037
2038 for (d = fstart; d; d = next)
2039 {
2040 FuncDeclaration *f;
2041 FuncAliasDeclaration *fa;
2042 AliasDeclaration *a;
2043
2044 fa = d->isFuncAliasDeclaration();
2045 if (fa)
2046 {
2047 overloadResolveX(m, fa->funcalias, NULL, arguments);
2048 next = fa->overnext;
2049 }
2050 else if ((f = d->isFuncDeclaration()) != NULL)
2051 {
2052 next = f->overnext;
2053 if (f == m->lastf)
2054 continue; // skip duplicates
2055 else
2056 {
2057 TypeFunction *tf;
2058
2059 m->anyf = f;
2060 tf = (TypeFunction *)f->type;
2061 match = (MATCH) tf->callMatch(arguments);
2062 //printf("2match = %d\n", match);
2063 if (match != MATCHnomatch)
2064 {
2065 if (match > m->last)
2066 goto LfIsBetter;
2067
2068 if (match < m->last)
2069 goto LlastIsBetter;
2070
2071 /* See if one of the matches overrides the other.
2072 */
2073 if (m->lastf->overrides(f))
2074 goto LlastIsBetter;
2075 else if (f->overrides(m->lastf))
2076 goto LfIsBetter;
2077
2078 Lambiguous:
2079 m->nextf = f;
2080 m->count++;
2081 continue;
2082
2083 LfIsBetter:
2084 m->last = match;
2085 m->lastf = f;
2086 m->count = 1;
2087 continue;
2088
2089 LlastIsBetter:
2090 continue;
2091 }
2092 }
2093 }
2094 else if ((a = d->isAliasDeclaration()) != NULL)
2095 {
2096 Dsymbol *s = a->toAlias();
2097 next = s->isDeclaration();
2098 if (next == a)
2099 break;
2100 if (next == fstart)
2101 break;
2102 }
2103 else
2104 { d->error("is aliased to a function");
2105 break;
2106 }
2107 }
2108 }
2109 #endif
2110 1941
2111 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, Module *from, int flags) 1942 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, Module *from, int flags)
2112 { 1943 {
2113 TypeFunction *tf; 1944 TypeFunction *tf;
2114 Match m; 1945 Match m;
2177 return m.lastf; 2008 return m.lastf;
2178 } 2009 }
2179 } 2010 }
2180 } 2011 }
2181 2012
2013 /*************************************
2014 * Determine partial specialization order of 'this' vs g.
2015 * This is very similar to TemplateDeclaration::leastAsSpecialized().
2016 * Returns:
2017 * match 'this' is at least as specialized as g
2018 * 0 g is more specialized than 'this'
2019 */
2020
2021 #if DMDV2
2022 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
2023 {
2024 #define LOG_LEASTAS 0
2025
2026 #if LOG_LEASTAS
2027 printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
2028 #endif
2029
2030 /* This works by calling g() with f()'s parameters, and
2031 * if that is possible, then f() is at least as specialized
2032 * as g() is.
2033 */
2034
2035 TypeFunction *tf = (TypeFunction *)type;
2036 TypeFunction *tg = (TypeFunction *)g->type;
2037 size_t nfparams = Argument::dim(tf->parameters);
2038 size_t ngparams = Argument::dim(tg->parameters);
2039 MATCH match = MATCHexact;
2040
2041 /* If both functions have a 'this' pointer, and the mods are not
2042 * the same and g's is not const, then this is less specialized.
2043 */
2044 if (needThis() && g->needThis())
2045 {
2046 if (tf->mod != tg->mod)
2047 {
2048 if (tg->mod == MODconst)
2049 match = MATCHconst;
2050 else
2051 return MATCHnomatch;
2052 }
2053 }
2054
2055 /* Create a dummy array of arguments out of the parameters to f()
2056 */
2057 Expressions args;
2058 args.setDim(nfparams);
2059 for (int u = 0; u < nfparams; u++)
2060 {
2061 Argument *p = Argument::getNth(tf->parameters, u);
2062 Expression *e;
2063 if (p->storageClass & (STCref | STCout))
2064 {
2065 e = new IdentifierExp(0, p->ident);
2066 e->type = p->type;
2067 }
2068 else
2069 e = p->type->defaultInit();
2070 args.data[u] = e;
2071 }
2072
2073 MATCH m = (MATCH) tg->callMatch(NULL, &args);
2074 if (m)
2075 {
2076 /* A variadic parameter list is less specialized than a
2077 * non-variadic one.
2078 */
2079 if (tf->varargs && !tg->varargs)
2080 goto L1; // less specialized
2081
2082 #if LOG_LEASTAS
2083 printf(" matches %d, so is least as specialized\n", m);
2084 #endif
2085 return m;
2086 }
2087 L1:
2088 #if LOG_LEASTAS
2089 printf(" doesn't match, so is not as specialized\n");
2090 #endif
2091 return MATCHnomatch;
2092 }
2093
2094 /*******************************************
2095 * Given a symbol that could be either a FuncDeclaration or
2096 * a function template, resolve it to a function symbol.
2097 * sc instantiation scope
2098 * loc instantiation location
2099 * targsi initial list of template arguments
2100 * ethis if !NULL, the 'this' pointer argument
2101 * fargs arguments to function
2102 * flags 1: do not issue error message on no match, just return NULL
2103 */
2104
2105 FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
2106 Objects *tiargs,
2107 Expression *ethis,
2108 Expressions *arguments,
2109 int flags)
2110 {
2111 if (!s)
2112 return NULL; // no match
2113 FuncDeclaration *f = s->isFuncDeclaration();
2114 if (f)
2115 f = f->overloadResolve(loc, ethis, arguments);
2116 else
2117 { TemplateDeclaration *td = s->isTemplateDeclaration();
2118 assert(td);
2119 f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags);
2120 }
2121 return f;
2122 }
2123 #endif
2124
2182 /******************************** 2125 /********************************
2183 * Labels are in a separate scope, one per function. 2126 * Labels are in a separate scope, one per function.
2184 */ 2127 */
2185 2128
2186 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident) 2129 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
2296 s = new ExpStatement(0, e); 2239 s = new ExpStatement(0, e);
2297 appendState(s); 2240 appendState(s);
2298 } 2241 }
2299 2242
2300 void FuncDeclaration::appendState(Statement *s) 2243 void FuncDeclaration::appendState(Statement *s)
2301 { CompoundStatement *cs; 2244 {
2302
2303 if (!fbody) 2245 if (!fbody)
2304 { Statements *a; 2246 { Statements *a;
2305 2247
2306 a = new Statements(); 2248 a = new Statements();
2307 fbody = new CompoundStatement(0, a); 2249 fbody = new CompoundStatement(0, a);
2308 } 2250 }
2309 cs = fbody->isCompoundStatement(); 2251 CompoundStatement *cs = fbody->isCompoundStatement();
2310 cs->statements->push(s); 2252 cs->statements->push(s);
2311 } 2253 }
2312 2254
2313 const char *FuncDeclaration::toPrettyChars() 2255 const char *FuncDeclaration::toPrettyChars()
2314 { 2256 {
2360 2302
2361 int FuncDeclaration::isVirtual() 2303 int FuncDeclaration::isVirtual()
2362 { 2304 {
2363 #if 0 2305 #if 0
2364 printf("FuncDeclaration::isVirtual(%s)\n", toChars()); 2306 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
2365 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd); 2307 printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2366 printf("result is %d\n", 2308 printf("result is %d\n",
2367 isMember() && 2309 isMember() &&
2368 !(isStatic() || protection == PROTprivate || protection == PROTpackage) && 2310 !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2369 toParent()->isClassDeclaration()); 2311 toParent()->isClassDeclaration());
2370 #endif 2312 #endif
2405 2347
2406 int FuncDeclaration::isNested() 2348 int FuncDeclaration::isNested()
2407 { 2349 {
2408 //if (!toParent()) 2350 //if (!toParent())
2409 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); 2351 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2410 //printf("\ttoParent() = '%s'\n", toParent()->toChars()); 2352 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2411 return ((storage_class & STCstatic) == 0) && toParent2() && 2353 return ((storage_class & STCstatic) == 0) && toParent2() &&
2412 (toParent2()->isFuncDeclaration() != NULL); 2354 (toParent2()->isFuncDeclaration() != NULL);
2413 } 2355 }
2414 2356
2415 int FuncDeclaration::needThis() 2357 int FuncDeclaration::needThis()
3076 Module *m = getModule(); 3018 Module *m = getModule();
3077 if (!m) 3019 if (!m)
3078 m = sc->module; 3020 m = sc->module;
3079 if (m) 3021 if (m)
3080 { m->needmoduleinfo = 1; 3022 { m->needmoduleinfo = 1;
3023 //printf("module2 %s needs moduleinfo\n", m->toChars());
3081 #ifdef IN_GCC 3024 #ifdef IN_GCC
3082 m->strictlyneedmoduleinfo = 1; 3025 m->strictlyneedmoduleinfo = 1;
3083 #endif 3026 #endif
3084 } 3027 }
3085 } 3028 }