Changeset 809
- Timestamp:
- 12/20/10 07:17:34 (14 years ago)
- Files:
-
- trunk/src/func.c (modified) (1 diff)
- trunk/src/mtype.c (modified) (2 diffs)
- trunk/src/template.c (modified) (7 diffs)
- trunk/src/template.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/func.c
r785 r809 1587 1587 fbody = new SynchronizedStatement(loc, vsync, fbody); 1588 1588 fbody = fbody->semantic(sc2); 1589 1589 } 1590 1590 } 1591 1591 else 1592 1592 { 1593 1593 error("synchronized function %s must be a member of a class", toChars()); 1594 1594 } 1595 1595 } 1596 1596 #endif 1597 1597 } 1598 1598 1599 1599 sc2->callSuper = 0; 1600 1600 sc2->pop(); 1601 1601 } 1602 1602 1603 1603 if (global.gag && global.errors != nerrors) 1604 1604 semanticRun = PASSsemanticdone; // Ensure errors get reported again 1605 1605 else 1606 1606 semanticRun = PASSsemantic3done; 1607 //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); 1608 //fflush(stdout); 1607 1609 } 1608 1610 1609 1611 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1610 1612 { 1611 1613 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars()); 1612 1614 1613 1615 StorageClassDeclaration::stcToCBuffer(buf, storage_class); 1614 1616 type->toCBuffer(buf, ident, hgs); 1615 1617 bodyToCBuffer(buf, hgs); 1616 1618 } 1617 1619 1618 1620 int FuncDeclaration::equals(Object *o) 1619 1621 { 1620 1622 if (this == o) 1621 1623 return TRUE; 1622 1624 1623 1625 Dsymbol *s = isDsymbol(o); 1624 1626 if (s) 1625 1627 { 1626 1628 FuncDeclaration *fd = s->isFuncDeclaration(); trunk/src/mtype.c
r786 r809 6050 6050 } 6051 6051 t = cd->type; 6052 6052 break; 6053 6053 } 6054 6054 sd = s->isStructDeclaration(); 6055 6055 if (sd) 6056 6056 { 6057 6057 if (exp->op == TOKsuper) 6058 6058 { 6059 6059 error(loc, "struct %s has no 'super'", sd->toChars()); 6060 6060 goto Lerr; 6061 6061 } 6062 6062 t = sd->type->pointerTo(); 6063 6063 break; 6064 6064 } 6065 6065 } 6066 6066 } 6067 6067 else 6068 6068 #endif 6069 6069 { 6070 sc->intypeof++; 6071 exp = exp->semantic(sc); 6070 Scope *sc2 = sc->push(); 6071 sc2->intypeof++; 6072 exp = exp->semantic(sc2); 6072 6073 #if DMDV2 6073 6074 if (exp->type && exp->type->ty == Tfunction && 6074 6075 ((TypeFunction *)exp->type)->isproperty) 6075 exp = resolveProperties(sc , exp);6076 exp = resolveProperties(sc2, exp); 6076 6077 #endif 6077 sc ->intypeof--;6078 sc2->pop(); 6078 6079 if (exp->op == TOKtype) 6079 6080 { 6080 6081 error(loc, "argument %s to typeof is not an expression", exp->toChars()); 6081 6082 goto Lerr; 6082 6083 } 6083 6084 t = exp->type; 6084 6085 if (!t) 6085 6086 { 6086 6087 error(loc, "expression (%s) has no type", exp->toChars()); 6087 6088 goto Lerr; 6088 6089 } 6089 6090 if (t->ty == Ttypeof) 6090 6091 { error(loc, "forward reference to %s", toChars()); 6091 6092 goto Lerr; 6092 6093 } 6093 6094 6094 6095 /* typeof should reflect the true type, 6095 6096 * not what 'auto' would have gotten us. 6096 6097 */ 6097 6098 //t = t->toHeadMutable(); … … 7128 7129 } 7129 7130 return t->implicitConvTo(to); 7130 7131 } 7131 7132 return MATCHnomatch; 7132 7133 } 7133 7134 7134 7135 MATCH TypeStruct::implicitConvTo(Type *to) 7135 7136 { MATCH m; 7136 7137 7137 7138 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars()); 7138 7139 if (to->ty == Taarray) 7139 7140 { 7140 7141 /* If there is an error instantiating AssociativeArray!(), it shouldn't 7141 7142 * be reported -- it just means implicit conversion is impossible. 7142 7143 */ 7143 7144 ++global.gag; 7144 7145 int errs = global.errors; 7145 7146 to = ((TypeAArray*)to)->getImpl()->type; 7146 7147 --global.gag; 7147 7148 if (errs != global.errors) 7148 { global.errors = errs; 7149 { 7150 global.errors = errs; 7149 7151 return MATCHnomatch; 7150 7152 } 7151 7153 } 7152 7154 7153 7155 if (ty == to->ty && sym == ((TypeStruct *)to)->sym) 7154 7156 { m = MATCHexact; // exact match 7155 7157 if (mod != to->mod) 7156 7158 { 7157 7159 if (MODimplicitConv(mod, to->mod)) 7158 7160 m = MATCHconst; 7159 7161 else 7160 7162 { /* Check all the fields. If they can all be converted, 7161 7163 * allow the conversion. 7162 7164 */ 7163 7165 for (int i = 0; i < sym->fields.dim; i++) 7164 7166 { Dsymbol *s = (Dsymbol *)sym->fields.data[i]; 7165 7167 VarDeclaration *v = s->isVarDeclaration(); 7166 7168 assert(v && v->storage_class & STCfield); 7167 7169 7168 7170 // 'from' type trunk/src/template.c
r801 r809 703 703 if (!flag) 704 704 { 705 705 /* Any parameter left without a type gets the type of 706 706 * its corresponding arg 707 707 */ 708 708 for (int i = 0; i < dedtypes_dim; i++) 709 709 { 710 710 if (!dedtypes->data[i]) 711 711 { assert(i < ti->tiargs->dim); 712 712 dedtypes->data[i] = ti->tiargs->data[i]; 713 713 } 714 714 } 715 715 } 716 716 717 717 #if DMDV2 718 718 if (m && constraint && !(flag & 1)) 719 719 { /* Check to see if constraint is satisfied. 720 720 */ 721 721 makeParamNamesVisibleInConstraint(paramscope); 722 722 Expression *e = constraint->syntaxCopy(); 723 paramscope->flags |= SCOPEstaticif; 724 e = e->semantic(paramscope); 723 Scope *sc = paramscope->push(); 724 sc->flags |= SCOPEstaticif; 725 e = e->semantic(sc); 726 sc->pop(); 725 727 e = e->optimize(WANTvalue | WANTinterpret); 726 728 if (e->isBool(TRUE)) 727 729 ; 728 730 else if (e->isBool(FALSE)) 729 731 goto Lnomatch; 730 732 else 731 733 { 732 734 e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); 733 735 } 734 736 } 735 737 #endif 736 738 737 739 #if LOGM 738 740 // Print out the results 739 741 printf("--------------------------\n"); 740 742 printf("template %s\n", toChars()); 741 743 printf("instance %s\n", ti->toChars()); 742 744 if (m) 743 745 { 744 746 for (int i = 0; i < dedtypes_dim; i++) … … 1291 1293 oded = (Object *)new Tuple(); 1292 1294 } 1293 1295 else 1294 1296 goto Lnomatch; 1295 1297 } 1296 1298 } 1297 1299 declareParameter(paramscope, tparam, oded); 1298 1300 dedargs->data[i] = (void *)oded; 1299 1301 } 1300 1302 } 1301 1303 1302 1304 #if DMDV2 1303 1305 if (constraint) 1304 1306 { /* Check to see if constraint is satisfied. 1305 1307 */ 1306 1308 makeParamNamesVisibleInConstraint(paramscope); 1307 1309 Expression *e = constraint->syntaxCopy(); 1308 1310 paramscope->flags |= SCOPEstaticif; 1309 1311 1310 1312 /* Detect recursive attempts to instantiate this template declaration, 1313 * Bugzilla 4072 1311 1314 * void foo(T)(T x) if (is(typeof(foo(x)))) { } 1312 * static assert(!is(typeof( bug4072(7))));1315 * static assert(!is(typeof(foo(7)))); 1313 1316 * Recursive attempts are regarded as a constraint failure. 1314 1317 */ 1318 int nmatches = 0; 1315 1319 for (Previous *p = previous; p; p = p->prev) 1316 1320 { 1317 1321 if (arrayObjectMatch(p->dedargs, dedargs, this, sc)) 1318 goto Lnomatch; 1322 { 1323 //printf("recursive, no match %p %s\n", this, this->toChars()); 1324 nmatches++; 1325 } 1319 1326 /* BUG: should also check for ref param differences 1320 1327 */ 1321 1328 } 1329 /* Look for 2 matches at least, because sometimes semantic3() gets run causing what appears to 1330 * be recursion but isn't. 1331 * Template A's constraint instantiates B, B's semantic3() run includes something that has A in its constraint. 1332 * Perhaps a better solution is to always defer semantic3() rather than doing it eagerly. The risk 1333 * with that is what if semantic3() fails, but our constraint "succeeded"? 1334 */ 1335 if (nmatches >= 2) 1336 goto Lnomatch; 1337 1322 1338 Previous pr; 1323 1339 pr.prev = previous; 1324 1340 pr.dedargs = dedargs; 1325 1341 previous = ≺ // add this to threaded list 1326 1342 1327 1343 int nerrors = global.errors; 1328 1344 1329 1345 e = e->semantic(paramscope); 1330 1346 1331 1347 previous = pr.prev; // unlink from threaded list 1332 1348 1333 1349 if (nerrors != global.errors) // if any errors from evaluating the constraint, no match 1334 1350 goto Lnomatch; 1335 1351 1336 1352 e = e->optimize(WANTvalue | WANTinterpret); 1337 1353 if (e->isBool(TRUE)) 1338 1354 ; 1339 1355 else if (e->isBool(FALSE)) 1340 1356 goto Lnomatch; 1341 1357 else … … 3832 3848 } 3833 3849 } 3834 3850 } 3835 3851 } 3836 3852 3837 3853 // It's a match 3838 3854 inst = ti; 3839 3855 parent = ti->parent; 3840 3856 #if LOG 3841 3857 printf("\tit's a match with instance %p\n", inst); 3842 3858 #endif 3843 3859 return; 3844 3860 3845 3861 L1: 3846 3862 ; 3847 3863 } 3848 3864 3849 3865 /* So, we need to implement 'this' instance. 3850 3866 */ 3851 3867 #if LOG 3852 printf("\timplement template instance '%s'\n", toChars()); 3868 printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars()); 3869 printf("\ttempdecl %s\n", tempdecl->toChars()); 3853 3870 #endif 3854 3871 unsigned errorsave = global.errors; 3855 3872 inst = this; 3856 3873 int tempdecl_instance_idx = tempdecl->instances.dim; 3857 3874 tempdecl->instances.push(this); 3858 3875 parent = tempdecl->parent; 3859 3876 //printf("parent = '%s'\n", parent->kind()); 3860 3877 3861 ident = genIdent( ); // need an identifier for name mangling purposes.3878 ident = genIdent(tiargs); // need an identifier for name mangling purposes. 3862 3879 3863 3880 #if 1 3864 3881 if (isnested) 3865 3882 parent = isnested; 3866 3883 #endif 3867 3884 //printf("parent = '%s'\n", parent->kind()); 3868 3885 3869 3886 // Add 'this' to the enclosing scope's members[] so the semantic routines 3870 3887 // will get called on the instance members 3871 3888 #if 1 3872 3889 int dosemantic3 = 0; 3873 3890 { Array *a; 3874 3891 3875 3892 Scope *scx = sc; 3876 3893 #if 0 3877 3894 for (scx = sc; scx; scx = scx->enclosing) 3878 3895 if (scx->scopesym) 3879 3896 break; 3880 3897 #endif 3881 3898 … … 3884 3901 scx->scopesym->members && !scx->scopesym->isTemplateMixin() 3885 3902 #if 0 // removed because it bloated compile times 3886 3903 /* The problem is if A imports B, and B imports A, and both A 3887 3904 * and B instantiate the same template, does the compilation of A 3888 3905 * or the compilation of B do the actual instantiation? 3889 3906 * 3890 3907 * see bugzilla 2500. 3891 3908 */ 3892 3909 && !scx->module->selfImports() 3893 3910 #endif 3894 3911 ) 3895 3912 { 3896 3913 //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars()); 3897 3914 a = scx->scopesym->members; 3898 3915 } 3899 3916 else 3900 3917 { Module *m = sc->module->importedFrom; 3901 3918 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); 3902 3919 a = m->members; 3903 3920 if (m->semanticRun >= 3) 3921 { 3904 3922 dosemantic3 = 1; 3923 } 3905 3924 } 3906 3925 for (int i = 0; 1; i++) 3907 3926 { 3908 3927 if (i == a->dim) 3909 3928 { 3910 3929 a->push(this); 3911 3930 break; 3912 3931 } 3913 3932 if (this == (Dsymbol *)a->data[i]) // if already in Array 3914 3933 break; 3915 3934 } 3916 3935 } 3917 3936 #endif 3918 3937 3919 3938 // Copy the syntax trees from the TemplateDeclaration 3920 3939 members = Dsymbol::arraySyntaxCopy(tempdecl->members); 3921 3940 3922 3941 // Create our own scope for the template parameters 3923 3942 Scope *scope = tempdecl->scope; 3924 3943 if (!tempdecl->semanticRun) … … 4086 4105 fatal(); 4087 4106 } 4088 4107 #endif 4089 4108 } 4090 4109 4091 4110 Laftersemantic: 4092 4111 sc2->pop(); 4093 4112 4094 4113 scope->pop(); 4095 4114 4096 4115 // Give additional context info if error occurred during instantiation 4097 4116 if (global.errors != errorsave) 4098 4117 { 4099 4118 error(loc, "error instantiating"); 4100 4119 if (tinst) 4101 4120 { tinst->printInstantiationTrace(); 4102 4121 } 4103 4122 errors = 1; 4104 4123 if (global.gag) 4105 4124 { // Try to reset things so we can try again later to instantiate it 4125 //printf("remove %s\n", toChars()); 4106 4126 tempdecl->instances.remove(tempdecl_instance_idx); 4107 4127 if (!(sc->flags & SCOPEstaticif)) 4108 4128 { // Bugzilla 4302 for discussion 4109 4129 semanticRun = 0; 4110 4130 inst = NULL; 4111 4131 } 4112 4132 } 4113 4133 } 4114 4134 4115 4135 #if LOG 4116 4136 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 4117 4137 #endif 4118 4138 } 4119 4139 4120 4140 4121 4141 void TemplateInstance::semanticTiargs(Scope *sc) 4122 4142 { 4123 4143 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); 4124 4144 if (semantictiargsdone) 4125 4145 return; … … 4590 4610 nested |= 1; 4591 4611 } 4592 4612 else 4593 4613 error("cannot use local '%s' as parameter to non-global template %s", sa->toChars(), tempdecl->toChars()); 4594 4614 } 4595 4615 } 4596 4616 else if (va) 4597 4617 { 4598 4618 nested |= hasNestedArgs(&va->objects); 4599 4619 } 4600 4620 } 4601 4621 return nested; 4602 4622 } 4603 4623 4604 4624 /**************************************** 4605 4625 * This instance needs an identifier for name mangling purposes. 4606 4626 * Create one by taking the template declaration name and adding 4607 4627 * the type signature for it. 4608 4628 */ 4609 4629 4610 Identifier *TemplateInstance::genIdent( )4630 Identifier *TemplateInstance::genIdent(Objects *args) 4611 4631 { OutBuffer buf; 4612 4632 4613 4633 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); 4614 4634 char *id = tempdecl->ident->toChars(); 4615 4635 buf.printf("__T%zu%s", strlen(id), id); 4616 Objects *args = tiargs;4617 4636 for (int i = 0; i < args->dim; i++) 4618 4637 { Object *o = (Object *)args->data[i]; 4619 4638 Type *ta = isType(o); 4620 4639 Expression *ea = isExpression(o); 4621 4640 Dsymbol *sa = isDsymbol(o); 4622 4641 Tuple *va = isTuple(o); 4623 4642 //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va); 4624 4643 if (ta) 4625 4644 { 4626 4645 buf.writeByte('T'); 4627 4646 if (ta->deco) 4628 4647 buf.writestring(ta->deco); 4629 4648 else 4630 4649 { 4631 4650 #ifdef DEBUG 4632 4651 printf("ta = %d, %s\n", ta->ty, ta->toChars()); 4633 4652 #endif 4634 4653 assert(global.errors); 4635 4654 } 4636 4655 } … … 5181 5200 scope = scx ? scx : new Scope(*sc); 5182 5201 scope->setNoFree(); 5183 5202 scope->module->addDeferredSemantic(this); 5184 5203 } 5185 5204 return; 5186 5205 } 5187 5206 } 5188 5207 5189 5208 // Run semantic on each argument, place results in tiargs[] 5190 5209 semanticTiargs(sc); 5191 5210 if (errors) 5192 5211 return; 5193 5212 5194 5213 tempdecl = findBestMatch(sc); 5195 5214 if (!tempdecl) 5196 5215 { inst = this; 5197 5216 return; // error recovery 5198 5217 } 5199 5218 5200 5219 if (!ident) 5201 ident = genIdent( );5220 ident = genIdent(tiargs); 5202 5221 5203 5222 inst = this; 5204 5223 parent = sc->parent; 5205 5224 5206 5225 /* Detect recursive mixin instantiations. 5207 5226 */ 5208 5227 for (Dsymbol *s = parent; s; s = s->parent) 5209 5228 { 5210 5229 //printf("\ts = '%s'\n", s->toChars()); 5211 5230 TemplateMixin *tm = s->isTemplateMixin(); 5212 5231 if (!tm || tempdecl != tm->tempdecl) 5213 5232 continue; 5214 5233 5215 5234 /* Different argument list lengths happen with variadic args 5216 5235 */ 5217 5236 if (tiargs->dim != tm->tiargs->dim) 5218 5237 continue; 5219 5238 5220 5239 for (int i = 0; i < tiargs->dim; i++) 5221 5240 { Object *o = (Object *)tiargs->data[i]; trunk/src/template.h
r495 r809 309 309 void semantic3(Scope *sc); 310 310 void inlineScan(); 311 311 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 312 312 Dsymbol *toAlias(); // resolve real symbol 313 313 const char *kind(); 314 314 int oneMember(Dsymbol **ps); 315 315 int needsTypeInference(Scope *sc); 316 316 char *toChars(); 317 317 char *mangle(); 318 318 void printInstantiationTrace(); 319 319 320 320 void toObjFile(int multiobj); // compile to .obj file 321 321 322 322 // Internal 323 323 static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); 324 324 void semanticTiargs(Scope *sc); 325 325 TemplateDeclaration *findTemplateDeclaration(Scope *sc); 326 326 TemplateDeclaration *findBestMatch(Scope *sc); 327 327 void declareParameters(Scope *sc); 328 328 int hasNestedArgs(Objects *tiargs); 329 Identifier *genIdent( );329 Identifier *genIdent(Objects *args); 330 330 331 331 TemplateInstance *isTemplateInstance() { return this; } 332 332 AliasDeclaration *isAliasDeclaration(); 333 333 }; 334 334 335 335 struct TemplateMixin : TemplateInstance 336 336 { 337 337 Array *idents; 338 338 Type *tqual; 339 339 340 340 TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs); 341 341 Dsymbol *syntaxCopy(Dsymbol *s); 342 342 void semantic(Scope *sc); 343 343 void semantic2(Scope *sc); 344 344 void semantic3(Scope *sc); 345 345 void inlineScan(); 346 346 const char *kind(); 347 347 int oneMember(Dsymbol **ps); 348 348 int hasPointers(); 349 349 char *toChars();
