Mercurial > projects > ldc
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 } |