Mercurial > projects > ldc
comparison dmd2/func.c @ 1452:638d16625da2
LDC 2 compiles again.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 30 May 2009 17:23:32 +0100 |
parents | 03d7c4aac654 |
children | 7d1e815b4f76 |
comparison
equal
deleted
inserted
replaced
1423:42bd767ec5a4 | 1452:638d16625da2 |
---|---|
33 | 33 |
34 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type) | 34 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type) |
35 : Declaration(id) | 35 : Declaration(id) |
36 { | 36 { |
37 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type); | 37 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type); |
38 //printf("storage_class = x%x\n", storage_class); | |
38 this->storage_class = storage_class; | 39 this->storage_class = storage_class; |
39 this->type = type; | 40 this->type = type; |
40 this->loc = loc; | 41 this->loc = loc; |
41 this->endloc = endloc; | 42 this->endloc = endloc; |
42 fthrows = NULL; | 43 fthrows = NULL; |
72 inferRetType = (type && type->nextOf() == NULL); | 73 inferRetType = (type && type->nextOf() == NULL); |
73 scope = NULL; | 74 scope = NULL; |
74 hasReturnExp = 0; | 75 hasReturnExp = 0; |
75 nrvo_can = 1; | 76 nrvo_can = 1; |
76 nrvo_var = NULL; | 77 nrvo_var = NULL; |
78 #if IN_DMD | |
77 shidden = NULL; | 79 shidden = NULL; |
80 #endif | |
81 | |
78 builtin = BUILTINunknown; | 82 builtin = BUILTINunknown; |
79 tookAddressOf = 0; | 83 tookAddressOf = 0; |
80 | 84 |
85 #if IN_LLVM | |
81 // LDC | 86 // LDC |
82 isArrayOp = false; | 87 isArrayOp = false; |
83 allowInlining = false; | 88 allowInlining = false; |
89 | |
90 // function types in ldc don't merge if the context parameter differs | |
91 // so we actually don't care about the function declaration, but only | |
92 // what kind of context parameter it has. | |
93 // however, this constructor is usually called from the parser, which | |
94 // unfortunately doesn't provide the information needed to get to the | |
95 // aggregate type. So we have to stick with the FuncDeclaration and | |
96 // just be sure we don't actually rely on the symbol it points to, | |
97 // but rather just the type of its context parameter. | |
98 // this means some function might have a function type pointing to | |
99 // another function declaration | |
100 | |
101 if (type) | |
102 { | |
103 assert(type->ty == Tfunction && "invalid function type"); | |
104 TypeFunction* tf = (TypeFunction*)type; | |
105 if (tf->funcdecl == NULL) | |
106 tf->funcdecl = this; | |
107 } | |
108 #endif | |
84 } | 109 } |
85 | 110 |
86 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) | 111 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) |
87 { | 112 { |
88 FuncDeclaration *f; | 113 FuncDeclaration *f; |
116 | 141 |
117 #if 0 | 142 #if 0 |
118 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage); | 143 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage); |
119 if (isFuncLiteralDeclaration()) | 144 if (isFuncLiteralDeclaration()) |
120 printf("\tFuncLiteralDeclaration()\n"); | 145 printf("\tFuncLiteralDeclaration()\n"); |
121 printf("sc->parent = %s\n", sc->parent->toChars()); | 146 printf("sc->parent = %s, parent = %s\n", sc->parent->toChars(), parent ? parent->toChars() : ""); |
122 printf("type: %p, %s\n", type, type->toChars()); | 147 printf("type: %p, %s\n", type, type->toChars()); |
123 #endif | 148 #endif |
149 | |
150 if (semanticRun && isFuncLiteralDeclaration()) | |
151 { | |
152 /* Member functions that have return types that are | |
153 * forward references can have semantic() run more than | |
154 * once on them. | |
155 * See test\interface2.d, test20 | |
156 */ | |
157 return; | |
158 } | |
159 assert(semanticRun <= 1); | |
160 semanticRun = 1; | |
124 | 161 |
125 storage_class |= sc->stc & ~STCref; | 162 storage_class |= sc->stc & ~STCref; |
126 //printf("function storage_class = x%x\n", storage_class); | 163 //printf("function storage_class = x%x\n", storage_class); |
127 | 164 |
128 if (!originalType) | 165 if (!originalType) |
129 originalType = type; | 166 originalType = type; |
130 if (!type->deco && type->nextOf()) | 167 if (!type->deco && type->nextOf()) |
131 { | 168 { |
132 #if 1 | |
133 /* Apply const and invariant storage class | 169 /* Apply const and invariant storage class |
134 * to the function type | 170 * to the function type |
135 */ | 171 */ |
136 type = type->semantic(loc, sc); | 172 type = type->semantic(loc, sc); |
137 if (storage_class & STCinvariant) | 173 unsigned stc = storage_class; |
138 { // Don't use toInvariant(), as that will do a merge() | 174 if (type->isInvariant()) |
139 type = type->makeInvariant(); | 175 stc |= STCimmutable; |
140 type->deco = type->merge()->deco; | 176 if (type->isConst()) |
141 } | 177 stc |= STCconst; |
142 else if (storage_class & STCconst) | 178 if (type->isShared()) |
143 { | 179 stc |= STCshared; |
144 if (!type->isInvariant()) | 180 switch (stc & STC_TYPECTOR) |
145 { // Don't use toConst(), as that will do a merge() | 181 { |
182 case STCimmutable: | |
183 case STCimmutable | STCconst: | |
184 case STCimmutable | STCconst | STCshared: | |
185 case STCimmutable | STCshared: | |
186 // Don't use toInvariant(), as that will do a merge() | |
187 type = type->makeInvariant(); | |
188 type->deco = type->merge()->deco; | |
189 break; | |
190 | |
191 case STCconst: | |
146 type = type->makeConst(); | 192 type = type->makeConst(); |
147 type->deco = type->merge()->deco; | 193 type->deco = type->merge()->deco; |
148 } | 194 break; |
149 } | 195 |
150 #else | 196 case STCshared | STCconst: |
151 if (storage_class & (STCconst | STCinvariant)) | 197 type = type->makeSharedConst(); |
152 { | 198 type->deco = type->merge()->deco; |
153 /* Apply const and invariant storage class | 199 break; |
154 * to the function's return type | 200 |
155 */ | 201 case STCshared: |
156 Type *tn = type->nextOf(); | 202 type = type->makeShared(); |
157 if (storage_class & STCconst) | 203 type->deco = type->merge()->deco; |
158 tn = tn->makeConst(); | 204 break; |
159 if (storage_class & STCinvariant) | 205 |
160 tn = tn->makeInvariant(); | 206 case 0: |
161 ((TypeNext *)type)->next = tn; | 207 break; |
162 } | 208 |
163 | 209 default: |
164 type = type->semantic(loc, sc); | 210 assert(0); |
165 #endif | 211 } |
166 } | 212 } |
167 //type->print(); | 213 //type->print(); |
168 if (type->ty != Tfunction) | 214 if (type->ty != Tfunction) |
169 { | 215 { |
170 error("%s must be a function", toChars()); | 216 error("%s must be a function", toChars()); |
188 | 234 |
189 if (isAbstract() && !isVirtual()) | 235 if (isAbstract() && !isVirtual()) |
190 error("non-virtual functions cannot be abstract"); | 236 error("non-virtual functions cannot be abstract"); |
191 | 237 |
192 if ((f->isConst() || f->isInvariant()) && !isThis()) | 238 if ((f->isConst() || f->isInvariant()) && !isThis()) |
193 error("without 'this' cannot be const/invariant"); | 239 error("without 'this' cannot be const/immutable"); |
194 | 240 |
195 if (isAbstract() && isFinal()) | 241 if (isAbstract() && isFinal()) |
196 error("cannot be both final and abstract"); | 242 error("cannot be both final and abstract"); |
197 #if 0 | 243 #if 0 |
198 if (isAbstract() && fbody) | 244 if (isAbstract() && fbody) |
345 if (cd->baseClass) | 391 if (cd->baseClass) |
346 { Dsymbol *s = cd->baseClass->search(loc, ident, 0); | 392 { Dsymbol *s = cd->baseClass->search(loc, ident, 0); |
347 if (s) | 393 if (s) |
348 { | 394 { |
349 FuncDeclaration *f = s->isFuncDeclaration(); | 395 FuncDeclaration *f = s->isFuncDeclaration(); |
350 f = f->overloadExactMatch(type); | 396 f = f->overloadExactMatch(type, getModule()); |
351 if (f && f->isFinal() && f->prot() != PROTprivate) | 397 if (f && f->isFinal() && f->prot() != PROTprivate) |
352 error("cannot override final function %s", f->toPrettyChars()); | 398 error("cannot override final function %s", f->toPrettyChars()); |
353 } | 399 } |
354 } | 400 } |
355 | 401 |
356 if (isFinal()) | 402 if (isFinal()) |
357 { | 403 { |
404 if (isOverride()) | |
405 error("does not override any function"); | |
358 cd->vtblFinal.push(this); | 406 cd->vtblFinal.push(this); |
359 } | 407 } |
360 else | 408 else |
361 { | 409 { |
362 // Append to end of vtbl[] | 410 // Append to end of vtbl[] |
377 // This function is covariant with fdv | 425 // This function is covariant with fdv |
378 if (fdv->isFinal()) | 426 if (fdv->isFinal()) |
379 error("cannot override final function %s", fdv->toPrettyChars()); | 427 error("cannot override final function %s", fdv->toPrettyChars()); |
380 | 428 |
381 #if DMDV2 | 429 #if DMDV2 |
382 if (!isOverride() && global.params.warnings) | 430 if (!isOverride()) |
383 warning("%s: overrides base class function %s, but is not marked with 'override'", locToChars(), fdv->toPrettyChars()); | 431 warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); |
384 #endif | 432 #endif |
385 | 433 |
386 if (fdv->toParent() == parent) | 434 if (fdv->toParent() == parent) |
387 { | 435 { |
388 // If both are mixins, then error. | 436 // If both are mixins, then error. |
601 | 649 |
602 // Do the semantic analysis on the internals of the function. | 650 // Do the semantic analysis on the internals of the function. |
603 | 651 |
604 void FuncDeclaration::semantic3(Scope *sc) | 652 void FuncDeclaration::semantic3(Scope *sc) |
605 { TypeFunction *f; | 653 { TypeFunction *f; |
606 AggregateDeclaration *ad; | |
607 VarDeclaration *argptr = NULL; | 654 VarDeclaration *argptr = NULL; |
608 VarDeclaration *_arguments = NULL; | 655 VarDeclaration *_arguments = NULL; |
609 | 656 |
610 if (!parent) | 657 if (!parent) |
611 { | 658 { |
614 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); | 661 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); |
615 assert(0); | 662 assert(0); |
616 } | 663 } |
617 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); | 664 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); |
618 //fflush(stdout); | 665 //fflush(stdout); |
666 //printf("storage class = x%x %x\n", sc->stc, storage_class); | |
619 //{ static int x; if (++x == 2) *(char*)0=0; } | 667 //{ static int x; if (++x == 2) *(char*)0=0; } |
620 //printf("\tlinkage = %d\n", sc->linkage); | 668 //printf("\tlinkage = %d\n", sc->linkage); |
621 | 669 |
622 //printf(" sc->incontract = %d\n", sc->incontract); | 670 //printf(" sc->incontract = %d\n", sc->incontract); |
623 if (semanticRun) | 671 if (semanticRun >= 3) |
624 return; | 672 return; |
625 semanticRun = 1; | 673 semanticRun = 3; |
626 | 674 |
627 if (!type || type->ty != Tfunction) | 675 if (!type || type->ty != Tfunction) |
628 return; | 676 return; |
629 f = (TypeFunction *)(type); | 677 f = (TypeFunction *)(type); |
678 size_t nparams = Argument::dim(f->parameters); | |
630 | 679 |
631 // Check the 'throws' clause | 680 // Check the 'throws' clause |
632 if (fthrows) | 681 if (fthrows) |
633 { | 682 { |
634 for (int i = 0; i < fthrows->dim; i++) | 683 for (int i = 0; i < fthrows->dim; i++) |
658 sc2->sbreak = NULL; | 707 sc2->sbreak = NULL; |
659 sc2->scontinue = NULL; | 708 sc2->scontinue = NULL; |
660 sc2->sw = NULL; | 709 sc2->sw = NULL; |
661 sc2->fes = fes; | 710 sc2->fes = fes; |
662 sc2->linkage = LINKd; | 711 sc2->linkage = LINKd; |
663 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCconst | STCfinal | STCinvariant | STCtls); | 712 sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref); |
664 sc2->protection = PROTpublic; | 713 sc2->protection = PROTpublic; |
665 sc2->explicitProtection = 0; | 714 sc2->explicitProtection = 0; |
666 sc2->structalign = 8; | 715 sc2->structalign = 8; |
667 sc2->incontract = 0; | 716 sc2->incontract = 0; |
717 #if !IN_LLVM | |
668 sc2->tf = NULL; | 718 sc2->tf = NULL; |
669 sc2->tfOfTry = NULL; | 719 #else |
720 sc2->enclosingFinally = NULL; | |
721 sc2->enclosingScopeExit = NULL; | |
722 #endif | |
670 sc2->noctor = 0; | 723 sc2->noctor = 0; |
671 | 724 |
672 // Declare 'this' | 725 // Declare 'this' |
673 ad = isThis(); | 726 AggregateDeclaration *ad = isThis(); |
674 if (ad) | 727 if (ad) |
675 { VarDeclaration *v; | 728 { VarDeclaration *v; |
676 | 729 |
677 if (isFuncLiteralDeclaration() && isNested()) | 730 if (isFuncLiteralDeclaration() && isNested()) |
678 { | 731 { |
682 else | 735 else |
683 { | 736 { |
684 assert(!isNested()); // can't be both member and nested | 737 assert(!isNested()); // can't be both member and nested |
685 assert(ad->handle); | 738 assert(ad->handle); |
686 Type *thandle = ad->handle; | 739 Type *thandle = ad->handle; |
740 #if STRUCTTHISREF | |
741 thandle = thandle->addMod(type->mod); | |
742 thandle = thandle->addStorageClass(storage_class); | |
743 if (isPure()) | |
744 thandle = thandle->addMod(MODconst); | |
745 #else | |
687 if (storage_class & STCconst || type->isConst()) | 746 if (storage_class & STCconst || type->isConst()) |
688 { | 747 { |
689 #if STRUCTTHISREF | 748 assert(0); // BUG: shared not handled |
690 thandle = thandle->constOf(); | |
691 #else | |
692 if (thandle->ty == Tclass) | 749 if (thandle->ty == Tclass) |
693 thandle = thandle->constOf(); | 750 thandle = thandle->constOf(); |
694 else | 751 else |
695 { assert(thandle->ty == Tpointer); | 752 { assert(thandle->ty == Tpointer); |
696 thandle = thandle->nextOf()->constOf()->pointerTo(); | 753 thandle = thandle->nextOf()->constOf()->pointerTo(); |
697 } | 754 } |
698 #endif | |
699 } | 755 } |
700 else if (storage_class & STCinvariant || type->isInvariant()) | 756 else if (storage_class & STCimmutable || type->isInvariant()) |
701 { | 757 { |
702 #if STRUCTTHISREF | |
703 thandle = thandle->invariantOf(); | |
704 #else | |
705 if (thandle->ty == Tclass) | 758 if (thandle->ty == Tclass) |
706 thandle = thandle->invariantOf(); | 759 thandle = thandle->invariantOf(); |
707 else | 760 else |
708 { assert(thandle->ty == Tpointer); | 761 { assert(thandle->ty == Tpointer); |
709 thandle = thandle->nextOf()->invariantOf()->pointerTo(); | 762 thandle = thandle->nextOf()->invariantOf()->pointerTo(); |
710 } | 763 } |
711 #endif | |
712 } | 764 } |
713 v = new ThisDeclaration(thandle); | 765 else if (storage_class & STCshared || type->isShared()) |
766 { | |
767 assert(0); // not implemented | |
768 } | |
769 #endif | |
770 v = new ThisDeclaration(loc, thandle); | |
714 v->storage_class |= STCparameter; | 771 v->storage_class |= STCparameter; |
715 #if STRUCTTHISREF | 772 #if STRUCTTHISREF |
716 if (thandle->ty == Tstruct) | 773 if (thandle->ty == Tstruct) |
717 v->storage_class |= STCref; | 774 v->storage_class |= STCref; |
718 #endif | 775 #endif |
727 { | 784 { |
728 /* The 'this' for a nested function is the link to the | 785 /* The 'this' for a nested function is the link to the |
729 * enclosing function's stack frame. | 786 * enclosing function's stack frame. |
730 * Note that nested functions and member functions are disjoint. | 787 * Note that nested functions and member functions are disjoint. |
731 */ | 788 */ |
732 VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo()); | 789 VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo()); |
733 v->storage_class |= STCparameter; | 790 v->storage_class |= STCparameter; |
734 v->semantic(sc2); | 791 v->semantic(sc2); |
735 if (!sc2->insert(v)) | 792 if (!sc2->insert(v)) |
736 assert(0); | 793 assert(0); |
737 v->parent = this; | 794 v->parent = this; |
738 vthis = v; | 795 vthis = v; |
739 } | 796 } |
740 | 797 |
741 // Declare hidden variable _arguments[] and _argptr | 798 // Declare hidden variable _arguments[] and _argptr |
742 if (f->varargs == 1) | 799 if (f->varargs == 1) |
743 { Type *t; | 800 { |
801 #if TARGET_NET | |
802 varArgs(sc2, f, argptr, _arguments); | |
803 #else | |
804 Type *t; | |
744 | 805 |
745 if (f->linkage == LINKd) | 806 if (f->linkage == LINKd) |
746 { // Declare _arguments[] | 807 { // Declare _arguments[] |
747 #if BREAKABI | 808 #if BREAKABI |
748 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); | 809 v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); |
776 argptr = new VarDeclaration(0, t, Id::_argptr, NULL); | 837 argptr = new VarDeclaration(0, t, Id::_argptr, NULL); |
777 argptr->semantic(sc2); | 838 argptr->semantic(sc2); |
778 sc2->insert(argptr); | 839 sc2->insert(argptr); |
779 argptr->parent = this; | 840 argptr->parent = this; |
780 } | 841 } |
781 } | 842 #endif |
843 } | |
844 | |
845 #if IN_LLVM | |
846 // LDC make sure argument type is semanticed. | |
847 // Turns TypeTuple!(int, int) into two int parameters, for instance. | |
848 if (f->parameters) | |
849 { | |
850 for (size_t i = 0; i < Argument::dim(f->parameters); i++) | |
851 { Argument *arg = (Argument *)Argument::getNth(f->parameters, i); | |
852 Type* nw = arg->type->semantic(0, sc); | |
853 if (arg->type != nw) { | |
854 arg->type = nw; | |
855 // Examine this index again. | |
856 // This is important if it turned into a tuple. | |
857 // In particular, the empty tuple should be handled or the | |
858 // next parameter will be skipped. | |
859 // FIXME: Maybe we only need to do this for tuples, | |
860 // and can add tuple.length after decrement? | |
861 i--; | |
862 } | |
863 } | |
864 // update nparams to include expanded tuples | |
865 nparams = Argument::dim(f->parameters); | |
866 } | |
867 #endif | |
782 | 868 |
783 // Propagate storage class from tuple parameters to their element-parameters. | 869 // Propagate storage class from tuple parameters to their element-parameters. |
784 if (f->parameters) | 870 if (f->parameters) |
785 { | 871 { |
786 for (size_t i = 0; i < f->parameters->dim; i++) | 872 for (size_t i = 0; i < f->parameters->dim; i++) |
816 /* Generate identifier for un-named parameter, | 902 /* Generate identifier for un-named parameter, |
817 * because we need it later on. | 903 * because we need it later on. |
818 */ | 904 */ |
819 arg->ident = id = Identifier::generateId("_param_", i); | 905 arg->ident = id = Identifier::generateId("_param_", i); |
820 } | 906 } |
821 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL); | 907 Type *vtype = arg->type; |
908 if (isPure()) | |
909 vtype = vtype->addMod(MODconst); | |
910 VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL); | |
822 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); | 911 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); |
823 v->storage_class |= STCparameter; | 912 v->storage_class |= STCparameter; |
824 if (f->varargs == 2 && i + 1 == nparams) | 913 if (f->varargs == 2 && i + 1 == nparams) |
825 v->storage_class |= STCvariadic; | 914 v->storage_class |= STCvariadic; |
826 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STCconst | STCinvariant | STCnodtor); | 915 v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); |
827 v->semantic(sc2); | 916 v->semantic(sc2); |
828 if (!sc2->insert(v)) | 917 if (!sc2->insert(v)) |
829 error("parameter %s.%s is already defined", toChars(), v->toChars()); | 918 error("parameter %s.%s is already defined", toChars(), v->toChars()); |
830 else | 919 else |
831 parameters->push(v); | 920 parameters->push(v); |
1064 | 1153 |
1065 // Insert implicit super() at start of fbody | 1154 // Insert implicit super() at start of fbody |
1066 Expression *e1 = new SuperExp(0); | 1155 Expression *e1 = new SuperExp(0); |
1067 Expression *e = new CallExp(0, e1); | 1156 Expression *e = new CallExp(0, e1); |
1068 | 1157 |
1069 unsigned errors = global.errors; | 1158 e = e->trySemantic(sc2); |
1070 global.gag++; | 1159 if (!e) |
1071 e = e->semantic(sc2); | |
1072 global.gag--; | |
1073 if (errors != global.errors) | |
1074 error("no match for implicit super() call in constructor"); | 1160 error("no match for implicit super() call in constructor"); |
1075 | 1161 else |
1076 Statement *s = new ExpStatement(0, e); | 1162 { |
1077 fbody = new CompoundStatement(0, s, fbody); | 1163 Statement *s = new ExpStatement(0, e); |
1164 fbody = new CompoundStatement(0, s, fbody); | |
1165 } | |
1078 } | 1166 } |
1079 } | 1167 } |
1080 else if (fes) | 1168 else if (fes) |
1081 { // For foreach(){} body, append a return 0; | 1169 { // For foreach(){} body, append a return 0; |
1082 Expression *e = new IntegerExp(0); | 1170 Expression *e = new IntegerExp(0); |
1086 } | 1174 } |
1087 else if (!hasReturnExp && type->nextOf()->ty != Tvoid) | 1175 else if (!hasReturnExp && type->nextOf()->ty != Tvoid) |
1088 error("expected to return a value of type %s", type->nextOf()->toChars()); | 1176 error("expected to return a value of type %s", type->nextOf()->toChars()); |
1089 else if (!inlineAsm) | 1177 else if (!inlineAsm) |
1090 { | 1178 { |
1091 int offend = fbody ? fbody->blockExit() & BEfallthru : TRUE; | 1179 int blockexit = fbody ? fbody->blockExit() : 0; |
1092 //int offend = fbody ? fbody->fallOffEnd() : TRUE; | 1180 if (f->isnothrow && blockexit & BEthrow) |
1181 error("'%s' is nothrow yet may throw", toChars()); | |
1182 | |
1183 int offend = blockexit & BEfallthru; | |
1093 | 1184 |
1094 if (type->nextOf()->ty == Tvoid) | 1185 if (type->nextOf()->ty == Tvoid) |
1095 { | 1186 { |
1096 if (offend && isMain()) | 1187 if (offend && isMain()) |
1097 { // Add a return 0; statement | 1188 { // Add a return 0; statement |
1102 else | 1193 else |
1103 { | 1194 { |
1104 if (offend) | 1195 if (offend) |
1105 { Expression *e; | 1196 { Expression *e; |
1106 | 1197 |
1107 if (global.params.warnings) | 1198 warning(loc, "no return at end of function"); |
1108 { warning("%s: no return at end of function", locToChars()); | |
1109 } | |
1110 | 1199 |
1111 if (global.params.useAssert && | 1200 if (global.params.useAssert && |
1112 !global.params.useInline) | 1201 !global.params.useInline) |
1113 { /* Add an assert(0, msg); where the missing return | 1202 { /* Add an assert(0, msg); where the missing return |
1114 * should be. | 1203 * should be. |
1185 Expression *e = new VarExp(0, v_arguments); | 1274 Expression *e = new VarExp(0, v_arguments); |
1186 e = new DotIdExp(0, e, Id::elements); | 1275 e = new DotIdExp(0, e, Id::elements); |
1187 Expression *e1 = new VarExp(0, _arguments); | 1276 Expression *e1 = new VarExp(0, _arguments); |
1188 e = new AssignExp(0, e1, e); | 1277 e = new AssignExp(0, e1, e); |
1189 e->op = TOKconstruct; | 1278 e->op = TOKconstruct; |
1190 e = e->semantic(sc); | 1279 e = e->semantic(sc2); |
1191 a->push(new ExpStatement(0, e)); | 1280 a->push(new ExpStatement(0, e)); |
1192 } | 1281 } |
1193 | 1282 |
1194 #endif // !IN_LLVM | 1283 #endif // !IN_LLVM |
1195 | 1284 |
1207 | 1296 |
1208 // Precondition invariant | 1297 // Precondition invariant |
1209 if (addPreInvariant()) | 1298 if (addPreInvariant()) |
1210 { | 1299 { |
1211 Expression *e = NULL; | 1300 Expression *e = NULL; |
1301 Expression *ee = NULL; | |
1212 if (isDtorDeclaration()) | 1302 if (isDtorDeclaration()) |
1213 { | 1303 { |
1214 // Call invariant directly only if it exists | 1304 // Call invariant directly only if it exists |
1215 InvariantDeclaration *inv = ad->inv; | 1305 InvariantDeclaration *inv = ad->inv; |
1216 ClassDeclaration *cd = ad->isClassDeclaration(); | 1306 ClassDeclaration *cd = ad->isClassDeclaration(); |
1235 v->type = vthis->type; | 1325 v->type = vthis->type; |
1236 #if STRUCTTHISREF | 1326 #if STRUCTTHISREF |
1237 if (ad->isStructDeclaration()) | 1327 if (ad->isStructDeclaration()) |
1238 v = v->addressOf(sc); | 1328 v = v->addressOf(sc); |
1239 #endif | 1329 #endif |
1330 #if IN_LLVM | |
1331 //e = new AssertExp(loc, v, NULL); | |
1332 | |
1333 // LDC: check for null this | |
1334 //v = new ThisExp(0); | |
1335 //v->type = vthis->type; | |
1336 //v->var = vthis; // Error: Expression has no property var... in D1 typeof(v) == ThisExp | |
1337 | |
1338 //NullExp *nv = new NullExp(0); | |
1339 //nv->type = v->type; | |
1340 | |
1341 //IdentityExp *ie = new IdentityExp(TOKnotidentity, 0, v, nv); | |
1342 //ie->type = Type::tbool; | |
1343 #endif | |
1240 Expression *se = new StringExp(0, (char *)"null this"); | 1344 Expression *se = new StringExp(0, (char *)"null this"); |
1241 se = se->semantic(sc); | 1345 se = se->semantic(sc); |
1242 se->type = Type::tchar->arrayOf(); | 1346 se->type = Type::tchar->arrayOf(); |
1347 //#if IN_LLVM | |
1348 // ee = new AssertExp(loc, ie, se); | |
1349 //#else | |
1243 e = new AssertExp(loc, v, se); | 1350 e = new AssertExp(loc, v, se); |
1351 //#endif | |
1244 } | 1352 } |
1353 if (ee) | |
1354 { | |
1355 ExpStatement *s = new ExpStatement(0, ee); | |
1356 a->push(s); | |
1357 } | |
1245 if (e) | 1358 if (e) |
1246 { | 1359 { |
1247 ExpStatement *s = new ExpStatement(0, e); | 1360 ExpStatement *s = new ExpStatement(0, e); |
1248 a->push(s); | 1361 a->push(s); |
1249 } | 1362 } |
1270 } | 1383 } |
1271 } | 1384 } |
1272 | 1385 |
1273 fbody = new CompoundStatement(0, a); | 1386 fbody = new CompoundStatement(0, a); |
1274 | 1387 |
1388 #if IN_LLVM | |
1389 // wrap body of synchronized functions in a synchronized statement | |
1390 if (isSynchronized()) | |
1391 { | |
1392 ClassDeclaration *cd = parent->isClassDeclaration(); | |
1393 if (!cd) | |
1394 error("synchronized function %s must be a member of a class", toChars()); | |
1395 | |
1396 Expression *sync; | |
1397 if (isStatic()) | |
1398 { | |
1399 // static member functions synchronize on classinfo | |
1400 sync = cd->type->dotExp(sc2, new TypeExp(loc, cd->type), Id::classinfo); | |
1401 } | |
1402 else | |
1403 { | |
1404 // non-static member functions synchronize on this | |
1405 sync = new VarExp(loc, vthis); | |
1406 } | |
1407 | |
1408 // we do not want to rerun semantics on the whole function, so we | |
1409 // manually adjust all labels in the function that currently don't | |
1410 // have an enclosingScopeExit to use the new SynchronizedStatement | |
1411 SynchronizedStatement* s = new SynchronizedStatement(loc, sync, NULL); | |
1412 s->semantic(sc2); | |
1413 s->body = fbody; | |
1414 | |
1415 // LDC | |
1416 LabelMap::iterator it, end = labmap.end(); | |
1417 for (it = labmap.begin(); it != end; ++it) | |
1418 if (it->second->enclosingScopeExit == NULL) | |
1419 it->second->enclosingScopeExit = s; | |
1420 | |
1421 a = new Statements; | |
1422 a->push(s); | |
1423 fbody = new CompoundStatement(0, a); | |
1424 } | |
1425 #endif | |
1426 | |
1275 /* Append destructor calls for parameters as finally blocks. | 1427 /* Append destructor calls for parameters as finally blocks. |
1276 */ | 1428 */ |
1277 if (parameters) | 1429 if (parameters) |
1278 { for (size_t i = 0; i < parameters->dim; i++) | 1430 { for (size_t i = 0; i < parameters->dim; i++) |
1279 { | 1431 { |
1303 } | 1455 } |
1304 | 1456 |
1305 sc2->callSuper = 0; | 1457 sc2->callSuper = 0; |
1306 sc2->pop(); | 1458 sc2->pop(); |
1307 } | 1459 } |
1308 semanticRun = 2; | 1460 semanticRun = 4; |
1309 } | 1461 } |
1310 | 1462 |
1311 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 1463 void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
1312 { | 1464 { |
1313 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars()); | 1465 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars()); |
1314 | 1466 |
1467 StorageClassDeclaration::stcToCBuffer(buf, storage_class); | |
1315 type->toCBuffer(buf, ident, hgs); | 1468 type->toCBuffer(buf, ident, hgs); |
1316 bodyToCBuffer(buf, hgs); | 1469 bodyToCBuffer(buf, hgs); |
1317 } | 1470 } |
1318 | 1471 |
1319 | 1472 |
1493 * Returns: | 1646 * Returns: |
1494 * 0 continue | 1647 * 0 continue |
1495 * 1 done | 1648 * 1 done |
1496 */ | 1649 */ |
1497 | 1650 |
1498 int overloadApply(FuncDeclaration *fstart, | 1651 int overloadApply(Module* from, FuncDeclaration *fstart, |
1499 int (*fp)(void *, FuncDeclaration *), | 1652 int (*fp)(void *, FuncDeclaration *), |
1500 void *param) | 1653 void *param) |
1501 { | 1654 { |
1502 FuncDeclaration *f; | 1655 FuncDeclaration *f; |
1503 Declaration *d; | 1656 Declaration *d; |
1506 for (d = fstart; d; d = next) | 1659 for (d = fstart; d; d = next) |
1507 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration(); | 1660 { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration(); |
1508 | 1661 |
1509 if (fa) | 1662 if (fa) |
1510 { | 1663 { |
1511 if (overloadApply(fa->funcalias, fp, param)) | 1664 if (fa->getModule() == from || fa->importprot != PROTprivate) |
1512 return 1; | 1665 if (overloadApply(from, fa->funcalias, fp, param)) |
1666 return 1; | |
1513 next = fa->overnext; | 1667 next = fa->overnext; |
1514 } | 1668 } |
1515 else | 1669 else |
1516 { | 1670 { |
1517 AliasDeclaration *a = d->isAliasDeclaration(); | 1671 AliasDeclaration *a = d->isAliasDeclaration(); |
1522 next = s->isDeclaration(); | 1676 next = s->isDeclaration(); |
1523 if (next == a) | 1677 if (next == a) |
1524 break; | 1678 break; |
1525 if (next == fstart) | 1679 if (next == fstart) |
1526 break; | 1680 break; |
1681 #if IN_LLVM | |
1682 if (a->importprot == PROTprivate && a->getModule() != from) | |
1683 if (FuncDeclaration* fd = next->isFuncDeclaration()) | |
1684 next = fd->overnext; | |
1685 #endif | |
1527 } | 1686 } |
1528 else | 1687 else |
1529 { | 1688 { |
1530 f = d->isFuncDeclaration(); | 1689 f = d->isFuncDeclaration(); |
1531 if (!f) | 1690 if (!f) |
1561 } | 1720 } |
1562 | 1721 |
1563 FuncDeclaration *FuncDeclaration::isUnique() | 1722 FuncDeclaration *FuncDeclaration::isUnique() |
1564 { FuncDeclaration *result = NULL; | 1723 { FuncDeclaration *result = NULL; |
1565 | 1724 |
1566 overloadApply(this, &fpunique, &result); | 1725 overloadApply(getModule(), this, &fpunique, &result); |
1567 return result; | 1726 return result; |
1568 } | 1727 } |
1569 | 1728 |
1570 /******************************************** | 1729 /******************************************** |
1571 * Find function in overload list that exactly matches t. | 1730 * Find function in overload list that exactly matches t. |
1601 } | 1760 } |
1602 #endif | 1761 #endif |
1603 return 0; | 1762 return 0; |
1604 } | 1763 } |
1605 | 1764 |
1606 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) | 1765 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t, Module* from) |
1607 { | 1766 { |
1608 Param1 p; | 1767 Param1 p; |
1609 p.t = t; | 1768 p.t = t; |
1610 p.f = NULL; | 1769 p.f = NULL; |
1611 overloadApply(this, &fp1, &p); | 1770 overloadApply(from, this, &fp1, &p); |
1612 return p.f; | 1771 return p.f; |
1613 } | 1772 } |
1614 | 1773 |
1615 | 1774 |
1616 /******************************************** | 1775 /******************************************** |
1683 } | 1842 } |
1684 return 0; | 1843 return 0; |
1685 } | 1844 } |
1686 | 1845 |
1687 void overloadResolveX(Match *m, FuncDeclaration *fstart, | 1846 void overloadResolveX(Match *m, FuncDeclaration *fstart, |
1688 Expression *ethis, Expressions *arguments) | 1847 Expression *ethis, Expressions *arguments, Module* from) |
1689 { | 1848 { |
1690 Param2 p; | 1849 Param2 p; |
1691 p.m = m; | 1850 p.m = m; |
1692 p.ethis = ethis; | 1851 p.ethis = ethis; |
1693 p.arguments = arguments; | 1852 p.arguments = arguments; |
1694 overloadApply(fstart, &fp2, &p); | 1853 overloadApply(from, fstart, &fp2, &p); |
1695 } | 1854 } |
1696 | 1855 |
1697 | 1856 |
1698 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags) | 1857 FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags, Module* from) |
1699 { | 1858 { |
1700 TypeFunction *tf; | 1859 TypeFunction *tf; |
1701 Match m; | 1860 Match m; |
1702 | 1861 |
1703 #if 0 | 1862 #if 0 |
1716 } | 1875 } |
1717 #endif | 1876 #endif |
1718 | 1877 |
1719 memset(&m, 0, sizeof(m)); | 1878 memset(&m, 0, sizeof(m)); |
1720 m.last = MATCHnomatch; | 1879 m.last = MATCHnomatch; |
1721 overloadResolveX(&m, this, ethis, arguments); | 1880 overloadResolveX(&m, this, ethis, arguments, from); |
1722 | 1881 |
1723 if (m.count == 1) // exactly one match | 1882 if (m.count == 1) // exactly one match |
1724 { | 1883 { |
1725 return m.lastf; | 1884 return m.lastf; |
1726 } | 1885 } |
1847 printf(" doesn't match, so is not as specialized\n"); | 2006 printf(" doesn't match, so is not as specialized\n"); |
1848 #endif | 2007 #endif |
1849 return MATCHnomatch; | 2008 return MATCHnomatch; |
1850 } | 2009 } |
1851 | 2010 |
2011 /******************************************* | |
2012 * Given a symbol that could be either a FuncDeclaration or | |
2013 * a function template, resolve it to a function symbol. | |
2014 * sc instantiation scope | |
2015 * loc instantiation location | |
2016 * targsi initial list of template arguments | |
2017 * ethis if !NULL, the 'this' pointer argument | |
2018 * fargs arguments to function | |
2019 * flags 1: do not issue error message on no match, just return NULL | |
2020 */ | |
2021 | |
2022 FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, | |
2023 Objects *tiargs, | |
2024 Expression *ethis, | |
2025 Expressions *arguments, | |
2026 int flags) | |
2027 { | |
2028 if (!s) | |
2029 return NULL; // no match | |
2030 FuncDeclaration *f = s->isFuncDeclaration(); | |
2031 if (f) | |
2032 f = f->overloadResolve(loc, ethis, arguments); | |
2033 else | |
2034 { TemplateDeclaration *td = s->isTemplateDeclaration(); | |
2035 assert(td); | |
2036 f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags); | |
2037 } | |
2038 return f; | |
2039 } | |
2040 | |
1852 /******************************** | 2041 /******************************** |
1853 * Labels are in a separate scope, one per function. | 2042 * Labels are in a separate scope, one per function. |
1854 */ | 2043 */ |
1855 | 2044 |
1856 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident) | 2045 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident) |
1938 { if (!thisfd->isNested() && !thisfd->vthis) | 2127 { if (!thisfd->isNested() && !thisfd->vthis) |
1939 goto Lerr; | 2128 goto Lerr; |
1940 } | 2129 } |
1941 else | 2130 else |
1942 { | 2131 { |
1943 ClassDeclaration *thiscd = s->isClassDeclaration(); | 2132 AggregateDeclaration *thiscd = s->isAggregateDeclaration(); |
1944 if (thiscd) | 2133 if (thiscd) |
1945 { if (!thiscd->isNested()) | 2134 { if (!thiscd->isNested()) |
1946 goto Lerr; | 2135 goto Lerr; |
1947 } | 2136 } |
1948 else | 2137 else |
2066 int FuncDeclaration::isOverloadable() | 2255 int FuncDeclaration::isOverloadable() |
2067 { | 2256 { |
2068 return 1; // functions can be overloaded | 2257 return 1; // functions can be overloaded |
2069 } | 2258 } |
2070 | 2259 |
2260 int FuncDeclaration::isPure() | |
2261 { | |
2262 //printf("FuncDeclaration::isPure() '%s'\n", toChars()); | |
2263 assert(type->ty == Tfunction); | |
2264 return ((TypeFunction *)this->type)->ispure; | |
2265 } | |
2266 | |
2071 // Determine if function needs | 2267 // Determine if function needs |
2072 // a static frame pointer to its lexically enclosing function | 2268 // a static frame pointer to its lexically enclosing function |
2073 | 2269 |
2074 int FuncDeclaration::isNested() | 2270 int FuncDeclaration::isNested() |
2075 { | 2271 { |
2076 //if (!toParent()) | 2272 //if (!toParent()) |
2077 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); | 2273 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); |
2078 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars()); | 2274 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars()); |
2079 return ((storage_class & STCstatic) == 0) && | 2275 return ((storage_class & STCstatic) == 0) && toParent2() && |
2080 (toParent2()->isFuncDeclaration() != NULL); | 2276 (toParent2()->isFuncDeclaration() != NULL); |
2081 } | 2277 } |
2082 | 2278 |
2083 int FuncDeclaration::needThis() | 2279 int FuncDeclaration::needThis() |
2084 { | 2280 { |
2194 | 2390 |
2195 for (int j = 0; j < v->nestedrefs.dim; j++) | 2391 for (int j = 0; j < v->nestedrefs.dim; j++) |
2196 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j]; | 2392 { FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j]; |
2197 assert(f != this); | 2393 assert(f != this); |
2198 | 2394 |
2199 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf); | 2395 //printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf); |
2200 if (f->isThis() || f->tookAddressOf) | 2396 if (f->isThis() || f->tookAddressOf) |
2201 goto Lyes; // assume f escapes this function's scope | 2397 goto Lyes; // assume f escapes this function's scope |
2202 | 2398 |
2203 // Look to see if any parents of f that are below this escape | 2399 // Look to see if any parents of f that are below this escape |
2204 for (Dsymbol *s = f->parent; s && s != this; s = s->parent) | 2400 for (Dsymbol *s = f->parent; s && s != this; s = s->parent) |
2225 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident, | 2421 : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident, |
2226 (enum STC)funcalias->storage_class, funcalias->type) | 2422 (enum STC)funcalias->storage_class, funcalias->type) |
2227 { | 2423 { |
2228 assert(funcalias != this); | 2424 assert(funcalias != this); |
2229 this->funcalias = funcalias; | 2425 this->funcalias = funcalias; |
2426 #if IN_LLVM | |
2427 importprot = PROTundefined; | |
2428 #endif | |
2230 } | 2429 } |
2231 | 2430 |
2232 const char *FuncAliasDeclaration::kind() | 2431 const char *FuncAliasDeclaration::kind() |
2233 { | 2432 { |
2234 return "function alias"; | 2433 return "function alias"; |
2247 id = "__foreachbody"; | 2446 id = "__foreachbody"; |
2248 else if (tok == TOKdelegate) | 2447 else if (tok == TOKdelegate) |
2249 id = "__dgliteral"; | 2448 id = "__dgliteral"; |
2250 else | 2449 else |
2251 id = "__funcliteral"; | 2450 id = "__funcliteral"; |
2252 this->ident = Identifier::generateId(id); | 2451 this->ident = Lexer::uniqueId(id); |
2253 this->tok = tok; | 2452 this->tok = tok; |
2254 this->fes = fes; | 2453 this->fes = fes; |
2255 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars()); | 2454 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars()); |
2256 } | 2455 } |
2257 | 2456 |
2261 | 2460 |
2262 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars()); | 2461 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars()); |
2263 if (s) | 2462 if (s) |
2264 f = (FuncLiteralDeclaration *)s; | 2463 f = (FuncLiteralDeclaration *)s; |
2265 else | 2464 else |
2266 f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); | 2465 { f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); |
2466 f->ident = ident; // keep old identifier | |
2467 } | |
2267 FuncDeclaration::syntaxCopy(f); | 2468 FuncDeclaration::syntaxCopy(f); |
2268 return f; | 2469 return f; |
2269 } | 2470 } |
2270 | 2471 |
2271 int FuncLiteralDeclaration::isNested() | 2472 int FuncLiteralDeclaration::isNested() |
2330 void CtorDeclaration::semantic(Scope *sc) | 2531 void CtorDeclaration::semantic(Scope *sc) |
2331 { | 2532 { |
2332 AggregateDeclaration *ad; | 2533 AggregateDeclaration *ad; |
2333 Type *tret; | 2534 Type *tret; |
2334 | 2535 |
2335 //printf("CtorDeclaration::semantic()\n"); | 2536 //printf("CtorDeclaration::semantic() %s\n", toChars()); |
2336 if (type) | 2537 if (type) |
2337 return; | 2538 return; |
2338 | 2539 |
2339 sc = sc->push(); | 2540 sc = sc->push(); |
2340 sc->stc &= ~STCstatic; // not a static constructor | 2541 sc->stc &= ~STCstatic; // not a static constructor |
2341 | 2542 |
2342 parent = sc->parent; | 2543 parent = sc->parent; |
2343 Dsymbol *parent = toParent(); | 2544 Dsymbol *parent = toParent2(); |
2344 ad = parent->isAggregateDeclaration(); | 2545 ad = parent->isAggregateDeclaration(); |
2345 if (!ad || parent->isUnionDeclaration()) | 2546 if (!ad || parent->isUnionDeclaration()) |
2346 { | 2547 { |
2347 error("constructors are only for class or struct definitions"); | 2548 error("constructors are only for class or struct definitions"); |
2348 fatal(); | 2549 fatal(); |
2349 tret = Type::tvoid; | 2550 tret = Type::tvoid; |
2350 } | 2551 } |
2351 else | 2552 else |
2352 { tret = ad->handle; | 2553 { tret = ad->handle; |
2353 assert(tret); | 2554 assert(tret); |
2367 // Append: | 2568 // Append: |
2368 // return this; | 2569 // return this; |
2369 // to the function body | 2570 // to the function body |
2370 if (fbody) | 2571 if (fbody) |
2371 { | 2572 { |
2372 Expression *e = new ThisExp(0); | 2573 Expression *e = new ThisExp(loc); |
2373 Statement *s = new ReturnStatement(0, e); | 2574 Statement *s = new ReturnStatement(loc, e); |
2374 fbody = new CompoundStatement(0, fbody, s); | 2575 fbody = new CompoundStatement(loc, fbody, s); |
2375 } | 2576 } |
2376 | 2577 |
2377 FuncDeclaration::semantic(sc); | 2578 FuncDeclaration::semantic(sc); |
2378 | 2579 |
2379 sc->pop(); | 2580 sc->pop(); |
2407 return FALSE; | 2608 return FALSE; |
2408 } | 2609 } |
2409 | 2610 |
2410 int CtorDeclaration::addPostInvariant() | 2611 int CtorDeclaration::addPostInvariant() |
2411 { | 2612 { |
2412 return (vthis && global.params.useInvariants); | 2613 return (isThis() && vthis && global.params.useInvariants); |
2413 } | 2614 } |
2414 | 2615 |
2415 | 2616 |
2416 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2617 void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2417 { | 2618 { |
2474 return FALSE; | 2675 return FALSE; |
2475 } | 2676 } |
2476 | 2677 |
2477 int PostBlitDeclaration::addPostInvariant() | 2678 int PostBlitDeclaration::addPostInvariant() |
2478 { | 2679 { |
2479 return (vthis && global.params.useInvariants); | 2680 return (isThis() && vthis && global.params.useInvariants); |
2480 } | 2681 } |
2481 | 2682 |
2482 int PostBlitDeclaration::isVirtual() | 2683 int PostBlitDeclaration::isVirtual() |
2483 { | 2684 { |
2484 return FALSE; | 2685 return FALSE; |
2520 Dsymbol *parent = toParent(); | 2721 Dsymbol *parent = toParent(); |
2521 AggregateDeclaration *ad = parent->isAggregateDeclaration(); | 2722 AggregateDeclaration *ad = parent->isAggregateDeclaration(); |
2522 if (!ad) | 2723 if (!ad) |
2523 { | 2724 { |
2524 error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars()); | 2725 error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars()); |
2525 fatal(); | 2726 fatal(); |
2526 } | 2727 } |
2527 else if (ident == Id::dtor) | 2728 else if (ident == Id::dtor) |
2528 ad->dtors.push(this); | 2729 ad->dtors.push(this); |
2529 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); | 2730 type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); |
2530 | 2731 |
2542 return FALSE; // cannot overload destructors | 2743 return FALSE; // cannot overload destructors |
2543 } | 2744 } |
2544 | 2745 |
2545 int DtorDeclaration::addPreInvariant() | 2746 int DtorDeclaration::addPreInvariant() |
2546 { | 2747 { |
2547 return (vthis && global.params.useInvariants); | 2748 return (isThis() && vthis && global.params.useInvariants); |
2548 } | 2749 } |
2549 | 2750 |
2550 int DtorDeclaration::addPostInvariant() | 2751 int DtorDeclaration::addPostInvariant() |
2551 { | 2752 { |
2552 return FALSE; | 2753 return FALSE; |
2754 } | |
2755 | |
2756 const char *DtorDeclaration::kind() | |
2757 { | |
2758 return "destructor"; | |
2759 } | |
2760 | |
2761 char *DtorDeclaration::toChars() | |
2762 { | |
2763 return (char *)"~this"; | |
2553 } | 2764 } |
2554 | 2765 |
2555 int DtorDeclaration::isVirtual() | 2766 int DtorDeclaration::isVirtual() |
2556 { | 2767 { |
2557 /* This should be FALSE so that dtor's don't get put into the vtbl[], | 2768 /* This should be FALSE so that dtor's don't get put into the vtbl[], |
2806 parent = sc->parent; | 3017 parent = sc->parent; |
2807 Dsymbol *parent = toParent(); | 3018 Dsymbol *parent = toParent(); |
2808 ad = parent->isAggregateDeclaration(); | 3019 ad = parent->isAggregateDeclaration(); |
2809 if (!ad) | 3020 if (!ad) |
2810 { | 3021 { |
2811 error("invariants only are for struct/union/class definitions"); | 3022 error("invariants are only for struct/union/class definitions"); |
2812 return; | 3023 return; |
2813 } | 3024 } |
2814 else if (ad->inv && ad->inv != this) | 3025 else if (ad->inv && ad->inv != this) |
2815 { | 3026 { |
2816 error("more than one invariant for %s", ad->toChars()); | 3027 error("more than one invariant for %s", ad->toChars()); |
2969 type = new TypeFunction(arguments, tret, varargs, LINKd); | 3180 type = new TypeFunction(arguments, tret, varargs, LINKd); |
2970 | 3181 |
2971 type = type->semantic(loc, sc); | 3182 type = type->semantic(loc, sc); |
2972 assert(type->ty == Tfunction); | 3183 assert(type->ty == Tfunction); |
2973 | 3184 |
2974 // Check that there is at least one argument of type uint | 3185 // Check that there is at least one argument of type size_t |
2975 TypeFunction *tf = (TypeFunction *)type; | 3186 TypeFunction *tf = (TypeFunction *)type; |
2976 if (Argument::dim(tf->parameters) < 1) | 3187 if (Argument::dim(tf->parameters) < 1) |
2977 { | 3188 { |
2978 error("at least one argument of type size_t expected"); | 3189 error("at least one argument of type size_t expected"); |
2979 } | 3190 } |