1: // Compiler implementation of the D programming language
2: // Copyright (c) 1999-2011 by Digital Mars
3: // All Rights Reserved
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:
10: #include <stdio.h>
11: static char __file__[] = __FILE__; /* for tassert.h */
12: #include "tassert.h"
13:
14: #include "mars.h"
15: #include "init.h"
16: #include "declaration.h"
17: #include "attrib.h"
18: #include "expression.h"
19: #include "scope.h"
20: #include "mtype.h"
21: #include "aggregate.h"
22: #include "identifier.h"
23: #include "id.h"
24: #include "module.h"
25: #include "statement.h"
26: #include "template.h"
27: #include "hdrgen.h"
28:
29: #ifdef IN_GCC
30: #include "d-dmd-gcc.h"
31: #endif
32:
33: /********************************* FuncDeclaration ****************************/
34:
35: FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
36: : Declaration(id)
37: {
38: //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
39: //printf("storage_class = x%x\n", storage_class);
40: this->storage_class = storage_class;
41: this->type = type;
42: this->loc = loc;
43: this->endloc = endloc;
44: fthrows = NULL;
45: frequire = NULL;
46: fdrequire = NULL;
47: fdensure = NULL;
48: outId = NULL;
49: vresult = NULL;
50: returnLabel = NULL;
51: fensure = NULL;
52: fbody = NULL;
53: localsymtab = NULL;
54: vthis = NULL;
55: v_arguments = NULL;
56: #if IN_GCC
57: v_argptr = NULL;
58: #endif
59: v_argsave = NULL;
60: parameters = NULL;
61: labtab = NULL;
62: overnext = NULL;
63: vtblIndex = -1;
64: hasReturnExp = 0;
65: naked = 0;
66: inlineStatus = ILSuninitialized;
67: inlineNest = 0;
68: cantInterpret = 0;
69: isArrayOp = 0;
70: semanticRun = PASSinit;
71: #if DMDV1
72: nestedFrameRef = 0;
73: #endif
74: fes = NULL;
75: introducing = 0;
76: tintro = NULL;
77: /* The type given for "infer the return type" is a TypeFunction with
78: * NULL for the return type.
79: */
80: inferRetType = (type && type->nextOf() == NULL);
81: hasReturnExp = 0;
82: nrvo_can = 1;
83: nrvo_var = NULL;
84: shidden = NULL;
85: #if DMDV2
86: builtin = BUILTINunknown;
87: tookAddressOf = 0;
88: flags = 0;
89: #endif
90: }
91:
92: Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
93: {
94: FuncDeclaration *f;
95:
96: //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
97: if (s)
98: f = (FuncDeclaration *)s;
99: else
100: f = new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
101: f->outId = outId;
102: f->frequire = frequire ? frequire->syntaxCopy() : NULL;
103: f->fensure = fensure ? fensure->syntaxCopy() : NULL;
104: f->fbody = fbody ? fbody->syntaxCopy() : NULL;
105: assert(!fthrows); // deprecated
106: return f;
107: }
108:
109:
110: // Do the semantic analysis on the external interface to the function.
111:
112: void FuncDeclaration::semantic(Scope *sc)
113: { TypeFunction *f;
114: AggregateDeclaration *ad;
115: StructDeclaration *sd;
116: ClassDeclaration *cd;
117: InterfaceDeclaration *id;
118: Dsymbol *pd;
119:
120: #if 0
121: printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
122: if (isFuncLiteralDeclaration())
123: printf("\tFuncLiteralDeclaration()\n");
124: printf("sc->parent = %s, parent = %s\n", sc->parent->toChars(), parent ? parent->toChars() : "");
125: printf("type: %p, %s\n", type, type->toChars());
126: #endif
127:
128: if (semanticRun != PASSinit && isFuncLiteralDeclaration())
129: {
130: /* Member functions that have return types that are
131: * forward references can have semantic() run more than
132: * once on them.
133: * See test\interface2.d, test20
134: */
135: return;
136: }
137:
138: parent = sc->parent;
139: Dsymbol *parent = toParent();
140:
141: if (semanticRun >= PASSsemanticdone)
142: {
143: if (!parent->isClassDeclaration())
144: {
145: return;
146: }
147: // need to re-run semantic() in order to set the class's vtbl[]
148: }
149: else
150: {
151: assert(semanticRun <= PASSsemantic);
152: semanticRun = PASSsemantic;
153: }
154:
155: unsigned dprogress_save = Module::dprogress;
156:
157: foverrides.setDim(0); // reset in case semantic() is being retried for this function
158:
159: storage_class |= sc->stc & ~STCref;
160: ad = isThis();
161: if (ad)
162: storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
163:
164: //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
165:
166: if (!originalType)
167: originalType = type;
168: if (!type->deco)
169: {
170: sc = sc->push();
171: sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable
172: | STCsafe | STCtrusted | STCsystem | STCproperty); // forward to function type
173:
174: if (isCtorDeclaration())
175: sc->flags |= SCOPEctor;
176: type = type->semantic(loc, sc);
177: sc = sc->pop();
178:
179: /* Apply const, immutable and shared storage class
180: * to the function type
181: */
182: StorageClass stc = storage_class;
183: if (type->isImmutable())
184: stc |= STCimmutable;
185: if (type->isConst())
186: stc |= STCconst;
187: if (type->isShared() || storage_class & STCsynchronized)
188: stc |= STCshared;
189: if (type->isWild())
190: stc |= STCwild;
191: switch (stc & STC_TYPECTOR)
192: {
193: case STCimmutable:
194: case STCimmutable | STCconst:
195: case STCimmutable | STCconst | STCshared:
196: case STCimmutable | STCshared:
197: case STCimmutable | STCwild:
198: case STCimmutable | STCconst | STCwild:
199: case STCimmutable | STCconst | STCshared | STCwild:
200: case STCimmutable | STCshared | STCwild:
201: // Don't use toInvariant(), as that will do a merge()
202: type = type->makeInvariant();
203: goto Lmerge;
204:
205: case STCconst:
206: case STCconst | STCwild:
207: type = type->makeConst();
208: goto Lmerge;
209:
210: case STCshared | STCconst:
211: case STCshared | STCconst | STCwild:
212: type = type->makeSharedConst();
213: goto Lmerge;
214:
215: case STCshared:
216: type = type->makeShared();
217: goto Lmerge;
218:
219: case STCwild:
220: type = type->makeWild();
221: goto Lmerge;
222:
223: case STCshared | STCwild:
224: type = type->makeSharedWild();
225: goto Lmerge;
226:
227: Lmerge:
228: if (!(type->ty == Tfunction && !type->nextOf()))
229: /* Can't do merge if return type is not known yet
230: */
231: type->deco = type->merge()->deco;
232: break;
233:
234: case 0:
235: break;
236:
237: default:
238: assert(0);
239: }
240: }
241: storage_class &= ~STCref;
242: if (type->ty != Tfunction)
243: {
244: error("%s must be a function instead of %s", toChars(), type->toChars());
245: return;
246: }
247: f = (TypeFunction *)(type);
248: size_t nparams = Parameter::dim(f->parameters);
249:
250: linkage = sc->linkage;
251: protection = sc->protection;
252:
253: /* Purity and safety can be inferred for some functions by examining
254: * the function body.
255: */
256: if (fbody &&
257: (isFuncLiteralDeclaration() || parent->isTemplateInstance()))
258: {
259: if (f->purity == PUREimpure && // purity not specified
260: !f->hasLazyParameters()
261: )
262: {
263: flags |= FUNCFLAGpurityInprocess;
264: }
265: if (f->trust == TRUSTdefault)
266: flags |= FUNCFLAGsafetyInprocess;
267:
268: if (!f->isnothrow)
269: flags |= FUNCFLAGnothrowInprocess;
270: }
271:
272: if (storage_class & STCscope)
273: error("functions cannot be scope");
274:
275: if (isAbstract() && !isVirtual())
276: error("non-virtual functions cannot be abstract");
277:
278: if ((f->isConst() || f->isImmutable()) && !isThis())
279: error("without 'this' cannot be const/immutable");
280:
281: if (isAbstract() && isFinal())
282: error("cannot be both final and abstract");
283: #if 0
284: if (isAbstract() && fbody)
285: error("abstract functions cannot have bodies");
286: #endif
287:
288: #if 0
289: if (isStaticConstructor() || isStaticDestructor())
290: {
291: if (!isStatic() || type->nextOf()->ty != Tvoid)
292: error("static constructors / destructors must be static void");
293: if (f->arguments && f->arguments->dim)
294: error("static constructors / destructors must have empty parameter list");
295: // BUG: check for invalid storage classes
296: }
297: #endif
298:
299: #ifdef IN_GCC
300: {
301: AggregateDeclaration *ad = parent->isAggregateDeclaration();
302: if (ad)
303: ad->methods.push(this);
304: }
305: #endif
306: sd = parent->isStructDeclaration();
307: if (sd)
308: {
309: if (isCtorDeclaration())
310: {
311: goto Ldone;
312: }
313: #if 0
314: // Verify no constructors, destructors, etc.
315: if (isCtorDeclaration()
316: //||isDtorDeclaration()
317: //|| isInvariantDeclaration()
318: //|| isUnitTestDeclaration()
319: )
320: {
321: error("special member functions not allowed for %ss", sd->kind());
322: }
323:
324: if (!sd->inv)
325: sd->inv = isInvariantDeclaration();
326:
327: if (!sd->aggNew)
328: sd->aggNew = isNewDeclaration();
329:
330: if (isDelete())
331: {
332: if (sd->aggDelete)
333: error("multiple delete's for struct %s", sd->toChars());
334: sd->aggDelete = (DeleteDeclaration *)(this);
335: }
336: #endif
337: }
338:
339: id = parent->isInterfaceDeclaration();
340: if (id)
341: {
342: storage_class |= STCabstract;
343:
344: if (isCtorDeclaration() ||
345: #if DMDV2
346: isPostBlitDeclaration() ||
347: #endif
348: isDtorDeclaration() ||
349: isInvariantDeclaration() ||
350: isUnitTestDeclaration() || isNewDeclaration() || isDelete())
351: error("constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface %s", id->toChars());
352: if (fbody && isVirtual())
353: error("function body is not abstract in interface %s", id->toChars());
354: }
355:
356: /* Contracts can only appear without a body when they are virtual interface functions
357: */
358: if (!fbody && (fensure || frequire) && !(id && isVirtual()))
359: error("in and out contracts require function body");
360:
361: /* Template member functions aren't virtual:
362: * interface TestInterface { void tpl(T)(); }
363: * and so won't work in interfaces
364: */
365: if ((pd = toParent()) != NULL &&
366: pd->isTemplateInstance() &&
367: (pd = toParent2()) != NULL &&
368: (id = pd->isInterfaceDeclaration()) != NULL)
369: {
370: error("template member functions are not allowed in interface %s", id->toChars());
371: }
372:
373: cd = parent->isClassDeclaration();
374: if (cd)
375: { int vi;
376: CtorDeclaration *ctor;
warning C4101: 'ctor' : unreferenced local variable
377: DtorDeclaration *dtor;
warning C4101: 'dtor' : unreferenced local variable
378: InvariantDeclaration *inv;
warning C4101: 'inv' : unreferenced local variable
379:
380: if (isCtorDeclaration())
381: {
382: // ctor = (CtorDeclaration *)this;
383: // if (!cd->ctor)
384: // cd->ctor = ctor;
385: return;
386: }
387:
388: #if 0
389: dtor = isDtorDeclaration();
390: if (dtor)
391: {
392: if (cd->dtor)
393: error("multiple destructors for class %s", cd->toChars());
394: cd->dtor = dtor;
395: }
396:
397: inv = isInvariantDeclaration();
398: if (inv)
399: {
400: cd->inv = inv;
401: }
402:
403: if (isNewDeclaration())
404: {
405: if (!cd->aggNew)
406: cd->aggNew = (NewDeclaration *)(this);
407: }
408:
409: if (isDelete())
410: {
411: if (cd->aggDelete)
412: error("multiple delete's for class %s", cd->toChars());
413: cd->aggDelete = (DeleteDeclaration *)(this);
414: }
415: #endif
416:
417: if (storage_class & STCabstract)
418: cd->isabstract = 1;
419:
420: // if static function, do not put in vtbl[]
421: if (!isVirtual())
422: {
423: //printf("\tnot virtual\n");
424: goto Ldone;
425: }
426:
427: /* Find index of existing function in base class's vtbl[] to override
428: * (the index will be the same as in cd's current vtbl[])
429: */
430: vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
431: : -1;
432:
433: switch (vi)
434: {
435: case -1:
436: /* Didn't find one, so
437: * This is an 'introducing' function which gets a new
438: * slot in the vtbl[].
439: */
440:
441: // Verify this doesn't override previous final function
442: if (cd->baseClass)
443: { Dsymbol *s = cd->baseClass->search(loc, ident, 0);
444: if (s)
445: {
446: FuncDeclaration *f = s->isFuncDeclaration();
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '113' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 113
447: f = f->overloadExactMatch(type);
448: if (f && f->isFinal() && f->prot() != PROTprivate)
449: error("cannot override final function %s", f->toPrettyChars());
450: }
451: }
452:
453: if (isFinal())
454: {
455: if (isOverride())
456: error("is marked as override, but does not override any function");
457: cd->vtblFinal.push(this);
458: }
459: else
460: {
461: // Append to end of vtbl[]
462: //printf("\tintroducing function\n");
463: introducing = 1;
464: vi = cd->vtbl.dim;
465: cd->vtbl.push(this);
466: vtblIndex = vi;
467: }
468: break;
469:
470: case -2: // can't determine because of fwd refs
471: cd->sizeok = 2; // can't finish due to forward reference
472: Module::dprogress = dprogress_save;
473: return;
474:
475: default:
476: { FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.tdata()[vi];
477: // This function is covariant with fdv
478: if (fdv->isFinal())
479: error("cannot override final function %s", fdv->toPrettyChars());
480:
481: #if DMDV2
482: if (!isOverride())
483: warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
484: #endif
485:
486: if (fdv->toParent() == parent)
487: {
488: // If both are mixins, then error.
489: // If either is not, the one that is not overrides
490: // the other.
491: if (fdv->parent->isClassDeclaration())
492: break;
493: if (!this->parent->isClassDeclaration()
494: #if !BREAKABI
495: && !isDtorDeclaration()
496: #endif
497: #if DMDV2
498: && !isPostBlitDeclaration()
499: #endif
500: )
501: error("multiple overrides of same function");
502: }
503: cd->vtbl.tdata()[vi] = this;
504: vtblIndex = vi;
505:
506: /* Remember which functions this overrides
507: */
508: foverrides.push(fdv);
509:
510: /* This works by whenever this function is called,
511: * it actually returns tintro, which gets dynamically
512: * cast to type. But we know that tintro is a base
513: * of type, so we could optimize it by not doing a
514: * dynamic cast, but just subtracting the isBaseOf()
515: * offset if the value is != null.
516: */
517:
518: if (fdv->tintro)
519: tintro = fdv->tintro;
520: else if (!type->equals(fdv->type))
521: {
522: /* Only need to have a tintro if the vptr
523: * offsets differ
524: */
525: int offset;
526: if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
527: {
528: tintro = fdv->type;
529: }
530: }
531: break;
532: }
533: }
534:
535: /* Go through all the interface bases.
536: * If this function is covariant with any members of those interface
537: * functions, set the tintro.
538: */
539: for (int i = 0; i < cd->interfaces_dim; i++)
540: {
541: BaseClass *b = cd->interfaces[i];
542: vi = findVtblIndex((Dsymbols *)&b->base->vtbl, b->base->vtbl.dim);
543: switch (vi)
544: {
545: case -1:
546: break;
547:
548: case -2:
549: cd->sizeok = 2; // can't finish due to forward reference
550: Module::dprogress = dprogress_save;
551: return;
552:
553: default:
554: { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi];
555: Type *ti = NULL;
556:
557: /* Remember which functions this overrides
558: */
559: foverrides.push(fdv);
560:
561: if (fdv->tintro)
562: ti = fdv->tintro;
563: else if (!type->equals(fdv->type))
564: {
565: /* Only need to have a tintro if the vptr
566: * offsets differ
567: */
568: unsigned errors = global.errors;
569: global.gag++; // suppress printing of error messages
570: int offset;
571: int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset);
572: global.gag--; // suppress printing of error messages
573: if (errors != global.errors)
574: {
575: // any error in isBaseOf() is a forward reference error, so we bail out
576: global.errors = errors;
577: cd->sizeok = 2; // can't finish due to forward reference
578: Module::dprogress = dprogress_save;
579: return;
580: }
581: if (baseOf)
582: {
583: ti = fdv->type;
584: }
585: }
586: if (ti)
587: {
588: if (tintro && !tintro->equals(ti))
589: {
590: error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
591: }
592: tintro = ti;
593: }
594: goto L2;
595: }
596: }
597: }
598:
599: if (introducing && isOverride())
600: {
601: error("does not override any function");
602: }
603:
604: L2: ;
605:
606: /* Go through all the interface bases.
607: * Disallow overriding any final functions in the interface(s).
608: */
609: for (int i = 0; i < cd->interfaces_dim; i++)
610: {
611: BaseClass *b = cd->interfaces[i];
612: if (b->base)
613: {
614: Dsymbol *s = search_function(b->base, ident);
615: if (s)
616: {
617: FuncDeclaration *f = s->isFuncDeclaration();
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '113' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 113
618: if (f)
619: {
620: f = f->overloadExactMatch(type);
621: if (f && f->isFinal() && f->prot() != PROTprivate)
622: error("cannot override final function %s.%s", b->base->toChars(), f->toPrettyChars());
623: }
624: }
625: }
626: }
627: }
628: else if (isOverride() && !parent->isTemplateInstance())
629: error("override only applies to class member functions");
630:
631: /* Do not allow template instances to add virtual functions
632: * to a class.
633: */
634: if (isVirtual())
635: {
636: TemplateInstance *ti = parent->isTemplateInstance();
637: if (ti)
638: {
639: // Take care of nested templates
640: while (1)
641: {
642: TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
643: if (!ti2)
644: break;
645: ti = ti2;
646: }
647:
648: // If it's a member template
649: ClassDeclaration *cd = ti->tempdecl->isClassMember();
warning C6246: Local declaration of 'cd' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '116' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 116
650: if (cd)
651: {
652: error("cannot use template to add virtual function to class '%s'", cd->toChars());
653: }
654: }
655: }
656:
657: if (isMain())
658: {
659: // Check parameters to see if they are either () or (char[][] args)
660: switch (nparams)
661: {
662: case 0:
663: break;
664:
665: case 1:
666: {
667: Parameter *arg0 = Parameter::getNth(f->parameters, 0);
668: if (arg0->type->ty != Tarray ||
669: arg0->type->nextOf()->ty != Tarray ||
670: arg0->type->nextOf()->nextOf()->ty != Tchar ||
671: arg0->storageClass & (STCout | STCref | STClazy))
672: goto Lmainerr;
673: break;
674: }
675:
676: default:
677: goto Lmainerr;
678: }
679:
680: if (!f->nextOf())
681: error("must return int or void");
682: else if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid)
683: error("must return int or void, not %s", f->nextOf()->toChars());
684: if (f->varargs)
685: {
686: Lmainerr:
687: error("parameters must be main() or main(string[] args)");
688: }
689: }
690:
691: if (ident == Id::assign && (sd || cd))
692: { // Disallow identity assignment operator.
693:
694: // opAssign(...)
695: if (nparams == 0)
696: { if (f->varargs == 1)
697: goto Lassignerr;
698: }
699: else
700: {
701: Parameter *arg0 = Parameter::getNth(f->parameters, 0);
702: Type *t0 = arg0->type->toBasetype();
703: Type *tb = sd ? sd->type : cd->type;
704: if (arg0->type->implicitConvTo(tb) ||
705: (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
706: )
707: {
708: if (nparams == 1)
709: goto Lassignerr;
710: Parameter *arg1 = Parameter::getNth(f->parameters, 1);
711: if (arg1->defaultArg)
712: goto Lassignerr;
713: }
714: }
715: }
716:
717: if (isVirtual() && semanticRun != PASSsemanticdone)
718: {
719: /* Rewrite contracts as nested functions, then call them.
720: * Doing it as nested functions means that overriding functions
721: * can call them.
722: */
723: if (frequire)
724: { /* in { ... }
725: * becomes:
726: * void __require() { ... }
727: * __require();
728: */
729: Loc loc = frequire->loc;
730: TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd);
731: FuncDeclaration *fd = new FuncDeclaration(loc, loc,
732: Id::require, STCundefined, tf);
733: fd->fbody = frequire;
734: Statement *s1 = new ExpStatement(loc, fd);
warning C6211: Leaking memory 's1' due to an exception. Consider using a local catch block to clean up memory: Lines: 113, 114, 115, 116, 117, 118, 128, 138, 139, 141, 151, 152, 155, 157, 159, 160, 161, 162, 166, 168, 170, 171, 174, 175, 176, 177, 182, 183, 184, 185, 186, 187, 189, 190, 191, 193, 194, 195, 196, 197, 198, 199, 200, 202, 203, 227, 228, 241, 242, 247, 248, 250, 251, 256, 272, 273, 275, 276, 278, 281, 282, 306, 307, 309, 339, 340, 342, 350, 352, 353, 358, 367, 373, 374, 375, 376, 377, 378, 380, 417, 418, 421, 430, 433, 435, 442, 453, 455, 456, 457, 539, 599, 604, 609, 634, 636, 637, 640, 642, 643, 649, 650, 652, 657, 660, 662, 680, 681, 684, 686, 687, 691, 717, 723, 729, 730, 731, 733, 734, 735
735: Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), (Expressions *)NULL);
736: Statement *s2 = new ExpStatement(loc, e);
737: frequire = new CompoundStatement(loc, s1, s2);
738: fdrequire = fd;
739: }
740:
741: if (!outId && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid)
742: outId = Id::result; // provide a default
743:
744: if (fensure)
745: { /* out (result) { ... }
746: * becomes:
747: * tret __ensure(ref tret result) { ... }
748: * __ensure(result);
749: */
750: Loc loc = fensure->loc;
751: Parameters *arguments = new Parameters();
warning C6211: Leaking memory 'arguments' due to an exception. Consider using a local catch block to clean up memory: Lines: 113, 114, 115, 116, 117, 118, 128, 138, 139, 141, 151, 152, 155, 157, 159, 160, 161, 162, 166, 168, 170, 171, 174, 175, 176, 177, 182, 183, 184, 185, 186, 187, 189, 190, 191, 193, 194, 195, 196, 197, 198, 199, 200, 202, 203, 227, 228, 241, 242, 247, 248, 250, 251, 256, 272, 273, 275, 276, 278, 281, 282, 306, 307, 309, 339, 340, 342, 350, 352, 353, 358, 367, 373, 374, 375, 376, 377, 378, 380, 417, 418, 421, 430, 433, 435, 442, 453, 455, 456, 457, 539, 599, 604, 609, 634, 636, 637, 640, 642, 643, 649, 650, 652, 657, 660, 662, 680, 681, 684, 686, 687, 691, 717, 723, 729, 730, 731, 733, 734, 735, 736, 737, 738, 741, 744, 750, 751, 752, 753, 754
752: Parameter *a = NULL;
753: if (outId)
754: { a = new Parameter(STCref | STCconst, f->nextOf(), outId, NULL);
755: arguments->push(a);
756: }
757: TypeFunction *tf = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
758: FuncDeclaration *fd = new FuncDeclaration(loc, loc,
759: Id::ensure, STCundefined, tf);
760: fd->fbody = fensure;
761: Statement *s1 = new ExpStatement(loc, fd);
762: Expression *eresult = NULL;
763: if (outId)
764: eresult = new IdentifierExp(loc, outId);
765: Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), eresult);
766: Statement *s2 = new ExpStatement(loc, e);
767: fensure = new CompoundStatement(loc, s1, s2);
768: fdensure = fd;
769: }
770: }
771:
772: Ldone:
773: Module::dprogress++;
774: semanticRun = PASSsemanticdone;
775:
776: /* Save scope for possible later use (if we need the
777: * function internals)
778: */
779: scope = new Scope(*sc);
780: scope->setNoFree();
781: return;
782:
783: Lassignerr:
784: if (sd)
785: {
786: sd->hasIdentityAssign = 1; // don't need to generate it
787: goto Ldone;
788: }
789: error("identity assignment operator overload is illegal");
790: }
791:
792: void FuncDeclaration::semantic2(Scope *sc)
793: {
794: }
795:
796: // Do the semantic analysis on the internals of the function.
797:
798: void FuncDeclaration::semantic3(Scope *sc)
799: { TypeFunction *f;
800: VarDeclaration *argptr = NULL;
801: VarDeclaration *_arguments = NULL;
802: int nerrors = global.errors;
803:
804: if (!parent)
805: {
806: if (global.errors)
807: return;
808: //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
809: assert(0);
810: }
811: //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
812: //fflush(stdout);
813: //printf("storage class = x%x %x\n", sc->stc, storage_class);
814: //{ static int x; if (++x == 2) *(char*)0=0; }
815: //printf("\tlinkage = %d\n", sc->linkage);
816:
817: //printf(" sc->incontract = %d\n", sc->incontract);
818: if (semanticRun >= PASSsemantic3)
819: return;
820: semanticRun = PASSsemantic3;
821:
822: if (!type || type->ty != Tfunction)
823: return;
824: f = (TypeFunction *)(type);
825:
826: #if 0
827: // Check the 'throws' clause
828: if (fthrows)
829: {
830: for (int i = 0; i < fthrows->dim; i++)
831: {
832: Type *t = fthrows->tdata()[i];
833:
834: t = t->semantic(loc, sc);
835: if (!t->isClassHandle())
836: error("can only throw classes, not %s", t->toChars());
837: }
838: }
839: #endif
840:
841: if (frequire)
842: {
843: for (int i = 0; i < foverrides.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
844: {
845: FuncDeclaration *fdv = foverrides.tdata()[i];
846:
847: if (fdv->fbody && !fdv->frequire)
848: {
849: error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
850: break;
851: }
852: }
853: }
854:
855: frequire = mergeFrequire(frequire);
856: fensure = mergeFensure(fensure);
857:
858: if (fbody || frequire || fensure)
859: {
860: /* Symbol table into which we place parameters and nested functions,
861: * solely to diagnose name collisions.
862: */
863: localsymtab = new DsymbolTable();
864:
865: // Establish function scope
866: ScopeDsymbol *ss = new ScopeDsymbol();
867: ss->parent = sc->scopesym;
868: Scope *sc2 = sc->push(ss);
869: sc2->func = this;
870: sc2->parent = this;
871: sc2->callSuper = 0;
872: sc2->sbreak = NULL;
873: sc2->scontinue = NULL;
874: sc2->sw = NULL;
875: sc2->fes = fes;
876: sc2->linkage = LINKd;
877: sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated |
878: STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref |
879: STCproperty | STCsafe | STCtrusted | STCsystem);
880: sc2->protection = PROTpublic;
881: sc2->explicitProtection = 0;
882: sc2->structalign = 8;
883: sc2->incontract = 0;
884: sc2->tf = NULL;
885: sc2->noctor = 0;
886:
887: // Declare 'this'
888: AggregateDeclaration *ad = isThis();
889: if (ad)
890: { VarDeclaration *v;
891:
892: if (isFuncLiteralDeclaration() && isNested() && !sc->intypeof)
893: {
894: error("function literals cannot be class members");
895: return;
896: }
897: else
898: {
899: assert(!isNested() || sc->intypeof); // can't be both member and nested
900: assert(ad->handle);
901: Type *thandle = ad->handle;
902: #if STRUCTTHISREF
903: thandle = thandle->addMod(type->mod);
904: thandle = thandle->addStorageClass(storage_class);
905: //if (isPure())
906: //thandle = thandle->addMod(MODconst);
907: #else
908: if (storage_class & STCconst || type->isConst())
909: {
910: assert(0); // BUG: shared not handled
911: if (thandle->ty == Tclass)
912: thandle = thandle->constOf();
913: else
914: { assert(thandle->ty == Tpointer);
915: thandle = thandle->nextOf()->constOf()->pointerTo();
916: }
917: }
918: else if (storage_class & STCimmutable || type->isImmutable())
919: {
920: if (thandle->ty == Tclass)
921: thandle = thandle->invariantOf();
922: else
923: { assert(thandle->ty == Tpointer);
924: thandle = thandle->nextOf()->invariantOf()->pointerTo();
925: }
926: }
927: else if (storage_class & STCshared || type->isShared())
928: {
929: assert(0); // not implemented
930: }
931: #endif
932: v = new ThisDeclaration(loc, thandle);
933: //v = new ThisDeclaration(loc, isCtorDeclaration() ? ad->handle : thandle);
934: v->storage_class |= STCparameter;
935: #if STRUCTTHISREF
936: if (thandle->ty == Tstruct)
937: v->storage_class |= STCref;
938: #endif
939: v->semantic(sc2);
940: if (!sc2->insert(v))
941: assert(0);
942: v->parent = this;
943: vthis = v;
944: }
945: }
946: else if (isNested())
947: {
948: /* The 'this' for a nested function is the link to the
949: * enclosing function's stack frame.
950: * Note that nested functions and member functions are disjoint.
951: */
952: VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo());
953: v->storage_class |= STCparameter;
954: v->semantic(sc2);
955: if (!sc2->insert(v))
956: assert(0);
957: v->parent = this;
958: vthis = v;
959: }
960:
961: // Declare hidden variable _arguments[] and _argptr
962: if (f->varargs == 1)
963: {
964: #if TARGET_NET
965: varArgs(sc2, f, argptr, _arguments);
966: #else
967: Type *t;
968:
969: if (global.params.is64bit)
970: { // Declare save area for varargs registers
971: Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '967' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 967
972: t = t->semantic(loc, sc);
973: if (t == Type::terror)
974: error("must import core.vararg to use variadic functions");
975: else
976: {
977: v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
978: v_argsave->semantic(sc2);
979: sc2->insert(v_argsave);
980: v_argsave->parent = this;
981: }
982: }
983:
984: if (f->linkage == LINKd)
985: { // Declare _arguments[]
986: #if BREAKABI
987: v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
988: v_arguments->storage_class = STCparameter;
989: v_arguments->semantic(sc2);
990: sc2->insert(v_arguments);
991: v_arguments->parent = this;
992:
993: //t = Type::typeinfo->type->constOf()->arrayOf();
994: t = Type::typeinfo->type->arrayOf();
995: _arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
996: _arguments->semantic(sc2);
997: sc2->insert(_arguments);
998: _arguments->parent = this;
999: #else
1000: t = Type::typeinfo->type->arrayOf();
1001: v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
1002: v_arguments->storage_class = STCparameter | STCin;
1003: v_arguments->semantic(sc2);
1004: sc2->insert(v_arguments);
1005: v_arguments->parent = this;
1006: #endif
1007: }
1008: if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
1009: { // Declare _argptr
1010: #if IN_GCC
1011: t = d_gcc_builtin_va_list_d_type;
1012: #else
1013: t = Type::tvoid->pointerTo();
1014: #endif
1015: argptr = new VarDeclaration(0, t, Id::_argptr, NULL);
1016: argptr->semantic(sc2);
1017: sc2->insert(argptr);
1018: argptr->parent = this;
1019: }
1020: #endif
1021: }
1022:
1023: #if 0
1024: // Propagate storage class from tuple parameters to their element-parameters.
1025: if (f->parameters)
1026: {
1027: for (size_t i = 0; i < f->parameters->dim; i++)
1028: { Parameter *arg = f->parameters->tdata()[i];
1029:
1030: //printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars());
1031: if (arg->type->ty == Ttuple)
1032: { TypeTuple *t = (TypeTuple *)arg->type;
1033: size_t dim = Parameter::dim(t->arguments);
1034: for (size_t j = 0; j < dim; j++)
1035: { Parameter *narg = Parameter::getNth(t->arguments, j);
1036: narg->storageClass = arg->storageClass;
1037: }
1038: }
1039: }
1040: }
1041: #endif
1042:
1043: /* Declare all the function parameters as variables
1044: * and install them in parameters[]
1045: */
1046: size_t nparams = Parameter::dim(f->parameters);
1047: if (nparams)
1048: { /* parameters[] has all the tuples removed, as the back end
1049: * doesn't know about tuples
1050: */
1051: parameters = new VarDeclarations();
1052: parameters->reserve(nparams);
1053: for (size_t i = 0; i < nparams; i++)
1054: {
1055: Parameter *arg = Parameter::getNth(f->parameters, i);
1056: Identifier *id = arg->ident;
1057: if (!id)
1058: {
1059: /* Generate identifier for un-named parameter,
1060: * because we need it later on.
1061: */
1062: arg->ident = id = Identifier::generateId("_param_", i);
1063: }
1064: Type *vtype = arg->type;
1065: //if (isPure())
1066: //vtype = vtype->addMod(MODconst);
1067: VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
1068: //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
1069: v->storage_class |= STCparameter;
1070: if (f->varargs == 2 && i + 1 == nparams)
1071: v->storage_class |= STCvariadic;
1072: v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
1073: v->semantic(sc2);
1074: if (!sc2->insert(v))
1075: error("parameter %s.%s is already defined", toChars(), v->toChars());
1076: else
1077: parameters->push(v);
1078: localsymtab->insert(v);
1079: v->parent = this;
1080: }
1081: }
1082:
1083: // Declare the tuple symbols and put them in the symbol table,
1084: // but not in parameters[].
1085: if (f->parameters)
1086: {
1087: for (size_t i = 0; i < f->parameters->dim; i++)
1088: { Parameter *arg = f->parameters->tdata()[i];
1089:
1090: if (!arg->ident)
1091: continue; // never used, so ignore
1092: if (arg->type->ty == Ttuple)
1093: { TypeTuple *t = (TypeTuple *)arg->type;
1094: size_t dim = Parameter::dim(t->arguments);
1095: Objects *exps = new Objects();
1096: exps->setDim(dim);
1097: for (size_t j = 0; j < dim; j++)
1098: { Parameter *narg = Parameter::getNth(t->arguments, j);
1099: assert(narg->ident);
1100: VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
1101: assert(v);
1102: Expression *e = new VarExp(v->loc, v);
1103: exps->tdata()[j] = e;
1104: }
1105: assert(arg->ident);
1106: TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
1107: //printf("declaring tuple %s\n", v->toChars());
1108: v->isexp = 1;
1109: if (!sc2->insert(v))
1110: error("parameter %s.%s is already defined", toChars(), v->toChars());
1111: localsymtab->insert(v);
1112: v->parent = this;
1113: }
1114: }
1115: }
1116:
1117: /* Do the semantic analysis on the [in] preconditions and
1118: * [out] postconditions.
1119: */
1120: sc2->incontract++;
1121:
1122: if (frequire)
1123: { /* frequire is composed of the [in] contracts
1124: */
1125: // BUG: need to error if accessing out parameters
1126: // BUG: need to treat parameters as const
1127: // BUG: need to disallow returns and throws
1128: // BUG: verify that all in and ref parameters are read
1129: frequire = frequire->semantic(sc2);
1130: labtab = NULL; // so body can't refer to labels
1131: }
1132:
1133: if (fensure || addPostInvariant())
1134: { /* fensure is composed of the [out] contracts
1135: */
1136: if (!type->nextOf()) // if return type is inferred
1137: { /* This case:
1138: * auto fp = function() out { } body { };
1139: * Can fix by doing semantic() onf fbody first.
1140: */
1141: error("post conditions are not supported if the return type is inferred");
1142: return;
1143: }
1144:
1145: ScopeDsymbol *sym = new ScopeDsymbol();
1146: sym->parent = sc2->scopesym;
1147: sc2 = sc2->push(sym);
1148:
1149: assert(type->nextOf());
1150: if (type->nextOf()->ty == Tvoid)
1151: {
1152: if (outId)
1153: error("void functions have no result");
1154: }
1155: else
1156: {
1157: if (!outId)
1158: outId = Id::result; // provide a default
1159: }
1160:
1161: if (outId)
1162: { // Declare result variable
1163: Loc loc = this->loc;
1164:
1165: if (fensure)
1166: loc = fensure->loc;
1167:
1168: VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
1169: v->noscope = 1;
1170: v->storage_class |= STCresult;
1171: #if DMDV2
1172: if (!isVirtual())
1173: v->storage_class |= STCconst;
1174: if (f->isref)
1175: {
1176: v->storage_class |= STCref | STCforeach;
1177: }
1178: #endif
1179: sc2->incontract--;
1180: v->semantic(sc2);
1181: sc2->incontract++;
1182: if (!sc2->insert(v))
1183: error("out result %s is already defined", v->toChars());
1184: v->parent = this;
1185: vresult = v;
1186:
1187: // vresult gets initialized with the function return value
1188: // in ReturnStatement::semantic()
1189: }
1190:
1191: // BUG: need to treat parameters as const
1192: // BUG: need to disallow returns and throws
1193: if (fensure)
1194: { fensure = fensure->semantic(sc2);
1195: labtab = NULL; // so body can't refer to labels
1196: }
1197:
1198: if (!global.params.useOut)
1199: { fensure = NULL; // discard
1200: vresult = NULL;
1201: }
1202:
1203: // Postcondition invariant
1204: if (addPostInvariant())
1205: {
1206: Expression *e = NULL;
1207: if (isCtorDeclaration())
1208: {
1209: // Call invariant directly only if it exists
1210: InvariantDeclaration *inv = ad->inv;
1211: ClassDeclaration *cd = ad->isClassDeclaration();
1212:
1213: while (!inv && cd)
1214: {
1215: cd = cd->baseClass;
1216: if (!cd)
1217: break;
1218: inv = cd->inv;
1219: }
1220: if (inv)
1221: {
1222: e = new DsymbolExp(0, inv);
1223: e = new CallExp(0, e);
1224: e = e->semantic(sc2);
1225: }
1226: }
1227: else
1228: { // Call invariant virtually
1229: Expression *v = new ThisExp(0);
1230: v->type = vthis->type;
1231: #if STRUCTTHISREF
1232: if (ad->isStructDeclaration())
1233: v = v->addressOf(sc);
1234: #endif
1235: e = new AssertExp(0, v);
1236: }
1237: if (e)
1238: {
1239: ExpStatement *s = new ExpStatement(0, e);
1240: if (fensure)
1241: fensure = new CompoundStatement(0, s, fensure);
1242: else
1243: fensure = s;
1244: }
1245: }
1246:
1247: if (fensure)
1248: { returnLabel = new LabelDsymbol(Id::returnLabel);
1249: LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
1250: returnLabel->statement = ls;
1251: }
1252: sc2 = sc2->pop();
1253: }
1254:
1255: sc2->incontract--;
1256:
1257: if (fbody)
1258: { ClassDeclaration *cd = isClassMember();
1259:
1260: /* If this is a class constructor
1261: */
1262: if (isCtorDeclaration() && cd)
1263: {
1264: for (int i = 0; i < cd->fields.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1265: { VarDeclaration *v = cd->fields.tdata()[i];
1266:
1267: v->ctorinit = 0;
1268: }
1269: }
1270:
1271: if (inferRetType || f->retStyle() != RETstack)
1272: nrvo_can = 0;
1273:
1274: fbody = fbody->semantic(sc2);
1275: if (!fbody)
1276: fbody = new CompoundStatement(0, new Statements());
1277:
1278: if (inferRetType)
1279: { // If no return type inferred yet, then infer a void
1280: if (!type->nextOf())
1281: {
1282: ((TypeFunction *)type)->next = Type::tvoid;
1283: type = type->semantic(loc, sc);
1284: }
1285: f = (TypeFunction *)type;
1286: }
1287:
1288: if (isStaticCtorDeclaration())
1289: { /* It's a static constructor. Ensure that all
1290: * ctor consts were initialized.
1291: */
1292:
1293: Dsymbol *p = toParent();
1294: ScopeDsymbol *ad = p->isScopeDsymbol();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '888' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 888
1295: if (!ad)
1296: {
1297: error("static constructor can only be member of struct/class/module, not %s %s", p->kind(), p->toChars());
1298: }
1299: else
1300: {
1301: for (int i = 0; i < ad->members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1302: { Dsymbol *s = ad->members->tdata()[i];
1303:
1304: s->checkCtorConstInit();
1305: }
1306: }
1307: }
1308:
1309: if (isCtorDeclaration() && cd)
1310: {
1311: //printf("callSuper = x%x\n", sc2->callSuper);
1312:
1313: // Verify that all the ctorinit fields got initialized
1314: if (!(sc2->callSuper & CSXthis_ctor))
1315: {
1316: for (int i = 0; i < cd->fields.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1317: { VarDeclaration *v = cd->fields.tdata()[i];
1318:
1319: if (v->ctorinit == 0 && v->isCtorinit() && !v->type->isMutable())
1320: error("missing initializer for final field %s", v->toChars());
1321: }
1322: }
1323:
1324: if (!(sc2->callSuper & CSXany_ctor) &&
1325: cd->baseClass && cd->baseClass->ctor)
1326: {
1327: sc2->callSuper = 0;
1328:
1329: // Insert implicit super() at start of fbody
1330: Expression *e1 = new SuperExp(0);
1331: Expression *e = new CallExp(0, e1);
1332:
1333: e = e->trySemantic(sc2);
1334: if (!e)
1335: error("no match for implicit super() call in constructor");
1336: else
1337: {
1338: Statement *s = new ExpStatement(0, e);
1339: fbody = new CompoundStatement(0, s, fbody);
1340: }
1341: }
1342: }
1343: else if (fes)
1344: { // For foreach(){} body, append a return 0;
1345: Expression *e = new IntegerExp(0);
1346: Statement *s = new ReturnStatement(0, e);
1347: fbody = new CompoundStatement(0, fbody, s);
1348: assert(!returnLabel);
1349: }
1350: else if (!hasReturnExp && type->nextOf()->ty != Tvoid)
1351: error("has no return statement, but is expected to return a value of type %s", type->nextOf()->toChars());
1352: else if (hasReturnExp & 8) // if inline asm
1353: {
1354: flags &= ~FUNCFLAGnothrowInprocess;
1355: }
1356: else
1357: {
1358: #if DMDV2
1359: // Check for errors related to 'nothrow'.
1360: int nothrowErrors = global.errors;
1361: int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru;
1362: if (f->isnothrow && (global.errors != nothrowErrors) )
1363: error("'%s' is nothrow yet may throw", toChars());
1364: if (flags & FUNCFLAGnothrowInprocess)
1365: {
1366: flags &= ~FUNCFLAGnothrowInprocess;
1367: if (!(blockexit & BEthrow))
1368: f->isnothrow = TRUE;
1369: }
1370:
1371: int offend = blockexit & BEfallthru;
1372: #endif
1373: if (type->nextOf()->ty == Tvoid)
1374: {
1375: if (offend && isMain())
1376: { // Add a return 0; statement
1377: Statement *s = new ReturnStatement(0, new IntegerExp(0));
1378: fbody = new CompoundStatement(0, fbody, s);
1379: }
1380: }
1381: else
1382: {
1383: if (offend)
1384: { Expression *e;
1385: #if DMDV1
1386: warning(loc, "no return exp; or assert(0); at end of function");
1387: #else
1388: error("no return exp; or assert(0); at end of function");
1389: #endif
1390: if (global.params.useAssert &&
1391: !global.params.useInline)
1392: { /* Add an assert(0, msg); where the missing return
1393: * should be.
1394: */
1395: e = new AssertExp(
1396: endloc,
1397: new IntegerExp(0),
1398: new StringExp(loc, (char *)"missing return expression")
1399: );
1400: }
1401: else
1402: e = new HaltExp(endloc);
1403: e = new CommaExp(0, e, type->nextOf()->defaultInit());
1404: e = e->semantic(sc2);
1405: Statement *s = new ExpStatement(0, e);
1406: fbody = new CompoundStatement(0, fbody, s);
1407: }
1408: }
1409: }
1410: }
1411:
1412: {
1413: Statements *a = new Statements();
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 799, 800, 801, 802, 804, 818, 820, 822, 824, 841, 843, 855, 856, 858, 863, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 880, 881, 882, 883, 884, 885, 888, 889, 890, 892, 899, 900, 901, 903, 904, 932, 934, 936, 939, 940, 942, 943, 962, 1046, 1047, 1051, 1052, 1053, 1055, 1056, 1057, 1062, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1085, 1087, 1120, 1122, 1129, 1130, 1133, 1136, 1145, 1146, 1147, 1149, 1150, 1157, 1161, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1193, 1194, 1195, 1198, 1199, 1200, 1204, 1206, 1207, 1210, 1211, 1213, 1220, 1237, 1247, 1248, 1249, 1250, 1252, 1255, 1257, 1258, 1262, 1264, 1271, 1274, 1275, 1278, 1288, 1293, 1294, 1295, 1297, 1309, 1314, 1316, 1325, 1413, 1416, 1417, 1432, 1495, 1510, 1516, 1518, 1519, 1522, 1523, 1525, 1532, 1552, 1559, 1560, 1562, 1564, 1566, 1569, 1570
1414:
1415: // Merge in initialization of 'out' parameters
1416: if (parameters)
1417: { for (size_t i = 0; i < parameters->dim; i++)
1418: {
1419: VarDeclaration *v = parameters->tdata()[i];
1420: if (v->storage_class & STCout)
1421: {
1422: assert(v->init);
1423: ExpInitializer *ie = v->init->isExpInitializer();
1424: assert(ie);
1425: if (ie->exp->op == TOKconstruct)
1426: ie->exp->op = TOKassign; // construction occured in parameter processing
1427: a->push(new ExpStatement(0, ie->exp));
1428: }
1429: }
1430: }
1431:
1432: if (argptr)
1433: { // Initialize _argptr
1434: #if IN_GCC
1435: // Handled in FuncDeclaration::toObjFile
1436: v_argptr = argptr;
1437: v_argptr->init = new VoidInitializer(loc);
1438: #else
1439: Type *t = argptr->type;
1440: if (global.params.is64bit)
1441: { // Initialize _argptr to point to v_argsave
1442: Expression *e1 = new VarExp(0, argptr);
1443: Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16);
1444: e->type = argptr->type;
1445: e = new AssignExp(0, e1, e);
1446: e = e->semantic(sc);
1447: a->push(new ExpStatement(0, e));
1448: }
1449: else
1450: { // Initialize _argptr to point past non-variadic arg
1451: VarDeclaration *p;
1452: unsigned offset = 0;
1453:
1454: Expression *e1 = new VarExp(0, argptr);
1455: // Find the last non-ref parameter
1456: if (parameters && parameters->dim)
1457: {
1458: int lastNonref = parameters->dim -1;
1459: p = parameters->tdata()[lastNonref];
1460: /* The trouble with out and ref parameters is that taking
1461: * the address of it doesn't work, because later processing
1462: * adds in an extra level of indirection. So we skip over them.
1463: */
1464: while (p->storage_class & (STCout | STCref))
1465: {
1466: --lastNonref;
1467: offset += PTRSIZE;
1468: if (lastNonref < 0)
1469: {
1470: p = v_arguments;
1471: break;
1472: }
1473: p = parameters->tdata()[lastNonref];
1474: }
1475: }
1476: else
1477: p = v_arguments; // last parameter is _arguments[]
1478: if (p->storage_class & STClazy)
1479: // If the last parameter is lazy, it's the size of a delegate
1480: offset += PTRSIZE * 2;
1481: else
1482: offset += p->type->size();
warning C4244: '+=' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
1483: offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size
1484: Expression *e = new SymOffExp(0, p, offset);
1485: e->type = Type::tvoidptr;
1486: //e = e->semantic(sc);
1487: e = new AssignExp(0, e1, e);
1488: e->type = t;
1489: a->push(new ExpStatement(0, e));
1490: p->isargptr = TRUE;
1491: }
1492: #endif
1493: }
1494:
1495: if (_arguments)
1496: {
1497: /* Advance to elements[] member of TypeInfo_Tuple with:
1498: * _arguments = v_arguments.elements;
1499: */
1500: Expression *e = new VarExp(0, v_arguments);
1501: e = new DotIdExp(0, e, Id::elements);
1502: Expression *e1 = new VarExp(0, _arguments);
1503: e = new ConstructExp(0, e1, e);
1504: e = e->semantic(sc2);
1505: a->push(new ExpStatement(0, e));
1506: }
1507:
1508: // Merge contracts together with body into one compound statement
1509:
1510: if (frequire && global.params.useIn)
1511: { frequire->incontract = 1;
1512: a->push(frequire);
1513: }
1514:
1515: // Precondition invariant
1516: if (addPreInvariant())
1517: {
1518: Expression *e = NULL;
1519: if (isDtorDeclaration())
1520: {
1521: // Call invariant directly only if it exists
1522: InvariantDeclaration *inv = ad->inv;
1523: ClassDeclaration *cd = ad->isClassDeclaration();
1524:
1525: while (!inv && cd)
1526: {
1527: cd = cd->baseClass;
1528: if (!cd)
1529: break;
1530: inv = cd->inv;
1531: }
1532: if (inv)
1533: {
1534: e = new DsymbolExp(0, inv);
1535: e = new CallExp(0, e);
1536: e = e->semantic(sc2);
1537: }
1538: }
1539: else
1540: { // Call invariant virtually
1541: Expression *v = new ThisExp(0);
1542: v->type = vthis->type;
1543: #if STRUCTTHISREF
1544: if (ad->isStructDeclaration())
1545: v = v->addressOf(sc);
1546: #endif
1547: Expression *se = new StringExp(0, (char *)"null this");
1548: se = se->semantic(sc);
1549: se->type = Type::tchar->arrayOf();
1550: e = new AssertExp(loc, v, se);
1551: }
1552: if (e)
1553: {
1554: ExpStatement *s = new ExpStatement(0, e);
1555: a->push(s);
1556: }
1557: }
1558:
1559: if (fbody)
1560: a->push(fbody);
1561:
1562: if (fensure)
1563: {
1564: a->push(returnLabel->statement);
1565:
1566: if (type->nextOf()->ty != Tvoid)
1567: {
1568: // Create: return vresult;
1569: assert(vresult);
1570: Expression *e = new VarExp(0, vresult);
warning C6211: Leaking memory 'e' due to an exception. Consider using a local catch block to clean up memory: Lines: 799, 800, 801, 802, 804, 818, 820, 822, 824, 841, 843, 855, 856, 858, 863, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 880, 881, 882, 883, 884, 885, 888, 889, 890, 892, 899, 900, 901, 903, 904, 932, 934, 936, 939, 940, 942, 943, 962, 1046, 1047, 1051, 1052, 1053, 1055, 1056, 1057, 1062, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1085, 1087, 1120, 1122, 1129, 1130, 1133, 1136, 1145, 1146, 1147, 1149, 1150, 1157, 1161, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1193, 1194, 1195, 1198, 1199, 1200, 1204, 1206, 1207, 1210, 1211, 1213, 1220, 1237, 1247, 1248, 1249, 1250, 1252, 1255, 1257, 1258, 1262, 1264, 1271, 1274, 1275, 1278, 1288, 1293, 1294, 1295, 1297, 1309, 1314, 1316, 1325, 1413, 1416, 1417, 1432, 1495, 1510, 1516, 1518, 1519, 1522, 1523, 1525, 1532, 1552, 1559, 1560, 1562, 1564, 1566, 1569, 1570, 1571, 1572, 1573, 1575
1571: if (tintro)
1572: { e = e->implicitCastTo(sc, tintro->nextOf());
1573: e = e->semantic(sc);
1574: }
1575: ReturnStatement *s = new ReturnStatement(0, e);
1576: a->push(s);
1577: }
1578: }
1579:
1580: fbody = new CompoundStatement(0, a);
1581: #if DMDV2
1582: /* Append destructor calls for parameters as finally blocks.
1583: */
1584: if (parameters)
1585: { for (size_t i = 0; i < parameters->dim; i++)
1586: {
1587: VarDeclaration *v = parameters->tdata()[i];
1588:
1589: if (v->storage_class & (STCref | STCout))
1590: continue;
1591:
1592: /* Don't do this for static arrays, since static
1593: * arrays are called by reference. Remove this
1594: * when we change them to call by value.
1595: */
1596: if (v->type->toBasetype()->ty == Tsarray)
1597: continue;
1598:
1599: if (v->noscope)
1600: continue;
1601:
1602: Expression *e = v->edtor;
1603: if (e)
1604: { Statement *s = new ExpStatement(0, e);
1605: s = s->semantic(sc2);
1606: if (fbody->blockExit(f->isnothrow) == BEfallthru)
1607: fbody = new CompoundStatement(0, fbody, s);
1608: else
1609: fbody = new TryFinallyStatement(0, fbody, s);
1610: }
1611: }
1612: }
1613: #endif
1614:
1615: #if 1
1616: if (isSynchronized())
1617: { /* Wrap the entire function body in a synchronized statement
1618: */
1619: AggregateDeclaration *ad = isThis();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '888' of 'c:\projects\extern\d\dmd\src\func.c': Lines: 888
1620: ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration();
1621:
1622: if (cd)
1623: {
1624: #if TARGET_WINDOS
1625: if (/*config.flags2 & CFG2seh &&*/ // always on for WINDOS
1626: !isStatic() && !fbody->usesEH())
1627: {
1628: /* The back end uses the "jmonitor" hack for syncing;
1629: * no need to do the sync at this level.
1630: */
1631: }
1632: else
1633: #endif
1634: {
1635: Expression *vsync;
1636: if (isStatic())
1637: { // The monitor is in the ClassInfo
1638: vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id::classinfo);
warning C6211: Leaking memory 'vsync' due to an exception. Consider using a local catch block to clean up memory: Lines: 799, 800, 801, 802, 804, 818, 820, 822, 824, 841, 843, 855, 856, 858, 863, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 880, 881, 882, 883, 884, 885, 888, 889, 890, 892, 899, 900, 901, 903, 904, 932, 934, 936, 939, 940,942, 943, 962, 1046, 1047, 1051, 1052, 1053, 1055, 1056, 1057, 1062, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1055, 1056, 1057, 1064, 1067, 1069, 1070, 1072, 1073, 1074, 1075, 1078, 1079, 1053, 1085, 1087, 1120, 1122, 1129, 1130, 1133, 1136, 1145, 1146, 1147, 1149, 1150, 1157, 1161, 1163, 1165, 1166, 1168, 1169, 1170, 1172, 1173, 1174, 1176, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1193, 1194, 1195, 1198, 1199, 1200, 1204, 1206, 1207, 1210, 1211, 1213, 1220, 1237, 1247, 1248, 1249, 1250, 1252, 1255, 1257, 1258, 1262, 1264, 1271, 1274, 1275, 1278, 1288, 1293, 1294, 1295, 1297, 1309, 1314, 1316, 1325, 1413, 1416, 1417, 1432, 1495, 1510, 1516, 1518, 1519, 1522, 1523, 1525, 1532, 1552, 1559, 1560, 1562, 1564, 1566, 1580, 1584, 1585, 1616, 1619, 1620, 1622, 1626, 1635, 1636, 1638, 1644
1639: }
1640: else
1641: { // 'this' is the monitor
1642: vsync = new VarExp(loc, vthis);
1643: }
1644: fbody = new PeelStatement(fbody); // don't redo semantic()
1645: fbody = new SynchronizedStatement(loc, vsync, fbody);
1646: fbody = fbody->semantic(sc2);
1647: }
1648: }
1649: else
1650: {
1651: error("synchronized function %s must be a member of a class", toChars());
1652: }
1653: }
1654: #endif
1655: }
1656:
1657: sc2->callSuper = 0;
1658: sc2->pop();
1659: }
1660:
1661: /* If function survived being marked as impure, then it is pure
1662: */
1663: if (flags & FUNCFLAGpurityInprocess)
1664: {
1665: flags &= ~FUNCFLAGpurityInprocess;
1666: f->purity = PUREfwdref;
1667: }
1668:
1669: if (flags & FUNCFLAGsafetyInprocess)
1670: {
1671: flags &= ~FUNCFLAGsafetyInprocess;
1672: f->trust = TRUSTsafe;
1673: }
1674:
1675: if (global.gag && global.errors != nerrors)
1676: semanticRun = PASSsemanticdone; // Ensure errors get reported again
1677: else
1678: semanticRun = PASSsemantic3done;
1679: //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
1680: //fflush(stdout);
1681: }
1682:
1683: void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1684: {
1685: //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1686:
1687: StorageClassDeclaration::stcToCBuffer(buf, storage_class);
1688: type->toCBuffer(buf, ident, hgs);
1689: bodyToCBuffer(buf, hgs);
1690: }
1691:
1692: int FuncDeclaration::equals(Object *o)
1693: {
1694: if (this == o)
1695: return TRUE;
1696:
1697: Dsymbol *s = isDsymbol(o);
1698: if (s)
1699: {
1700: FuncDeclaration *fd = s->isFuncDeclaration();
1701: if (fd)
1702: {
1703: return toParent()->equals(fd->toParent()) &&
1704: ident->equals(fd->ident) && type->equals(fd->type);
1705: }
1706: }
1707: return FALSE;
1708: }
1709:
1710: void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
1711: {
1712: if (fbody &&
1713: (!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
1714: )
1715: { buf->writenl();
1716:
1717: // in{}
1718: if (frequire)
1719: { buf->writestring("in");
1720: buf->writenl();
1721: frequire->toCBuffer(buf, hgs);
1722: }
1723:
1724: // out{}
1725: if (fensure)
1726: { buf->writestring("out");
1727: if (outId)
1728: { buf->writebyte('(');
1729: buf->writestring(outId->toChars());
1730: buf->writebyte(')');
1731: }
1732: buf->writenl();
1733: fensure->toCBuffer(buf, hgs);
1734: }
1735:
1736: if (frequire || fensure)
1737: { buf->writestring("body");
1738: buf->writenl();
1739: }
1740:
1741: buf->writebyte('{');
1742: buf->writenl();
1743: fbody->toCBuffer(buf, hgs);
1744: buf->writebyte('}');
1745: buf->writenl();
1746: }
1747: else
1748: { buf->writeByte(';');
1749: buf->writenl();
1750: }
1751: }
1752:
1753: /****************************************************
1754: * Merge into this function the 'in' contracts of all it overrides.
1755: * 'in's are OR'd together, i.e. only one of them needs to pass.
1756: */
1757:
1758: Statement *FuncDeclaration::mergeFrequire(Statement *sf)
1759: {
1760: /* Implementing this is done by having the overriding function call
1761: * nested functions (the fdrequire functions) nested inside the overridden
1762: * function. This requires that the stack layout of the calling function's
1763: * parameters and 'this' pointer be in the same place (as the nested
1764: * function refers to them).
1765: * This is easy for the parameters, as they are all on the stack in the same
1766: * place by definition, since it's an overriding function. The problem is
1767: * getting the 'this' pointer in the same place, since it is a local variable.
1768: * We did some hacks in the code generator to make this happen:
1769: * 1. always generate exception handler frame, or at least leave space for it
1770: * in the frame (Windows 32 SEH only)
1771: * 2. always generate an EBP style frame
1772: * 3. since 'this' is passed in a register that is subsequently copied into
1773: * a stack local, allocate that local immediately following the exception
1774: * handler block, so it is always at the same offset from EBP.
1775: */
1776: for (int i = 0; i < foverrides.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1777: {
1778: FuncDeclaration *fdv = foverrides.tdata()[i];
1779:
1780: /* The semantic pass on the contracts of the overridden functions must
1781: * be completed before code generation occurs (bug 3602).
1782: */
1783: if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done)
1784: {
1785: assert(fdv->scope);
1786: Scope *sc = fdv->scope->push();
1787: sc->stc &= ~STCoverride;
1788: fdv->semantic3(sc);
1789: sc->pop();
1790: }
1791:
1792: sf = fdv->mergeFrequire(sf);
1793: if (sf && fdv->fdrequire)
1794: {
1795: //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
1796: /* Make the call:
1797: * try { __require(); }
1798: * catch { frequire; }
1799: */
1800: Expression *eresult = NULL;
1801: Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire, 0), eresult);
1802: Statement *s2 = new ExpStatement(loc, e);
warning C6211: Leaking memory 's2' due to an exception. Consider using a local catch block to clean up memory: Lines: 1776, 1778, 1783, 1792, 1793, 1800, 1801, 1802, 1804
1803:
1804: Catch *c = new Catch(loc, NULL, NULL, sf);
warning C6211: Leaking memory 'c' due to an exception. Consider using a local catch block to clean up memory: Lines: 1776, 1778, 1783, 1792, 1793, 1800, 1801, 1802, 1804, 1805
1805: Catches *catches = new Catches();
1806: catches->push(c);
1807: sf = new TryCatchStatement(loc, s2, catches);
1808: }
1809: else
1810: return NULL;
1811: }
1812: return sf;
1813: }
1814:
1815: /****************************************************
1816: * Merge into this function the 'out' contracts of all it overrides.
1817: * 'out's are AND'd together, i.e. all of them need to pass.
1818: */
1819:
1820: Statement *FuncDeclaration::mergeFensure(Statement *sf)
1821: {
1822: /* Same comments as for mergeFrequire(), except that we take care
1823: * of generating a consistent reference to the 'result' local by
1824: * explicitly passing 'result' to the nested function as a reference
1825: * argument.
1826: * This won't work for the 'this' parameter as it would require changing
1827: * the semantic code for the nested function so that it looks on the parameter
1828: * list for the 'this' pointer, something that would need an unknown amount
1829: * of tweaking of various parts of the compiler that I'd rather leave alone.
1830: */
1831: for (int i = 0; i < foverrides.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1832: {
1833: FuncDeclaration *fdv = foverrides.tdata()[i];
1834:
1835: /* The semantic pass on the contracts of the overridden functions must
1836: * be completed before code generation occurs (bug 3602 and 5230).
1837: */
1838: if (fdv->fdensure && fdv->fdensure->semanticRun != PASSsemantic3done)
1839: {
1840: assert(fdv->scope);
1841: Scope *sc = fdv->scope->push();
1842: sc->stc &= ~STCoverride;
1843: fdv->semantic3(sc);
1844: sc->pop();
1845: }
1846:
1847: sf = fdv->mergeFensure(sf);
1848: if (fdv->fdensure)
1849: {
1850: //printf("fdv->fensure: %s\n", fdv->fensure->toChars());
1851: // Make the call: __ensure(result)
1852: Expression *eresult = NULL;
1853: if (outId)
1854: eresult = new IdentifierExp(loc, outId);
1855: Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, 0), eresult);
1856: Statement *s2 = new ExpStatement(loc, e);
1857:
1858: if (sf)
1859: {
1860: sf = new CompoundStatement(fensure->loc, s2, sf);
1861: }
1862: else
1863: sf = s2;
1864: }
1865: }
1866: return sf;
1867: }
1868:
1869: /****************************************************
1870: * Determine if 'this' overrides fd.
1871: * Return !=0 if it does.
1872: */
1873:
1874: int FuncDeclaration::overrides(FuncDeclaration *fd)
1875: { int result = 0;
1876:
1877: if (fd->ident == ident)
1878: {
1879: int cov = type->covariant(fd->type);
1880: if (cov)
1881: { ClassDeclaration *cd1 = toParent()->isClassDeclaration();
1882: ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
1883:
1884: if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
1885: result = 1;
1886: }
1887: }
1888: return result;
1889: }
1890:
1891: /*************************************************
1892: * Find index of function in vtbl[0..dim] that
1893: * this function overrides.
1894: * Prefer an exact match to a covariant one.
1895: * Returns:
1896: * -1 didn't find one
1897: * -2 can't determine because of forward references
1898: */
1899:
1900: int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
1901: {
1902: FuncDeclaration *mismatch = NULL;
1903: int bestvi = -1;
1904: for (int vi = 0; vi < dim; vi++)
1905: {
1906: FuncDeclaration *fdv = vtbl->tdata()[vi]->isFuncDeclaration();
1907: if (fdv && fdv->ident == ident)
1908: {
1909: if (type->equals(fdv->type)) // if exact match
1910: return vi; // no need to look further
1911:
1912: int cov = type->covariant(fdv->type);
1913: //printf("\tbaseclass cov = %d\n", cov);
1914: switch (cov)
1915: {
1916: case 0: // types are distinct
1917: break;
1918:
1919: case 1:
1920: bestvi = vi; // covariant, but not identical
1921: break; // keep looking for an exact match
1922:
1923: case 2:
1924: mismatch = fdv; // overrides, but is not covariant
1925: break; // keep looking for an exact match
1926:
1927: case 3:
1928: return -2; // forward references
1929:
1930: default:
1931: assert(0);
1932: }
1933: }
1934: }
1935: if (bestvi == -1 && mismatch)
1936: {
1937: //type->print();
1938: //mismatch->type->print();
1939: //printf("%s %s\n", type->deco, mismatch->type->deco);
1940: error("of type %s overrides but is not covariant with %s of type %s",
1941: type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
1942: }
1943: return bestvi;
1944: }
1945:
1946: /****************************************************
1947: * Overload this FuncDeclaration with the new one f.
1948: * Return !=0 if successful; i.e. no conflict.
1949: */
1950:
1951: int FuncDeclaration::overloadInsert(Dsymbol *s)
1952: {
1953: FuncDeclaration *f;
1954: AliasDeclaration *a;
1955:
1956: //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
1957: a = s->isAliasDeclaration();
1958: if (a)
1959: {
1960: if (overnext)
1961: return overnext->overloadInsert(a);
1962: if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance)
1963: {
1964: //printf("\ta = '%s'\n", a->type->toChars());
1965: return FALSE;
1966: }
1967: overnext = a;
1968: //printf("\ttrue: no conflict\n");
1969: return TRUE;
1970: }
1971: f = s->isFuncDeclaration();
1972: if (!f)
1973: return FALSE;
1974:
1975: #if 0
1976: /* Disable this check because:
1977: * const void foo();
1978: * semantic() isn't run yet on foo(), so the const hasn't been
1979: * applied yet.
1980: */
1981: if (type)
1982: { printf("type = %s\n", type->toChars());
1983: printf("f->type = %s\n", f->type->toChars());
1984: }
1985: if (type && f->type && // can be NULL for overloaded constructors
1986: f->type->covariant(type) &&
1987: f->type->mod == type->mod &&
1988: !isFuncAliasDeclaration())
1989: {
1990: //printf("\tfalse: conflict %s\n", kind());
1991: return FALSE;
1992: }
1993: #endif
1994:
1995: if (overnext)
1996: return overnext->overloadInsert(f);
1997: overnext = f;
1998: //printf("\ttrue: no conflict\n");
1999: return TRUE;
2000: }
2001:
2002: /********************************************
2003: * Find function in overload list that exactly matches t.
2004: */
2005:
2006: /***************************************************
2007: * Visit each overloaded function in turn, and call
2008: * (*fp)(param, f) on it.
2009: * Exit when no more, or (*fp)(param, f) returns 1.
2010: * Returns:
2011: * 0 continue
2012: * 1 done
2013: */
2014:
2015: int overloadApply(FuncDeclaration *fstart,
2016: int (*fp)(void *, FuncDeclaration *),
2017: void *param)
2018: {
2019: FuncDeclaration *f;
2020: Declaration *d;
2021: Declaration *next;
2022:
2023: for (d = fstart; d; d = next)
2024: { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration();
2025:
2026: if (fa)
2027: {
2028: if (overloadApply(fa->funcalias, fp, param))
2029: return 1;
2030: next = fa->overnext;
2031: }
2032: else
2033: {
2034: AliasDeclaration *a = d->isAliasDeclaration();
2035:
2036: if (a)
2037: {
2038: Dsymbol *s = a->toAlias();
2039: next = s->isDeclaration();
2040: if (next == a)
2041: break;
2042: if (next == fstart)
2043: break;
2044: }
2045: else
2046: {
2047: f = d->isFuncDeclaration();
2048: if (!f)
2049: { d->error("is aliased to a function");
2050: break; // BUG: should print error message?
2051: }
2052: if ((*fp)(param, f))
2053: return 1;
2054:
2055: next = f->overnext;
2056: }
2057: }
2058: }
2059: return 0;
2060: }
2061:
2062: /********************************************
2063: * If there are no overloads of function f, return that function,
2064: * otherwise return NULL.
2065: */
2066:
2067: static int fpunique(void *param, FuncDeclaration *f)
2068: { FuncDeclaration **pf = (FuncDeclaration **)param;
2069:
2070: if (*pf)
2071: { *pf = NULL;
2072: return 1; // ambiguous, done
2073: }
2074: else
2075: { *pf = f;
2076: return 0;
2077: }
2078: }
2079:
2080: FuncDeclaration *FuncDeclaration::isUnique()
2081: { FuncDeclaration *result = NULL;
2082:
2083: overloadApply(this, &fpunique, &result);
2084: return result;
2085: }
2086:
2087: /********************************************
2088: * Find function in overload list that exactly matches t.
2089: */
2090:
2091: struct Param1
2092: {
2093: Type *t; // type to match
2094: FuncDeclaration *f; // return value
2095: };
2096:
2097: int fp1(void *param, FuncDeclaration *f)
2098: { Param1 *p = (Param1 *)param;
2099: Type *t = p->t;
2100:
2101: if (t->equals(f->type))
2102: { p->f = f;
2103: return 1;
2104: }
2105:
2106: #if DMDV2
2107: /* Allow covariant matches, as long as the return type
2108: * is just a const conversion.
2109: * This allows things like pure functions to match with an impure function type.
2110: */
2111: if (t->ty == Tfunction)
2112: { TypeFunction *tf = (TypeFunction *)f->type;
2113: if (tf->covariant(t) == 1 &&
2114: tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
2115: {
2116: p->f = f;
2117: return 1;
2118: }
2119: }
2120: #endif
2121: return 0;
2122: }
2123:
2124: FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
2125: {
2126: Param1 p;
2127: p.t = t;
2128: p.f = NULL;
2129: overloadApply(this, &fp1, &p);
2130: return p.f;
2131: }
2132:
2133:
2134: /********************************************
2135: * Decide which function matches the arguments best.
2136: */
2137:
2138: struct Param2
2139: {
2140: Match *m;
2141: #if DMDV2
2142: Expression *ethis;
2143: int property; // 0: unintialized
2144: // 1: seen @property
2145: // 2: not @property
2146: #endif
2147: Expressions *arguments;
2148: };
2149:
2150: int fp2(void *param, FuncDeclaration *f)
2151: { Param2 *p = (Param2 *)param;
2152: Match *m = p->m;
2153: Expressions *arguments = p->arguments;
2154: MATCH match;
2155:
2156: if (f != m->lastf) // skip duplicates
2157: {
2158: m->anyf = f;
2159: TypeFunction *tf = (TypeFunction *)f->type;
2160:
2161: int property = (tf->isproperty) ? 1 : 2;
2162: if (p->property == 0)
2163: p->property = property;
2164: else if (p->property != property)
2165: error(f->loc, "cannot overload both property and non-property functions");
2166:
2167: /* For constructors, don't worry about the right type of ethis. It's a problem
2168: * anyway, because the constructor attribute may not match the ethis attribute,
2169: * but we don't care because the attribute on the ethis doesn't matter until
2170: * after it's constructed.
2171: */
2172: match = (MATCH) tf->callMatch(f->needThis() && !f->isCtorDeclaration() ? p->ethis : NULL, arguments);
2173: //printf("test1: match = %d\n", match);
2174: if (match != MATCHnomatch)
2175: {
2176: if (match > m->last)
2177: goto LfIsBetter;
2178:
2179: if (match < m->last)
2180: goto LlastIsBetter;
2181:
2182: /* See if one of the matches overrides the other.
2183: */
2184: if (m->lastf->overrides(f))
2185: goto LlastIsBetter;
2186: else if (f->overrides(m->lastf))
2187: goto LfIsBetter;
2188:
2189: #if DMDV2
2190: /* Try to disambiguate using template-style partial ordering rules.
2191: * In essence, if f() and g() are ambiguous, if f() can call g(),
2192: * but g() cannot call f(), then pick f().
2193: * This is because f() is "more specialized."
2194: */
2195: {
2196: MATCH c1 = f->leastAsSpecialized(m->lastf);
2197: MATCH c2 = m->lastf->leastAsSpecialized(f);
2198: //printf("c1 = %d, c2 = %d\n", c1, c2);
2199: if (c1 > c2)
2200: goto LfIsBetter;
2201: if (c1 < c2)
2202: goto LlastIsBetter;
2203: }
2204: #endif
2205: Lambiguous:
warning C4102: 'Lambiguous' : unreferenced label
2206: m->nextf = f;
2207: m->count++;
2208: return 0;
2209:
2210: LfIsBetter:
2211: m->last = match;
2212: m->lastf = f;
2213: m->count = 1;
2214: return 0;
2215:
2216: LlastIsBetter:
2217: return 0;
2218: }
2219: }
2220: return 0;
2221: }
2222:
2223:
2224: void overloadResolveX(Match *m, FuncDeclaration *fstart,
2225: Expression *ethis, Expressions *arguments)
2226: {
2227: Param2 p;
2228: p.m = m;
2229: p.ethis = ethis;
2230: p.property = 0;
2231: p.arguments = arguments;
2232: overloadApply(fstart, &fp2, &p);
2233: }
2234:
2235:
2236: FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags)
2237: {
2238: TypeFunction *tf;
2239: Match m;
2240:
2241: #if 0
2242: printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
2243: if (arguments)
2244: { int i;
2245:
2246: for (i = 0; i < arguments->dim; i++)
2247: { Expression *arg;
2248:
2249: arg = arguments->tdata()[i];
2250: assert(arg->type);
2251: printf("\t%s: ", arg->toChars());
2252: arg->type->print();
2253: }
2254: }
2255: #endif
2256:
2257: memset(&m, 0, sizeof(m));
2258: m.last = MATCHnomatch;
2259: overloadResolveX(&m, this, ethis, arguments);
2260:
2261: if (m.count == 1) // exactly one match
2262: {
2263: return m.lastf;
2264: }
2265: else
2266: {
2267: OutBuffer buf;
2268:
2269: buf.writeByte('(');
2270: if (arguments)
2271: {
2272: HdrGenState hgs;
2273:
2274: argExpTypesToCBuffer(&buf, arguments, &hgs);
2275: buf.writeByte(')');
2276: if (ethis)
2277: ethis->type->modToBuffer(&buf);
2278: }
2279: else
2280: buf.writeByte(')');
2281:
2282: if (m.last == MATCHnomatch)
2283: {
2284: if (flags & 1) // if do not print error messages
2285: return NULL; // no match
2286:
2287: tf = (TypeFunction *)type;
2288:
2289: OutBuffer buf2;
2290: tf->modToBuffer(&buf2);
2291:
2292: //printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco);
2293: error(loc, "%s%s is not callable using argument types %s",
2294: Parameter::argsTypesToChars(tf->parameters, tf->varargs),
2295: buf2.toChars(),
2296: buf.toChars());
2297: return m.anyf; // as long as it's not a FuncAliasDeclaration
2298: }
2299: else
2300: {
2301: #if 1
2302: TypeFunction *t1 = (TypeFunction *)m.lastf->type;
2303: TypeFunction *t2 = (TypeFunction *)m.nextf->type;
2304:
2305: error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
2306: buf.toChars(),
2307: m.lastf->toPrettyChars(), Parameter::argsTypesToChars(t1->parameters, t1->varargs),
2308: m.nextf->toPrettyChars(), Parameter::argsTypesToChars(t2->parameters, t2->varargs));
2309: #else
2310: error(loc, "overloads %s and %s both match argument list for %s",
2311: m.lastf->type->toChars(),
2312: m.nextf->type->toChars(),
2313: m.lastf->toChars());
2314: #endif
2315: return m.lastf;
2316: }
2317: }
2318: }
2319:
2320: /*************************************
2321: * Determine partial specialization order of 'this' vs g.
2322: * This is very similar to TemplateDeclaration::leastAsSpecialized().
2323: * Returns:
2324: * match 'this' is at least as specialized as g
2325: * 0 g is more specialized than 'this'
2326: */
2327:
2328: #if DMDV2
2329: MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
2330: {
2331: #define LOG_LEASTAS 0
2332:
2333: #if LOG_LEASTAS
2334: printf("%s.leastAsSpecialized(%s)\n", toChars(), g->toChars());
2335: printf("%s, %s\n", type->toChars(), g->type->toChars());
2336: #endif
2337:
2338: /* This works by calling g() with f()'s parameters, and
2339: * if that is possible, then f() is at least as specialized
2340: * as g() is.
2341: */
2342:
2343: TypeFunction *tf = (TypeFunction *)type;
2344: TypeFunction *tg = (TypeFunction *)g->type;
2345: size_t nfparams = Parameter::dim(tf->parameters);
2346: size_t ngparams = Parameter::dim(tg->parameters);
2347: MATCH match = MATCHexact;
2348:
2349: /* If both functions have a 'this' pointer, and the mods are not
2350: * the same and g's is not const, then this is less specialized.
2351: */
2352: if (needThis() && g->needThis())
2353: {
2354: if (tf->mod != tg->mod)
2355: {
2356: if (tg->mod == MODconst)
2357: match = MATCHconst;
2358: else
2359: return MATCHnomatch;
2360: }
2361: }
2362:
2363: /* Create a dummy array of arguments out of the parameters to f()
2364: */
2365: Expressions args;
2366: args.setDim(nfparams);
2367: for (int u = 0; u < nfparams; u++)
warning C4018: '<' : signed/unsigned mismatch
2368: {
2369: Parameter *p = Parameter::getNth(tf->parameters, u);
2370: Expression *e;
2371: if (p->storageClass & (STCref | STCout))
2372: {
2373: e = new IdentifierExp(0, p->ident);
2374: e->type = p->type;
2375: }
2376: else
2377: e = p->type->defaultInit();
2378: args.tdata()[u] = e;
2379: }
2380:
2381: MATCH m = (MATCH) tg->callMatch(NULL, &args, 1);
2382: if (m)
2383: {
2384: /* A variadic parameter list is less specialized than a
2385: * non-variadic one.
2386: */
2387: if (tf->varargs && !tg->varargs)
2388: goto L1; // less specialized
2389:
2390: #if LOG_LEASTAS
2391: printf(" matches %d, so is least as specialized\n", m);
2392: #endif
2393: return m;
2394: }
2395: L1:
2396: #if LOG_LEASTAS
2397: printf(" doesn't match, so is not as specialized\n");
2398: #endif
2399: return MATCHnomatch;
2400: }
2401:
2402: /*******************************************
2403: * Given a symbol that could be either a FuncDeclaration or
2404: * a function template, resolve it to a function symbol.
2405: * sc instantiation scope
2406: * loc instantiation location
2407: * targsi initial list of template arguments
2408: * ethis if !NULL, the 'this' pointer argument
2409: * fargs arguments to function
2410: * flags 1: do not issue error message on no match, just return NULL
2411: */
2412:
2413: FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
2414: Objects *tiargs,
2415: Expression *ethis,
2416: Expressions *arguments,
2417: int flags)
2418: {
2419: if (!s)
2420: return NULL; // no match
2421: FuncDeclaration *f = s->isFuncDeclaration();
2422: if (f)
2423: f = f->overloadResolve(loc, ethis, arguments);
2424: else
2425: { TemplateDeclaration *td = s->isTemplateDeclaration();
2426: assert(td);
2427: f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags);
2428: }
2429: return f;
2430: }
2431: #endif
2432:
2433: /********************************
2434: * Labels are in a separate scope, one per function.
2435: */
2436:
2437: LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
2438: { Dsymbol *s;
2439:
2440: if (!labtab)
2441: labtab = new DsymbolTable(); // guess we need one
2442:
2443: s = labtab->lookup(ident);
2444: if (!s)
2445: {
2446: s = new LabelDsymbol(ident);
2447: labtab->insert(s);
2448: }
2449: return (LabelDsymbol *)s;
2450: }
2451:
2452: /****************************************
2453: * If non-static member function that has a 'this' pointer,
2454: * return the aggregate it is a member of.
2455: * Otherwise, return NULL.
2456: */
2457:
2458: AggregateDeclaration *FuncDeclaration::isThis()
2459: { AggregateDeclaration *ad;
2460:
2461: //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
2462: ad = NULL;
2463: if ((storage_class & STCstatic) == 0)
2464: {
2465: ad = isMember2();
2466: }
2467: //printf("-FuncDeclaration::isThis() %p\n", ad);
2468: return ad;
2469: }
2470:
2471: AggregateDeclaration *FuncDeclaration::isMember2()
2472: { AggregateDeclaration *ad;
2473:
2474: //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
2475: ad = NULL;
2476: for (Dsymbol *s = this; s; s = s->parent)
2477: {
2478: //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
2479: ad = s->isMember();
2480: if (ad)
2481: {
2482: break;
2483: }
2484: if (!s->parent ||
2485: (!s->parent->isTemplateInstance()))
2486: {
2487: break;
2488: }
2489: }
2490: //printf("-FuncDeclaration::isMember2() %p\n", ad);
2491: return ad;
2492: }
2493:
2494: /*****************************************
2495: * Determine lexical level difference from 'this' to nested function 'fd'.
2496: * Error if this cannot call fd.
2497: * Returns:
2498: * 0 same level
2499: * -1 increase nesting by 1 (fd is nested within 'this')
2500: * >0 decrease nesting by number
2501: */
2502:
2503: int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
2504: { int level;
2505: Dsymbol *s;
2506: Dsymbol *fdparent;
2507:
2508: //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
2509: fdparent = fd->toParent2();
2510: if (fdparent == this)
2511: return -1;
2512: s = this;
2513: level = 0;
2514: while (fd != s && fdparent != s->toParent2())
2515: {
2516: //printf("\ts = %s, '%s'\n", s->kind(), s->toChars());
2517: FuncDeclaration *thisfd = s->isFuncDeclaration();
2518: if (thisfd)
2519: { if (!thisfd->isNested() && !thisfd->vthis)
2520: goto Lerr;
2521: }
2522: else
2523: {
2524: AggregateDeclaration *thiscd = s->isAggregateDeclaration();
2525: if (thiscd)
2526: { if (!thiscd->isNested())
2527: goto Lerr;
2528: }
2529: else
2530: goto Lerr;
2531: }
2532:
2533: s = s->toParent2();
2534: assert(s);
2535: level++;
2536: }
2537: return level;
2538:
2539: Lerr:
2540: error(loc, "cannot access frame of function %s", fd->toPrettyChars());
2541: return 1;
2542: }
2543:
2544: void FuncDeclaration::appendExp(Expression *e)
2545: { Statement *s;
2546:
2547: s = new ExpStatement(0, e);
2548: appendState(s);
2549: }
2550:
2551: void FuncDeclaration::appendState(Statement *s)
2552: {
2553: if (!fbody)
2554: fbody = s;
2555: else
2556: {
2557: CompoundStatement *cs = fbody->isCompoundStatement();
2558: if (cs)
2559: {
2560: if (!cs->statements)
2561: fbody = s;
2562: else
2563: cs->statements->push(s);
2564: }
2565: else
2566: fbody = new CompoundStatement(0, fbody, s);
2567: }
2568: }
2569:
2570: const char *FuncDeclaration::toPrettyChars()
2571: {
2572: if (isMain())
2573: return "D main";
2574: else
2575: return Dsymbol::toPrettyChars();
2576: }
2577:
2578: int FuncDeclaration::isMain()
2579: {
2580: return ident == Id::main &&
2581: linkage != LINKc && !isMember() && !isNested();
2582: }
2583:
2584: int FuncDeclaration::isWinMain()
2585: {
2586: //printf("FuncDeclaration::isWinMain() %s\n", toChars());
2587: #if 0
2588: int x = ident == Id::WinMain &&
2589: linkage != LINKc && !isMember();
2590: printf("%s\n", x ? "yes" : "no");
2591: return x;
2592: #else
2593: return ident == Id::WinMain &&
2594: linkage != LINKc && !isMember();
2595: #endif
2596: }
2597:
2598: int FuncDeclaration::isDllMain()
2599: {
2600: return ident == Id::DllMain &&
2601: linkage != LINKc && !isMember();
2602: }
2603:
2604: int FuncDeclaration::isExport()
2605: {
2606: return protection == PROTexport;
2607: }
2608:
2609: int FuncDeclaration::isImportedSymbol()
2610: {
2611: //printf("isImportedSymbol()\n");
2612: //printf("protection = %d\n", protection);
2613: return (protection == PROTexport) && !fbody;
2614: }
2615:
2616: // Determine if function goes into virtual function pointer table
2617:
2618: int FuncDeclaration::isVirtual()
2619: {
2620: #if 0
2621: printf("FuncDeclaration::isVirtual(%s)\n", toChars());
2622: printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
2623: printf("result is %d\n",
2624: isMember() &&
2625: !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2626: toParent()->isClassDeclaration());
2627: #endif
2628: Dsymbol *p = toParent();
2629: return isMember() &&
2630: !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2631: p->isClassDeclaration() &&
2632: !(p->isInterfaceDeclaration() && isFinal());
2633: }
2634:
2635: int FuncDeclaration::isFinal()
2636: {
2637: ClassDeclaration *cd;
2638: #if 0
2639: printf("FuncDeclaration::isFinal(%s), %x\n", toChars(), Declaration::isFinal());
2640: printf("%p %d %d %d\n", isMember(), isStatic(), Declaration::isFinal(), ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2641: printf("result is %d\n",
2642: isMember() &&
2643: (Declaration::isFinal() ||
2644: ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal)));
2645: if (cd)
2646: printf("\tmember of %s\n", cd->toChars());
2647: #if 0
2648: !(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
2649: (cd = toParent()->isClassDeclaration()) != NULL &&
2650: cd->storage_class & STCfinal);
2651: #endif
2652: #endif
2653: return isMember() &&
2654: (Declaration::isFinal() ||
2655: ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
2656: }
2657:
2658: int FuncDeclaration::isAbstract()
2659: {
2660: return storage_class & STCabstract;
2661: }
2662:
2663: int FuncDeclaration::isCodeseg()
2664: {
2665: return TRUE; // functions are always in the code segment
2666: }
2667:
2668: int FuncDeclaration::isOverloadable()
2669: {
2670: return 1; // functions can be overloaded
2671: }
2672:
2673: enum PURE FuncDeclaration::isPure()
2674: {
2675: //printf("FuncDeclaration::isPure() '%s'\n", toChars());
2676: assert(type->ty == Tfunction);
2677: TypeFunction *tf = (TypeFunction *)type;
2678: if (flags & FUNCFLAGpurityInprocess)
2679: setImpure();
2680: if (tf->purity == PUREfwdref)
2681: tf->purityLevel();
2682: enum PURE purity = tf->purity;
2683: if (purity > PUREweak && needThis())
2684: { // The attribute of the 'this' reference affects purity strength
2685: if (type->mod & (MODimmutable | MODwild))
2686: ;
2687: else if (type->mod & MODconst && purity >= PUREconst)
2688: purity = PUREconst;
2689: else
2690: purity = PUREweak;
2691: }
2692: tf->purity = purity;
2693: // ^ This rely on the current situation that every FuncDeclaration has a
2694: // unique TypeFunction.
2695: return purity;
2696: }
2697:
2698: /**************************************
2699: * The function is doing something impure,
2700: * so mark it as impure.
2701: * If there's a purity error, return TRUE.
2702: */
2703: bool FuncDeclaration::setImpure()
2704: {
2705: if (flags & FUNCFLAGpurityInprocess)
2706: {
2707: flags &= ~FUNCFLAGpurityInprocess;
2708: }
2709: else if (isPure())
2710: return TRUE;
2711: return FALSE;
2712: }
2713:
2714: int FuncDeclaration::isSafe()
2715: {
2716: assert(type->ty == Tfunction);
2717: if (flags & FUNCFLAGsafetyInprocess)
2718: setUnsafe();
2719: return ((TypeFunction *)type)->trust == TRUSTsafe;
2720: }
2721:
2722: int FuncDeclaration::isTrusted()
2723: {
2724: assert(type->ty == Tfunction);
2725: if (flags & FUNCFLAGsafetyInprocess)
2726: setUnsafe();
2727: return ((TypeFunction *)type)->trust == TRUSTtrusted;
2728: }
2729:
2730: /**************************************
2731: * The function is doing something unsave,
2732: * so mark it as unsafe.
2733: * If there's a safe error, return TRUE.
2734: */
2735: bool FuncDeclaration::setUnsafe()
2736: {
2737: if (flags & FUNCFLAGsafetyInprocess)
2738: {
2739: flags &= ~FUNCFLAGsafetyInprocess;
2740: ((TypeFunction *)type)->trust = TRUSTsystem;
2741: }
2742: else if (isSafe())
2743: return TRUE;
2744: return FALSE;
2745: }
2746:
2747: // Determine if function needs
2748: // a static frame pointer to its lexically enclosing function
2749:
2750: int FuncDeclaration::isNested()
2751: {
2752: //if (!toParent())
2753: //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2754: //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2755: return ((storage_class & STCstatic) == 0) &&
2756: (toParent2()->isFuncDeclaration() != NULL);
2757: }
2758:
2759: int FuncDeclaration::needThis()
2760: {
2761: //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2762: int i = isThis() != NULL;
2763: //printf("\t%d\n", i);
2764: if (!i && isFuncAliasDeclaration())
2765: i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
2766: return i;
2767: }
2768:
2769: int FuncDeclaration::addPreInvariant()
2770: {
2771: AggregateDeclaration *ad = isThis();
2772: return (ad &&
2773: //ad->isClassDeclaration() &&
2774: global.params.useInvariants &&
2775: (protection == PROTpublic || protection == PROTexport) &&
2776: !naked &&
2777: ident != Id::cpctor);
2778: }
2779:
2780: int FuncDeclaration::addPostInvariant()
2781: {
2782: AggregateDeclaration *ad = isThis();
2783: return (ad &&
2784: ad->inv &&
2785: //ad->isClassDeclaration() &&
2786: global.params.useInvariants &&
2787: (protection == PROTpublic || protection == PROTexport) &&
2788: !naked &&
2789: ident != Id::cpctor);
2790: }
2791:
2792: /**********************************
2793: * Generate a FuncDeclaration for a runtime library function.
2794: */
2795:
2796: FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, const char *name)
2797: {
2798: return genCfunc(treturn, Lexer::idPool(name));
2799: }
2800:
2801: FuncDeclaration *FuncDeclaration::genCfunc(Type *treturn, Identifier *id)
2802: {
2803: FuncDeclaration *fd;
2804: TypeFunction *tf;
2805: Dsymbol *s;
2806: static DsymbolTable *st = NULL;
2807:
2808: //printf("genCfunc(name = '%s')\n", id->toChars());
2809: //printf("treturn\n\t"); treturn->print();
2810:
2811: // See if already in table
2812: if (!st)
2813: st = new DsymbolTable();
2814: s = st->lookup(id);
2815: if (s)
2816: {
2817: fd = s->isFuncDeclaration();
2818: assert(fd);
2819: assert(fd->type->nextOf()->equals(treturn));
2820: }
2821: else
2822: {
2823: tf = new TypeFunction(NULL, treturn, 0, LINKc);
2824: fd = new FuncDeclaration(0, 0, id, STCstatic, tf);
2825: fd->protection = PROTpublic;
2826: fd->linkage = LINKc;
2827:
2828: st->insert(fd);
2829: }
2830: return fd;
2831: }
2832:
2833: const char *FuncDeclaration::kind()
2834: {
2835: return "function";
2836: }
2837:
2838: /*******************************
2839: * Look at all the variables in this function that are referenced
2840: * by nested functions, and determine if a closure needs to be
2841: * created for them.
2842: */
2843:
2844: #if DMDV2
2845: int FuncDeclaration::needsClosure()
2846: {
2847: /* Need a closure for all the closureVars[] if any of the
2848: * closureVars[] are accessed by a
2849: * function that escapes the scope of this function.
2850: * We take the conservative approach and decide that any function that:
2851: * 1) is a virtual function
2852: * 2) has its address taken
2853: * 3) has a parent that escapes
2854: * -or-
2855: * 4) this function returns a local struct/class
2856: *
2857: * Note that since a non-virtual function can be called by
2858: * a virtual one, if that non-virtual function accesses a closure
2859: * var, the closure still has to be taken. Hence, we check for isThis()
2860: * instead of isVirtual(). (thanks to David Friedman)
2861: */
2862:
2863: //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2864: for (int i = 0; i < closureVars.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2865: { VarDeclaration *v = closureVars.tdata()[i];
2866: assert(v->isVarDeclaration());
2867: //printf("\tv = %s\n", v->toChars());
2868:
2869: for (int j = 0; j < v->nestedrefs.dim; j++)
warning C4018: '<' : signed/unsigned mismatch
2870: { FuncDeclaration *f = v->nestedrefs.tdata()[j];
2871: assert(f != this);
2872:
2873: //printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
2874: if (f->isThis() || f->tookAddressOf)
2875: goto Lyes; // assume f escapes this function's scope
2876:
2877: // Look to see if any parents of f that are below this escape
2878: for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
2879: {
2880: f = s->isFuncDeclaration();
2881: if (f && (f->isThis() || f->tookAddressOf))
2882: goto Lyes;
2883: }
2884: }
2885: }
2886:
2887: /* Look for case (4)
2888: */
2889: if (closureVars.dim)
2890: {
2891: assert(type->ty == Tfunction);
2892: Type *tret = ((TypeFunction *)type)->next;
2893: assert(tret);
2894: tret = tret->toBasetype();
2895: if (tret->ty == Tclass || tret->ty == Tstruct)
2896: { Dsymbol *st = tret->toDsymbol(NULL);
2897: for (Dsymbol *s = st->parent; s; s = s->parent)
2898: {
2899: if (s == this)
2900: goto Lyes;
2901: }
2902: }
2903: }
2904:
2905: return 0;
2906:
2907: Lyes:
2908: //printf("\tneeds closure\n");
2909: return 1;
2910: }
2911: #endif
2912:
2913: /*********************************************
2914: * Return the function's parameter list, and whether
2915: * it is variadic or not.
2916: */
2917:
2918: Parameters *FuncDeclaration::getParameters(int *pvarargs)
2919: { Parameters *fparameters;
2920: int fvarargs;
2921:
2922: if (type)
2923: {
2924: assert(type->ty == Tfunction);
2925: TypeFunction *fdtype = (TypeFunction *)type;
2926: fparameters = fdtype->parameters;
2927: fvarargs = fdtype->varargs;
2928: }
2929: if (pvarargs)
2930: *pvarargs = fvarargs;
warning C6001: Using uninitialized memory 'fvarargs': Lines: 2919, 2920, 2922, 2929, 2930
2931: return fparameters;
warning C6001: Using uninitialized memory 'fparameters': Lines: 2919, 2920, 2922, 2929, 2930, 2931
2932: }
2933:
2934:
2935: /****************************** FuncAliasDeclaration ************************/
2936:
2937: // Used as a way to import a set of functions from another scope into this one.
2938:
2939: FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
2940: : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
2941: funcalias->storage_class, funcalias->type)
2942: {
2943: assert(funcalias != this);
2944: this->funcalias = funcalias;
2945: }
2946:
2947: const char *FuncAliasDeclaration::kind()
2948: {
2949: return "function alias";
2950: }
2951:
2952:
2953: /****************************** FuncLiteralDeclaration ************************/
2954:
2955: FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
2956: enum TOK tok, ForeachStatement *fes)
2957: : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
2958: {
2959: const char *id;
2960:
2961: if (fes)
2962: id = "__foreachbody";
2963: else if (tok == TOKdelegate)
2964: id = "__dgliteral";
2965: else
2966: id = "__funcliteral";
2967: this->ident = Lexer::uniqueId(id);
2968: this->tok = tok;
2969: this->fes = fes;
2970: //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2971: }
2972:
2973: Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
2974: {
2975: FuncLiteralDeclaration *f;
2976:
2977: //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2978: if (s)
2979: f = (FuncLiteralDeclaration *)s;
2980: else
2981: { f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
2982: f->ident = ident; // keep old identifier
2983: }
2984: FuncDeclaration::syntaxCopy(f);
2985: return f;
2986: }
2987:
2988: int FuncLiteralDeclaration::isNested()
2989: {
2990: //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2991: return (tok == TOKdelegate);
2992: }
2993:
2994: int FuncLiteralDeclaration::isVirtual()
2995: {
2996: return FALSE;
2997: }
2998:
2999: const char *FuncLiteralDeclaration::kind()
3000: {
3001: // GCC requires the (char*) casts
3002: return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
3003: }
3004:
3005: void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3006: {
3007: buf->writestring(kind());
3008: buf->writeByte(' ');
3009: type->toCBuffer(buf, NULL, hgs);
3010: bodyToCBuffer(buf, hgs);
3011: }
3012:
3013:
3014: /********************************* CtorDeclaration ****************************/
3015:
3016: CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type)
3017: : FuncDeclaration(loc, endloc, Id::ctor, stc, type)
3018: {
3019: //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
3020: }
3021:
3022: Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
3023: {
3024: CtorDeclaration *f = new CtorDeclaration(loc, endloc, storage_class, type->syntaxCopy());
3025:
3026: f->outId = outId;
3027: f->frequire = frequire ? frequire->syntaxCopy() : NULL;
3028: f->fensure = fensure ? fensure->syntaxCopy() : NULL;
3029: f->fbody = fbody ? fbody->syntaxCopy() : NULL;
3030: assert(!fthrows); // deprecated
3031:
3032: return f;
3033: }
3034:
3035:
3036: void CtorDeclaration::semantic(Scope *sc)
3037: {
3038: //printf("CtorDeclaration::semantic() %s\n", toChars());
3039: TypeFunction *tf = (TypeFunction *)type;
3040: assert(tf && tf->ty == Tfunction);
3041: Expressions *fargs = ((TypeFunction *)type)->fargs; // for auto ref
3042:
3043: sc = sc->push();
3044: sc->stc &= ~STCstatic; // not a static constructor
3045:
3046: parent = sc->parent;
3047: Dsymbol *parent = toParent2();
3048: Type *tret;
3049: AggregateDeclaration *ad = parent->isAggregateDeclaration();
3050: if (!ad || parent->isUnionDeclaration())
3051: {
3052: error("constructors are only for class or struct definitions");
3053: tret = Type::tvoid;
3054: }
3055: else
3056: { tret = ad->handle;
3057: assert(tret);
3058: tret = tret->addStorageClass(storage_class | sc->stc);
3059: }
3060: tf = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc);
3061: tf->fargs = fargs;
3062: type = tf;
3063:
3064: #if STRUCTTHISREF
3065: if (ad && ad->isStructDeclaration())
3066: { ((TypeFunction *)type)->isref = 1;
3067: if (!originalType)
3068: // Leave off the "ref"
3069: originalType = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc);
3070: }
3071: #endif
3072: if (!originalType)
3073: originalType = type;
3074:
3075: // Append:
3076: // return this;
3077: // to the function body
3078: if (fbody && semanticRun < PASSsemantic)
3079: {
3080: Expression *e = new ThisExp(loc);
3081: if (parent->isClassDeclaration())
3082: e->type = tret;
3083: Statement *s = new ReturnStatement(loc, e);
3084: fbody = new CompoundStatement(loc, fbody, s);
3085: }
3086:
3087: FuncDeclaration::semantic(sc);
3088:
3089: sc->pop();
3090:
3091: // See if it's the default constructor
3092: if (ad && tf->varargs == 0 && Parameter::dim(tf->parameters) == 0)
3093: {
3094: StructDeclaration *sd = ad->isStructDeclaration();
3095: if (sd)
3096: {
3097: if (fbody || !(storage_class & STCdisable))
3098: { error("default constructor for structs only allowed with @disable and no body");
3099: storage_class |= STCdisable;
3100: fbody = NULL;
3101: }
3102: sd->noDefaultCtor = TRUE;
3103: }
3104: else
3105: ad->defaultCtor = this;
3106: }
3107: }
3108:
3109: const char *CtorDeclaration::kind()
3110: {
3111: return "constructor";
3112: }
3113:
3114: char *CtorDeclaration::toChars()
3115: {
3116: return (char *)"this";
3117: }
3118:
3119: int CtorDeclaration::isVirtual()
3120: {
3121: return FALSE;
3122: }
3123:
3124: int CtorDeclaration::addPreInvariant()
3125: {
3126: return FALSE;
3127: }
3128:
3129: int CtorDeclaration::addPostInvariant()
3130: {
3131: return (isThis() && vthis && global.params.useInvariants);
3132: }
3133:
3134:
3135: void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3136: {
3137: TypeFunction *tf = (TypeFunction *)type;
3138: assert(tf && tf->ty == Tfunction);
3139:
3140: if (originalType && originalType->ty == Tfunction)
3141: ((TypeFunction *)originalType)->attributesToCBuffer(buf, 0);
3142: buf->writestring("this");
3143: Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
3144: bodyToCBuffer(buf, hgs);
3145: }
3146:
3147: /********************************* PostBlitDeclaration ****************************/
3148:
3149: #if DMDV2
3150: PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
3151: : FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
3152: {
3153: }
3154:
3155: PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
3156: : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
3157: {
3158: }
3159:
3160: Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
3161: {
3162: assert(!s);
3163: PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
3164: return FuncDeclaration::syntaxCopy(dd);
3165: }
3166:
3167:
3168: void PostBlitDeclaration::semantic(Scope *sc)
3169: {
3170: //printf("PostBlitDeclaration::semantic() %s\n", toChars());
3171: //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
3172: //printf("stc = x%llx\n", sc->stc);
3173: parent = sc->parent;
3174: Dsymbol *parent = toParent();
3175: StructDeclaration *ad = parent->isStructDeclaration();
3176: if (!ad)
3177: {
3178: error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars());
3179: }
3180: else if (ident == Id::_postblit && semanticRun < PASSsemantic)
3181: ad->postblits.push(this);
3182:
3183: if (!type)
3184: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3185:
3186: sc = sc->push();
3187: sc->stc &= ~STCstatic; // not static
3188: sc->linkage = LINKd;
3189:
3190: FuncDeclaration::semantic(sc);
3191:
3192: sc->pop();
3193: }
3194:
3195: int PostBlitDeclaration::overloadInsert(Dsymbol *s)
3196: {
3197: return FALSE; // cannot overload postblits
3198: }
3199:
3200: int PostBlitDeclaration::addPreInvariant()
3201: {
3202: return FALSE;
3203: }
3204:
3205: int PostBlitDeclaration::addPostInvariant()
3206: {
3207: return (isThis() && vthis && global.params.useInvariants);
3208: }
3209:
3210: int PostBlitDeclaration::isVirtual()
3211: {
3212: return FALSE;
3213: }
3214:
3215: void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3216: {
3217: buf->writestring("this(this)");
3218: bodyToCBuffer(buf, hgs);
3219: }
3220: #endif
3221:
3222: /********************************* DtorDeclaration ****************************/
3223:
3224: DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
3225: : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
3226: {
3227: }
3228:
3229: DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
3230: : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
3231: {
3232: }
3233:
3234: Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
3235: {
3236: assert(!s);
3237: DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
3238: return FuncDeclaration::syntaxCopy(dd);
3239: }
3240:
3241:
3242: void DtorDeclaration::semantic(Scope *sc)
3243: {
3244: //printf("DtorDeclaration::semantic() %s\n", toChars());
3245: //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
3246: parent = sc->parent;
3247: Dsymbol *parent = toParent();
3248: AggregateDeclaration *ad = parent->isAggregateDeclaration();
3249: if (!ad)
3250: {
3251: error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars());
3252: }
3253: else if (ident == Id::dtor && semanticRun < PASSsemantic)
3254: ad->dtors.push(this);
3255:
3256: if (!type)
3257: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3258:
3259: sc = sc->push();
3260: sc->stc &= ~STCstatic; // not a static destructor
3261: sc->linkage = LINKd;
3262:
3263: FuncDeclaration::semantic(sc);
3264:
3265: sc->pop();
3266: }
3267:
3268: int DtorDeclaration::overloadInsert(Dsymbol *s)
3269: {
3270: return FALSE; // cannot overload destructors
3271: }
3272:
3273: int DtorDeclaration::addPreInvariant()
3274: {
3275: return (isThis() && vthis && global.params.useInvariants);
3276: }
3277:
3278: int DtorDeclaration::addPostInvariant()
3279: {
3280: return FALSE;
3281: }
3282:
3283: const char *DtorDeclaration::kind()
3284: {
3285: return "destructor";
3286: }
3287:
3288: char *DtorDeclaration::toChars()
3289: {
3290: return (char *)"~this";
3291: }
3292:
3293: int DtorDeclaration::isVirtual()
3294: {
3295: /* This should be FALSE so that dtor's don't get put into the vtbl[],
3296: * but doing so will require recompiling everything.
3297: */
3298: #if BREAKABI
3299: return FALSE;
3300: #else
3301: return FuncDeclaration::isVirtual();
3302: #endif
3303: }
3304:
3305: void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3306: {
3307: buf->writestring("~this()");
3308: bodyToCBuffer(buf, hgs);
3309: }
3310:
3311: /********************************* StaticCtorDeclaration ****************************/
3312:
3313: StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
3314: : FuncDeclaration(loc, endloc,
3315: Identifier::generateId("_staticCtor"), STCstatic, NULL)
3316: {
3317: }
3318:
3319: StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, const char *name)
3320: : FuncDeclaration(loc, endloc,
3321: Identifier::generateId(name), STCstatic, NULL)
3322: {
3323: }
3324:
3325: Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
3326: {
3327: assert(!s);
3328: StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc);
3329: return FuncDeclaration::syntaxCopy(scd);
3330: }
3331:
3332:
3333: void StaticCtorDeclaration::semantic(Scope *sc)
3334: {
3335: //printf("StaticCtorDeclaration::semantic()\n");
3336:
3337: if (!type)
3338: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3339:
3340: /* If the static ctor appears within a template instantiation,
3341: * it could get called multiple times by the module constructors
3342: * for different modules. Thus, protect it with a gate.
3343: */
3344: if (inTemplateInstance() && semanticRun < PASSsemantic)
3345: {
3346: /* Add this prefix to the function:
3347: * static int gate;
3348: * if (++gate != 1) return;
3349: * Note that this is not thread safe; should not have threads
3350: * during static construction.
3351: */
3352: Identifier *id = Lexer::idPool("__gate");
3353: VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
warning C6211: Leaking memory 'v' due to an exception. Consider using a local catch block to clean up memory: Lines: 3337, 3338, 3344, 3352, 3353, 3354, 3355
3354: v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls;
3355: Statements *sa = new Statements();
warning C6211: Leaking memory 'sa' due to an exception. Consider using a local catch block to clean up memory: Lines: 3337, 3338, 3344, 3352, 3353, 3354, 3355, 3356
3356: Statement *s = new ExpStatement(0, v);
3357: sa->push(s);
3358: Expression *e = new IdentifierExp(0, id);
3359: e = new AddAssignExp(0, e, new IntegerExp(1));
3360: e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
3361: s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
3362: sa->push(s);
3363: if (fbody)
3364: sa->push(fbody);
3365: fbody = new CompoundStatement(0, sa);
3366: }
3367:
3368: FuncDeclaration::semantic(sc);
3369:
3370: // We're going to need ModuleInfo
3371: Module *m = getModule();
3372: if (!m)
3373: m = sc->module;
3374: if (m)
3375: { m->needmoduleinfo = 1;
3376: //printf("module1 %s needs moduleinfo\n", m->toChars());
3377: #ifdef IN_GCC
3378: m->strictlyneedmoduleinfo = 1;
3379: #endif
3380: }
3381: }
3382:
3383: AggregateDeclaration *StaticCtorDeclaration::isThis()
3384: {
3385: return NULL;
3386: }
3387:
3388: int StaticCtorDeclaration::isVirtual()
3389: {
3390: return FALSE;
3391: }
3392:
3393: int StaticCtorDeclaration::addPreInvariant()
3394: {
3395: return FALSE;
3396: }
3397:
3398: int StaticCtorDeclaration::addPostInvariant()
3399: {
3400: return FALSE;
3401: }
3402:
3403: void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3404: {
3405: if (hgs->hdrgen)
3406: { buf->writestring("static this();");
3407: buf->writenl();
3408: return;
3409: }
3410: buf->writestring("static this()");
3411: bodyToCBuffer(buf, hgs);
3412: }
3413:
3414: /********************************* SharedStaticCtorDeclaration ****************************/
3415:
3416: SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc, Loc endloc)
3417: : StaticCtorDeclaration(loc, endloc, "_sharedStaticCtor")
3418: {
3419: }
3420:
3421: Dsymbol *SharedStaticCtorDeclaration::syntaxCopy(Dsymbol *s)
3422: {
3423: assert(!s);
3424: SharedStaticCtorDeclaration *scd = new SharedStaticCtorDeclaration(loc, endloc);
3425: return FuncDeclaration::syntaxCopy(scd);
3426: }
3427:
3428: void SharedStaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3429: {
3430: buf->writestring("shared ");
3431: StaticCtorDeclaration::toCBuffer(buf, hgs);
3432: }
3433:
3434: /********************************* StaticDtorDeclaration ****************************/
3435:
3436: StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
3437: : FuncDeclaration(loc, endloc,
3438: Identifier::generateId("_staticDtor"), STCstatic, NULL)
3439: {
3440: vgate = NULL;
3441: }
3442:
3443: StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, const char *name)
3444: : FuncDeclaration(loc, endloc,
3445: Identifier::generateId(name), STCstatic, NULL)
3446: {
3447: vgate = NULL;
3448: }
3449:
3450: Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
3451: {
3452: assert(!s);
3453: StaticDtorDeclaration *sdd = new StaticDtorDeclaration(loc, endloc);
3454: return FuncDeclaration::syntaxCopy(sdd);
3455: }
3456:
3457:
3458: void StaticDtorDeclaration::semantic(Scope *sc)
3459: {
3460: ClassDeclaration *cd = sc->scopesym->isClassDeclaration();
3461:
3462: if (!type)
3463: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3464:
3465: /* If the static ctor appears within a template instantiation,
3466: * it could get called multiple times by the module constructors
3467: * for different modules. Thus, protect it with a gate.
3468: */
3469: if (inTemplateInstance() && semanticRun < PASSsemantic)
3470: {
3471: /* Add this prefix to the function:
3472: * static int gate;
3473: * if (--gate != 0) return;
3474: * Increment gate during constructor execution.
3475: * Note that this is not thread safe; should not have threads
3476: * during static destruction.
3477: */
3478: Identifier *id = Lexer::idPool("__gate");
3479: VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
warning C6211: Leaking memory 'v' due to an exception. Consider using a local catch block to clean up memory: Lines: 3460, 3462, 3463, 3469, 3478, 3479, 3480, 3481
3480: v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls;
3481: Statements *sa = new Statements();
warning C6211: Leaking memory 'sa' due to an exception. Consider using a local catch block to clean up memory: Lines: 3460, 3462, 3463, 3469, 3478, 3479, 3480, 3481, 3482
3482: Statement *s = new ExpStatement(0, v);
3483: sa->push(s);
3484: Expression *e = new IdentifierExp(0, id);
3485: e = new AddAssignExp(0, e, new IntegerExp(-1));
3486: e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0));
3487: s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
3488: sa->push(s);
3489: if (fbody)
3490: sa->push(fbody);
3491: fbody = new CompoundStatement(0, sa);
3492: vgate = v;
3493: }
3494:
3495: FuncDeclaration::semantic(sc);
3496:
3497: // We're going to need ModuleInfo
3498: Module *m = getModule();
3499: if (!m)
3500: m = sc->module;
3501: if (m)
3502: { m->needmoduleinfo = 1;
3503: //printf("module2 %s needs moduleinfo\n", m->toChars());
3504: #ifdef IN_GCC
3505: m->strictlyneedmoduleinfo = 1;
3506: #endif
3507: }
3508: }
3509:
3510: AggregateDeclaration *StaticDtorDeclaration::isThis()
3511: {
3512: return NULL;
3513: }
3514:
3515: int StaticDtorDeclaration::isVirtual()
3516: {
3517: return FALSE;
3518: }
3519:
3520: int StaticDtorDeclaration::addPreInvariant()
3521: {
3522: return FALSE;
3523: }
3524:
3525: int StaticDtorDeclaration::addPostInvariant()
3526: {
3527: return FALSE;
3528: }
3529:
3530: void StaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3531: {
3532: if (hgs->hdrgen)
3533: return;
3534: buf->writestring("static ~this()");
3535: bodyToCBuffer(buf, hgs);
3536: }
3537:
3538: /********************************* SharedStaticDtorDeclaration ****************************/
3539:
3540: SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc, Loc endloc)
3541: : StaticDtorDeclaration(loc, endloc, "_sharedStaticDtor")
3542: {
3543: }
3544:
3545: Dsymbol *SharedStaticDtorDeclaration::syntaxCopy(Dsymbol *s)
3546: {
3547: assert(!s);
3548: SharedStaticDtorDeclaration *sdd = new SharedStaticDtorDeclaration(loc, endloc);
3549: return FuncDeclaration::syntaxCopy(sdd);
3550: }
3551:
3552: void SharedStaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3553: {
3554: if (!hgs->hdrgen)
3555: {
3556: buf->writestring("shared ");
3557: StaticDtorDeclaration::toCBuffer(buf, hgs);
3558: }
3559: }
3560:
3561:
3562: /********************************* InvariantDeclaration ****************************/
3563:
3564: InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc)
3565: : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL)
3566: {
3567: }
3568:
3569: Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
3570: {
3571: InvariantDeclaration *id;
3572:
3573: assert(!s);
3574: id = new InvariantDeclaration(loc, endloc);
3575: FuncDeclaration::syntaxCopy(id);
3576: return id;
3577: }
3578:
3579:
3580: void InvariantDeclaration::semantic(Scope *sc)
3581: {
3582: parent = sc->parent;
3583: Dsymbol *parent = toParent();
3584: AggregateDeclaration *ad = parent->isAggregateDeclaration();
3585: if (!ad)
3586: {
3587: error("invariants are only for struct/union/class definitions");
3588: return;
3589: }
3590: else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic)
3591: {
3592: error("more than one invariant for %s", ad->toChars());
3593: }
3594: ad->inv = this;
3595: if (!type)
3596: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3597:
3598: sc = sc->push();
3599: sc->stc &= ~STCstatic; // not a static invariant
3600: sc->incontract++;
3601: sc->linkage = LINKd;
3602:
3603: FuncDeclaration::semantic(sc);
3604:
3605: sc->pop();
3606: }
3607:
3608: int InvariantDeclaration::isVirtual()
3609: {
3610: return FALSE;
3611: }
3612:
3613: int InvariantDeclaration::addPreInvariant()
3614: {
3615: return FALSE;
3616: }
3617:
3618: int InvariantDeclaration::addPostInvariant()
3619: {
3620: return FALSE;
3621: }
3622:
3623: void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3624: {
3625: if (hgs->hdrgen)
3626: return;
3627: buf->writestring("invariant");
3628: bodyToCBuffer(buf, hgs);
3629: }
3630:
3631:
3632: /********************************* UnitTestDeclaration ****************************/
3633:
3634: /*******************************
3635: * Generate unique unittest function Id so we can have multiple
3636: * instances per module.
3637: */
3638:
3639: static Identifier *unitTestId()
3640: {
3641: return Lexer::uniqueId("__unittest");
3642: }
3643:
3644: UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
3645: : FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
3646: {
3647: }
3648:
3649: Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
3650: {
3651: UnitTestDeclaration *utd;
3652:
3653: assert(!s);
3654: utd = new UnitTestDeclaration(loc, endloc);
3655: return FuncDeclaration::syntaxCopy(utd);
3656: }
3657:
3658:
3659: void UnitTestDeclaration::semantic(Scope *sc)
3660: {
3661: if (global.params.useUnitTests)
3662: {
3663: if (!type)
3664: type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
3665: Scope *sc2 = sc->push();
3666: // It makes no sense for unit tests to be pure or nothrow.
3667: sc2->stc &= ~(STCnothrow | STCpure);
3668: sc2->linkage = LINKd;
3669: FuncDeclaration::semantic(sc2);
3670: sc2->pop();
3671: }
3672:
3673: #if 0
3674: // We're going to need ModuleInfo even if the unit tests are not
3675: // compiled in, because other modules may import this module and refer
3676: // to this ModuleInfo.
3677: // (This doesn't make sense to me?)
3678: Module *m = getModule();
3679: if (!m)
3680: m = sc->module;
3681: if (m)
3682: {
3683: //printf("module3 %s needs moduleinfo\n", m->toChars());
3684: m->needmoduleinfo = 1;
3685: }
3686: #endif
3687: }
3688:
3689: AggregateDeclaration *UnitTestDeclaration::isThis()
3690: {
3691: return NULL;
3692: }
3693:
3694: int UnitTestDeclaration::isVirtual()
3695: {
3696: return FALSE;
3697: }
3698:
3699: int UnitTestDeclaration::addPreInvariant()
3700: {
3701: return FALSE;
3702: }
3703:
3704: int UnitTestDeclaration::addPostInvariant()
3705: {
3706: return FALSE;
3707: }
3708:
3709: void UnitTestDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3710: {
3711: if (hgs->hdrgen)
3712: return;
3713: buf->writestring("unittest");
3714: bodyToCBuffer(buf, hgs);
3715: }
3716:
3717: /********************************* NewDeclaration ****************************/
3718:
3719: NewDeclaration::NewDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs)
3720: : FuncDeclaration(loc, endloc, Id::classNew, STCstatic, NULL)
3721: {
3722: this->arguments = arguments;
3723: this->varargs = varargs;
3724: }
3725:
3726: Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
3727: {
3728: NewDeclaration *f;
3729:
3730: f = new NewDeclaration(loc, endloc, NULL, varargs);
3731:
3732: FuncDeclaration::syntaxCopy(f);
3733:
3734: f->arguments = Parameter::arraySyntaxCopy(arguments);
3735:
3736: return f;
3737: }
3738:
3739:
3740: void NewDeclaration::semantic(Scope *sc)
3741: {
3742: //printf("NewDeclaration::semantic()\n");
3743:
3744: parent = sc->parent;
3745: Dsymbol *parent = toParent();
3746: ClassDeclaration *cd = parent->isClassDeclaration();
3747: if (!cd && !parent->isStructDeclaration())
3748: {
3749: error("new allocators only are for class or struct definitions");
3750: }
3751: Type *tret = Type::tvoid->pointerTo();
3752: if (!type)
3753: type = new TypeFunction(arguments, tret, varargs, LINKd);
3754:
3755: type = type->semantic(loc, sc);
3756: assert(type->ty == Tfunction);
3757:
3758: // Check that there is at least one argument of type size_t
3759: TypeFunction *tf = (TypeFunction *)type;
3760: if (Parameter::dim(tf->parameters) < 1)
3761: {
3762: error("at least one argument of type size_t expected");
3763: }
3764: else
3765: {
3766: Parameter *a = Parameter::getNth(tf->parameters, 0);
3767: if (!a->type->equals(Type::tsize_t))
3768: error("first argument must be type size_t, not %s", a->type->toChars());
3769: }
3770:
3771: FuncDeclaration::semantic(sc);
3772: }
3773:
3774: const char *NewDeclaration::kind()
3775: {
3776: return "allocator";
3777: }
3778:
3779: int NewDeclaration::isVirtual()
3780: {
3781: return FALSE;
3782: }
3783:
3784: int NewDeclaration::addPreInvariant()
3785: {
3786: return FALSE;
3787: }
3788:
3789: int NewDeclaration::addPostInvariant()
3790: {
3791: return FALSE;
3792: }
3793:
3794: void NewDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3795: {
3796: buf->writestring("new");
3797: Parameter::argsToCBuffer(buf, hgs, arguments, varargs);
3798: bodyToCBuffer(buf, hgs);
3799: }
3800:
3801:
3802: /********************************* DeleteDeclaration ****************************/
3803:
3804: DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, Parameters *arguments)
3805: : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic, NULL)
3806: {
3807: this->arguments = arguments;
3808: }
3809:
3810: Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
3811: {
3812: DeleteDeclaration *f;
3813:
3814: f = new DeleteDeclaration(loc, endloc, NULL);
3815:
3816: FuncDeclaration::syntaxCopy(f);
3817:
3818: f->arguments = Parameter::arraySyntaxCopy(arguments);
3819:
3820: return f;
3821: }
3822:
3823:
3824: void DeleteDeclaration::semantic(Scope *sc)
3825: {
3826: //printf("DeleteDeclaration::semantic()\n");
3827:
3828: parent = sc->parent;
3829: Dsymbol *parent = toParent();
3830: ClassDeclaration *cd = parent->isClassDeclaration();
3831: if (!cd && !parent->isStructDeclaration())
3832: {
3833: error("new allocators only are for class or struct definitions");
3834: }
3835: if (!type)
3836: type = new TypeFunction(arguments, Type::tvoid, 0, LINKd);
3837:
3838: type = type->semantic(loc, sc);
3839: assert(type->ty == Tfunction);
3840:
3841: // Check that there is only one argument of type void*
3842: TypeFunction *tf = (TypeFunction *)type;
3843: if (Parameter::dim(tf->parameters) != 1)
3844: {
3845: error("one argument of type void* expected");
3846: }
3847: else
3848: {
3849: Parameter *a = Parameter::getNth(tf->parameters, 0);
3850: if (!a->type->equals(Type::tvoid->pointerTo()))
3851: error("one argument of type void* expected, not %s", a->type->toChars());
3852: }
3853:
3854: FuncDeclaration::semantic(sc);
3855: }
3856:
3857: const char *DeleteDeclaration::kind()
3858: {
3859: return "deallocator";
3860: }
3861:
3862: int DeleteDeclaration::isDelete()
3863: {
3864: return TRUE;
3865: }
3866:
3867: int DeleteDeclaration::isVirtual()
3868: {
3869: return FALSE;
3870: }
3871:
3872: int DeleteDeclaration::addPreInvariant()
3873: {
3874: return FALSE;
3875: }
3876:
3877: int DeleteDeclaration::addPostInvariant()
3878: {
3879: return FALSE;
3880: }
3881:
3882: void DeleteDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3883: {
3884: buf->writestring("delete");
3885: Parameter::argsToCBuffer(buf, hgs, arguments, 0);
3886: bodyToCBuffer(buf, hgs);
3887: }
3888:
3889:
3890:
3891:
3892: