2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
22 #include "declaration.h"
24 #include "expression.h"
27 #include "aggregate.h"
28 #include "identifier.h"
31 #include "statement.h"
36 #include "d-dmd-gcc.h"
39 /********************************* FuncDeclaration ****************************/
41 FuncDeclaration::FuncDeclaration(Loc loc
, Loc endloc
, Identifier
*id
, enum STC storage_class
, Type
*type
)
44 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
45 this->storage_class
= storage_class
;
48 this->endloc
= endloc
;
61 v_arguments_var
= NULL
;
69 inlineStatus
= ILSuninitialized
;
78 inferRetType
= (type
&& type
->nextOf() == NULL
);
86 Dsymbol
*FuncDeclaration::syntaxCopy(Dsymbol
*s
)
90 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
92 f
= (FuncDeclaration
*)s
;
94 f
= new FuncDeclaration(loc
, endloc
, ident
, (enum STC
) storage_class
, type
->syntaxCopy());
96 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
97 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
98 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
99 assert(!fthrows
); // deprecated
104 // Do the semantic analysis on the external interface to the function.
106 void FuncDeclaration::semantic(Scope
*sc
)
108 StructDeclaration
*sd
;
109 ClassDeclaration
*cd
;
110 InterfaceDeclaration
*id
;
113 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc
, this, toPrettyChars(), sc
->linkage
);
114 if (isFuncLiteralDeclaration())
115 printf("\tFuncLiteralDeclaration()\n");
116 printf("sc->parent = %s\n", sc
->parent
->toChars());
117 printf("type: %s\n", type
->toChars());
121 type
= type
->semantic(loc
, sc
);
123 if (type
->ty
!= Tfunction
)
125 error("%s must be a function", toChars());
128 f
= (TypeFunction
*)(type
);
129 size_t nparams
= Argument::dim(f
->parameters
);
131 linkage
= sc
->linkage
;
134 //parent = sc->scopesym;
137 protection
= sc
->protection
;
138 storage_class
|= sc
->stc
;
140 attributes
->append(sc
->attributes
);
142 attributes
= sc
->attributes
;
143 //printf("function storage_class = x%x\n", storage_class);
144 Dsymbol
*parent
= toParent();
146 if (isConst() || isAuto() || isScope())
147 error("functions cannot be const or auto");
149 if (isAbstract() && !isVirtual())
150 error("non-virtual functions cannot be abstract");
152 if (isAbstract() && isFinal())
153 error("cannot be both final and abstract");
155 if (isAbstract() && fbody
)
156 error("abstract functions cannot have bodies");
160 if (isStaticConstructor() || isStaticDestructor())
162 if (!isStatic() || type
->nextOf()->ty
!= Tvoid
)
163 error("static constructors / destructors must be static void");
164 if (f
->arguments
&& f
->arguments
->dim
)
165 error("static constructors / destructors must have empty parameter list");
166 // BUG: check for invalid storage classes
171 AggregateDeclaration
*ad
;
173 ad
= parent
->isAggregateDeclaration();
175 ad
->methods
.push(this);
177 sd
= parent
->isStructDeclaration();
180 // Verify no constructors, destructors, etc.
181 if (isCtorDeclaration() ||
183 //|| isInvariantDeclaration()
184 //|| isUnitTestDeclaration()
187 error("special member functions not allowed for %ss", sd
->kind());
192 sd
->inv
= isInvariantDeclaration();
195 sd
->aggNew
= isNewDeclaration();
200 error("multiple delete's for struct %s", sd
->toChars());
201 sd
->aggDelete
= (DeleteDeclaration
*)(this);
206 id
= parent
->isInterfaceDeclaration();
209 storage_class
|= STCabstract
;
211 if (isCtorDeclaration() ||
212 isDtorDeclaration() ||
213 isInvariantDeclaration() ||
214 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
215 error("special function not allowed in interface %s", id
->toChars());
217 error("function body is not abstract in interface %s", id
->toChars());
220 cd
= parent
->isClassDeclaration();
223 CtorDeclaration
*ctor
;
224 DtorDeclaration
*dtor
;
225 InvariantDeclaration
*inv
;
227 if (isCtorDeclaration())
229 // ctor = (CtorDeclaration *)this;
236 dtor
= isDtorDeclaration();
240 error("multiple destructors for class %s", cd
->toChars());
244 inv
= isInvariantDeclaration();
250 if (isNewDeclaration())
253 cd
->aggNew
= (NewDeclaration
*)(this);
259 error("multiple delete's for class %s", cd
->toChars());
260 cd
->aggDelete
= (DeleteDeclaration
*)(this);
264 if (storage_class
& STCabstract
)
267 // if static function, do not put in vtbl[]
270 //printf("\tnot virtual\n");
274 // Find index of existing function in vtbl[] to override
275 vi
= findVtblIndex(&cd
->vtbl
, cd
->baseClass
? cd
->baseClass
->vtbl
.dim
: 0);
278 case -1: // didn't find one
279 // This is an 'introducing' function.
281 // Verify this doesn't override previous final function
283 { Dsymbol
*s
= cd
->baseClass
->search(loc
, ident
, 0);
286 FuncDeclaration
*f
= s
->isFuncDeclaration();
287 f
= f
->overloadExactMatch(type
);
288 if (f
&& f
->isFinal() && f
->prot() != PROTprivate
)
289 error("cannot override final function %s", f
->toPrettyChars());
295 cd
->vtblFinal
.push(this);
299 // Append to end of vtbl[]
300 //printf("\tintroducing function\n");
308 case -2: // can't determine because of fwd refs
309 cd
->sizeok
= 2; // can't finish due to forward reference
313 { FuncDeclaration
*fdv
= (FuncDeclaration
*)cd
->vtbl
.data
[vi
];
314 // This function is covariant with fdv
316 error("cannot override final function %s", fdv
->toPrettyChars());
319 if (!isOverride() && global
.params
.warnings
)
320 error("overrides base class function %s, but is not marked with 'override'", fdv
->toPrettyChars());
322 if (!isOverride() && sc
->module
->isDltFile
)
323 error("overrides base class function %s, but is not marked with 'override'", fdv
->toPrettyChars());
326 if (fdv
->toParent() == parent
)
328 // If both are mixins, then error.
329 // If either is not, the one that is not overrides
331 if (fdv
->parent
->isClassDeclaration())
333 if (!this->parent
->isClassDeclaration()
335 && !isDtorDeclaration()
338 && !isPostBlitDeclaration()
341 error("multiple overrides of same function");
343 cd
->vtbl
.data
[vi
] = (void *)this;
346 /* This works by whenever this function is called,
347 * it actually returns tintro, which gets dynamically
348 * cast to type. But we know that tintro is a base
349 * of type, so we could optimize it by not doing a
350 * dynamic cast, but just subtracting the isBaseOf()
351 * offset if the value is != null.
355 tintro
= fdv
->tintro
;
356 else if (!type
->equals(fdv
->type
))
358 /* Only need to have a tintro if the vptr
361 target_ptrdiff_t offset
;
362 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
371 /* Go through all the interface bases.
372 * If this function is covariant with any members of those interface
373 * functions, set the tintro.
375 for (int i
= 0; i
< cd
->interfaces_dim
; i
++)
378 BaseClass
*b
= cd
->interfaces
[i
];
379 vi
= findVtblIndex(&b
->base
->vtbl
, b
->base
->vtbl
.dim
);
386 cd
->sizeok
= 2; // can't finish due to forward reference
390 { FuncDeclaration
*fdv
= (FuncDeclaration
*)b
->base
->vtbl
.data
[vi
];
395 else if (!type
->equals(fdv
->type
))
397 /* Only need to have a tintro if the vptr
400 target_ptrdiff_t offset
;
401 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
407 else if (type
->nextOf()->ty
== Tclass
)
408 { ClassDeclaration
*cdn
= ((TypeClass
*)type
->nextOf())->sym
;
409 if (cdn
&& cdn
->sizeok
!= 1)
417 if (tintro
&& !tintro
->equals(ti
))
419 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
427 BaseClass
*b
= cd
->interfaces
[i
];
428 for (vi
= 0; vi
< b
->base
->vtbl
.dim
; vi
++)
430 Dsymbol
*s
= (Dsymbol
*)b
->base
->vtbl
.data
[vi
];
431 //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
432 FuncDeclaration
*fdv
= s
->isFuncDeclaration();
433 if (fdv
&& fdv
->ident
== ident
)
435 int cov
= type
->covariant(fdv
->type
);
436 //printf("\tcov = %d\n", cov);
440 //fdv->type->print();
441 //printf("%s %s\n", type->deco, fdv->type->deco);
442 error("of type %s overrides but is not covariant with %s of type %s",
443 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
450 else if (!type
->equals(fdv
->type
))
452 /* Only need to have a tintro if the vptr
455 target_ptrdiff_t offset
;
456 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
462 else if (type
->nextOf()->ty
== Tclass
)
463 { ClassDeclaration
*cdn
= ((TypeClass
*)type
->nextOf())->sym
;
464 if (cdn
&& cdn
->sizeok
!= 1)
472 if (tintro
&& !tintro
->equals(ti
))
474 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
482 cd
->sizeok
= 2; // can't finish due to forward reference
490 if (introducing
&& isOverride())
492 error("does not override any function");
497 else if (isOverride() && !parent
->isTemplateInstance())
498 error("override only applies to class member functions");
500 /* Do not allow template instances to add virtual functions
505 TemplateInstance
*ti
= parent
->isTemplateInstance();
508 // Take care of nested templates
511 TemplateInstance
*ti2
= ti
->tempdecl
->parent
->isTemplateInstance();
517 // If it's a member template
518 ClassDeclaration
*cd
= ti
->tempdecl
->isClassMember();
521 error("cannot use template to add virtual function to class '%s'", cd
->toChars());
528 // Check parameters to see if they are either () or (char[][] args)
536 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
537 if (arg0
->type
->ty
!= Tarray
||
538 arg0
->type
->nextOf()->ty
!= Tarray
||
539 arg0
->type
->nextOf()->nextOf()->ty
!= Tchar
||
540 arg0
->storageClass
& (STCout
| STCref
| STClazy
))
549 if (f
->nextOf()->ty
!= Tint32
&& f
->nextOf()->ty
!= Tvoid
)
550 error("must return int or void, not %s", f
->nextOf()->toChars());
554 error("parameters must be main() or main(char[][] args)");
558 if (ident
== Id::assign
&& (sd
|| cd
))
559 { // Disallow identity assignment operator.
563 { if (f
->varargs
== 1)
568 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
569 Type
*t0
= arg0
->type
->toBasetype();
570 Type
*tb
= sd
? sd
->type
: cd
->type
;
571 if (arg0
->type
->implicitConvTo(tb
) ||
572 (sd
&& t0
->ty
== Tpointer
&& t0
->nextOf()->implicitConvTo(tb
))
577 Argument
*arg1
= Argument::getNth(f
->parameters
, 1);
578 if (arg1
->defaultArg
)
585 /* Save scope for possible later use (if we need the
586 * function internals)
588 scope
= new Scope(*sc
);
593 error("identity assignment operator overload is illegal");
596 void FuncDeclaration::semantic2(Scope
*sc
)
600 // Do the semantic analysis on the internals of the function.
602 void FuncDeclaration::semantic3(Scope
*sc
)
604 AggregateDeclaration
*ad
;
605 VarDeclaration
*argptr
= NULL
;
606 VarDeclaration
*_arguments
= NULL
;
612 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
615 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
617 //{ static int x; if (++x == 2) *(char*)0=0; }
618 //printf("\tlinkage = %d\n", sc->linkage);
620 //printf(" sc->incontract = %d\n", sc->incontract);
625 if (!type
|| type
->ty
!= Tfunction
)
627 f
= (TypeFunction
*)(type
);
628 size_t nparams
= Argument::dim(f
->parameters
);
630 // Check the 'throws' clause
634 for (i
= 0; i
< fthrows
->dim
; i
++)
636 Type
*t
= (Type
*)fthrows
->data
[i
];
638 t
= t
->semantic(loc
, sc
);
639 if (!t
->isClassHandle())
640 error("can only throw classes, not %s", t
->toChars());
644 if (fbody
|| frequire
)
646 /* Symbol table into which we place parameters and nested functions,
647 * solely to diagnose name collisions.
649 localsymtab
= new DsymbolTable();
651 // Establish function scope
652 ScopeDsymbol
*ss
= new ScopeDsymbol();
653 ss
->parent
= sc
->scopesym
;
654 Scope
*sc2
= sc
->push(ss
);
659 sc2
->scontinue
= NULL
;
662 sc2
->linkage
= LINKd
;
663 sc2
->stc
&= ~(STCauto
| STCscope
| STCstatic
| STCabstract
| STCdeprecated
| STCfinal
);
664 sc2
->attributes
= NULL
;
665 sc2
->protection
= PROTpublic
;
666 sc2
->explicitProtection
= 0;
667 sc2
->structalign
= 8;
677 if (isFuncLiteralDeclaration() && isNested())
679 error("literals cannot be class members");
684 assert(!isNested()); // can't be both member and nested
686 v
= new ThisDeclaration(ad
->handle
);
687 v
->storage_class
|= STCparameter
| STCin
;
699 v
= new ThisDeclaration(Type::tvoid
->pointerTo());
700 v
->storage_class
|= STCparameter
| STCin
;
708 // Declare hidden variable _arguments[] and _argptr
712 if (f
->linkage
== LINKd
)
713 { // Declare _arguments[]
715 v_arguments
= new VarDeclaration(0, Type::typeinfotypelist
->type
, Id::_arguments_typeinfo
, NULL
);
716 v_arguments
->storage_class
= STCparameter
| STCin
;
717 v_arguments
->semantic(sc2
);
718 sc2
->insert(v_arguments
);
719 v_arguments
->parent
= this;
721 t
= Type::typeinfo
->type
->arrayOf();
722 _arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
723 _arguments
->skipnullcheck
= TRUE
;
724 _arguments
->semantic(sc2
);
725 sc2
->insert(_arguments
);
726 _arguments
->parent
= this;
728 t
= Type::typeinfo
->type
->arrayOf();
729 v_arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
730 v_arguments
->storage_class
= STCparameter
| STCin
;
731 v_arguments
->semantic(sc2
);
732 sc2
->insert(v_arguments
);
733 v_arguments
->parent
= this;
736 if (f
->linkage
== LINKd
|| (parameters
&& parameters
->dim
))
739 t
= d_gcc_builtin_va_list_d_type
;
741 t
= Type::tvoid
->pointerTo();
743 argptr
= new VarDeclaration(0, t
, Id::_argptr
, NULL
);
744 argptr
->skipnullcheck
= TRUE
;
745 argptr
->semantic(sc2
);
747 argptr
->parent
= this;
751 // Propagate storage class from tuple parameters to their element-parameters.
754 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
755 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
757 if (arg
->type
->ty
== Ttuple
)
758 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
759 size_t dim
= Argument::dim(t
->arguments
);
760 for (size_t j
= 0; j
< dim
; j
++)
761 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
762 narg
->storageClass
= arg
->storageClass
;
768 // Declare all the function parameters as variables
770 { /* parameters[] has all the tuples removed, as the back end
771 * doesn't know about tuples
773 parameters
= new Dsymbols();
774 parameters
->reserve(nparams
);
775 for (size_t i
= 0; i
< nparams
; i
++)
777 Argument
*arg
= Argument::getNth(f
->parameters
, i
);
778 Identifier
*id
= arg
->ident
;
781 /* Generate identifier for un-named parameter,
782 * because we need it later on.
785 buf
.printf("_param_%"PRIuSIZE
, i
);
786 char *name
= (char *)buf
.extractData();
787 id
= new Identifier(name
, TOKidentifier
);
790 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, id
, NULL
);
791 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
792 v
->storage_class
|= STCparameter
;
793 if (f
->varargs
== 2 && i
+ 1 == nparams
)
794 v
->storage_class
|= STCvariadic
;
795 v
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STClazy
);
796 if (v
->storage_class
& STClazy
)
797 v
->storage_class
|= STCin
;
800 error("parameter %s.%s is already defined", toChars(), v
->toChars());
803 localsymtab
->insert(v
);
808 // Declare the tuple symbols and put them in the symbol table,
809 // but not in parameters[].
812 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
813 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
816 continue; // never used, so ignore
817 if (arg
->type
->ty
== Ttuple
)
818 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
819 size_t dim
= Argument::dim(t
->arguments
);
820 Objects
*exps
= new Objects();
822 for (size_t j
= 0; j
< dim
; j
++)
823 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
825 VarDeclaration
*v
= sc2
->search(0, narg
->ident
, NULL
)->isVarDeclaration();
827 Expression
*e
= new VarExp(0, v
);
828 exps
->data
[j
] = (void *)e
;
831 TupleDeclaration
*v
= new TupleDeclaration(0, arg
->ident
, exps
);
832 //printf("declaring tuple %s\n", v->toChars());
835 error("parameter %s.%s is already defined", toChars(), v
->toChars());
836 localsymtab
->insert(v
);
842 /* Do the semantic analysis on the [in] preconditions and
843 * [out] postconditions.
848 { /* frequire is composed of the [in] contracts
850 // BUG: need to error if accessing out parameters
851 // BUG: need to treat parameters as const
852 // BUG: need to disallow returns and throws
853 // BUG: verify that all in and ref parameters are read
854 frequire
= frequire
->semantic(sc2
);
855 labtab
= NULL
; // so body can't refer to labels
858 if (fensure
|| addPostInvariant())
859 { /* fensure is composed of the [out] contracts
861 ScopeDsymbol
*sym
= new ScopeDsymbol();
862 sym
->parent
= sc2
->scopesym
;
863 sc2
= sc2
->push(sym
);
865 assert(type
->nextOf());
866 if (type
->nextOf()->ty
== Tvoid
)
869 error("void functions have no result");
874 outId
= Id::result
; // provide a default
878 { // Declare result variable
885 v
= new VarDeclaration(loc
, type
->nextOf(), outId
, NULL
);
887 v
->skipnullcheck
= 1;
892 error("out result %s is already defined", v
->toChars());
896 // vresult gets initialized with the function return value
897 // in ReturnStatement::semantic()
900 // BUG: need to treat parameters as const
901 // BUG: need to disallow returns and throws
903 { fensure
= fensure
->semantic(sc2
);
904 labtab
= NULL
; // so body can't refer to labels
907 if (!global
.params
.useOut
)
908 { fensure
= NULL
; // discard
912 // Postcondition invariant
913 if (addPostInvariant())
915 Expression
*e
= NULL
;
916 if (isCtorDeclaration())
918 // Call invariant directly only if it exists
919 InvariantDeclaration
*inv
= ad
->inv
;
920 ClassDeclaration
*cd
= ad
->isClassDeclaration();
931 e
= new DsymbolExp(0, inv
);
932 e
= new CallExp(0, e
);
933 e
= e
->semantic(sc2
);
937 { // Call invariant virtually
938 ThisExp
*v
= new ThisExp(0);
939 v
->type
= vthis
->type
;
940 e
= new AssertExp(0, v
);
944 ExpStatement
*s
= new ExpStatement(0, e
);
946 fensure
= new CompoundStatement(0, s
, fensure
);
953 { returnLabel
= new LabelDsymbol(Id::returnLabel
);
954 LabelStatement
*ls
= new LabelStatement(0, Id::returnLabel
, fensure
);
955 ls
->isReturnLabel
= 1;
956 returnLabel
->statement
= ls
;
964 { ClassDeclaration
*cd
= isClassMember();
966 /* If this is a class constructor
968 if (isCtorDeclaration() && cd
)
970 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
971 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
977 if (inferRetType
|| f
->retStyle() != RETstack
)
980 fbody
= fbody
->semantic(sc2
);
983 { // If no return type inferred yet, then infer a void
986 ((TypeFunction
*)type
)->next
= Type::tvoid
;
987 type
= type
->semantic(loc
, sc
);
989 f
= (TypeFunction
*)type
;
992 int offend
= fbody
? fbody
->fallOffEnd() : TRUE
;
994 if (isStaticCtorDeclaration())
995 { /* It's a static constructor. Ensure that all
996 * ctor consts were initialized.
999 Dsymbol
*p
= toParent();
1000 ScopeDsymbol
*ad
= p
->isScopeDsymbol();
1003 error("static constructor can only be member of struct/class/module, not %s %s", p
->kind(), p
->toChars());
1007 for (int i
= 0; i
< ad
->members
->dim
; i
++)
1008 { Dsymbol
*s
= (Dsymbol
*)ad
->members
->data
[i
];
1010 s
->checkCtorConstInit();
1015 if (isCtorDeclaration() && cd
)
1017 //printf("callSuper = x%x\n", sc2->callSuper);
1019 // Verify that all the ctorinit fields got initialized
1020 // Also check that non-null members got set
1021 if (!(sc2
->callSuper
& CSXthis_ctor
))
1023 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
1024 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
1026 if (v
->ctorinit
== 0)
1028 if (v
->isCtorinit())
1029 error("missing initializer for const field %s", v
->toChars());
1030 else if (v
->type
->ty
== Tclass
|| v
->type
->ty
== Tpointer
)
1031 error("missing initializer for non-null field %s", v
->toChars());
1036 if (!(sc2
->callSuper
& CSXany_ctor
) &&
1037 cd
->baseClass
&& cd
->baseClass
->ctor
)
1041 // Insert implicit super() at start of fbody
1042 Expression
*e1
= new SuperExp(0);
1043 Expression
*e
= new CallExp(0, e1
);
1045 unsigned errors
= global
.errors
;
1047 e
= e
->semantic(sc2
);
1049 if (errors
!= global
.errors
)
1050 error("no match for implicit super() call in constructor");
1052 Statement
*s
= new ExpStatement(0, e
);
1053 fbody
= new CompoundStatement(0, s
, fbody
);
1057 { // For foreach(){} body, append a return 0;
1058 Expression
*e
= new IntegerExp(0);
1059 Statement
*s
= new ReturnStatement(0, e
);
1060 fbody
= new CompoundStatement(0, fbody
, s
);
1061 assert(!returnLabel
);
1063 else if (!hasReturnExp
&& type
->nextOf()->ty
!= Tvoid
)
1064 error("expected to return a value of type %s", type
->nextOf()->toChars());
1065 else if (!inlineAsm
)
1067 if (type
->nextOf()->ty
== Tvoid
)
1069 if (offend
&& isMain())
1070 { // Add a return 0; statement
1071 Statement
*s
= new ReturnStatement(0, new IntegerExp(0));
1072 fbody
= new CompoundStatement(0, fbody
, s
);
1080 if (global
.params
.warnings
)
1081 { fprintf(stdmsg
, "warning - ");
1082 error("no return at end of function");
1085 if (global
.params
.useAssert
&&
1086 !global
.params
.useInline
)
1087 { /* Add an assert(0, msg); where the missing return
1093 new StringExp(loc
, "missing return expression")
1097 e
= new HaltExp(endloc
);
1098 e
= new CommaExp(0, e
, type
->nextOf()->defaultInit());
1099 e
= e
->semantic(sc2
);
1100 Statement
*s
= new ExpStatement(0, e
);
1101 fbody
= new CompoundStatement(0, fbody
, s
);
1108 Statements
*a
= new Statements();
1110 // Merge in initialization of 'out' parameters
1112 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1114 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1115 if (v
->storage_class
& STCout
)
1118 ExpInitializer
*ie
= v
->init
->isExpInitializer();
1120 a
->push(new ExpStatement(0, ie
->exp
));
1126 { // Initialize _argptr to point past non-variadic arg
1128 // Handled in FuncDeclaration::toObjFile
1130 v_argptr
->init
= new VoidInitializer(loc
);
1134 Type
*t
= argptr
->type
;
1138 e1
= new VarExp(0, argptr
);
1139 if (parameters
&& parameters
->dim
)
1140 p
= (VarDeclaration
*)parameters
->data
[parameters
->dim
- 1];
1142 p
= v_arguments
; // last parameter is _arguments[]
1143 offset
= p
->type
->size();
1144 offset
= (offset
+ 3) & ~3; // assume stack aligns on 4
1145 e
= new SymOffExp(0, p
, offset
);
1146 e
= new AssignExp(0, e1
, e
);
1148 a
->push(new ExpStatement(0, e
));
1155 v_arguments_var
= _arguments
;
1156 v_arguments_var
->init
= new VoidInitializer(loc
);
1158 /* Advance to elements[] member of TypeInfo_Tuple with:
1159 * _arguments = v_arguments.elements;
1161 Expression
*e
= new VarExp(0, v_arguments
);
1162 e
= new DotIdExp(0, e
, Id::elements
);
1163 Expression
*e1
= new VarExp(0, _arguments
);
1164 e
= new AssignExp(0, e1
, e
);
1165 e
= e
->semantic(sc
);
1166 a
->push(new ExpStatement(0, e
));
1169 // Merge contracts together with body into one compound statement
1172 if (frequire
&& global
.params
.useIn
)
1173 { frequire
->incontract
= 1;
1177 if (frequire
&& global
.params
.useIn
)
1181 // Precondition invariant
1182 if (addPreInvariant())
1184 Expression
*e
= NULL
;
1185 if (isDtorDeclaration())
1187 // Call invariant directly only if it exists
1188 InvariantDeclaration
*inv
= ad
->inv
;
1189 ClassDeclaration
*cd
= ad
->isClassDeclaration();
1200 e
= new DsymbolExp(0, inv
);
1201 e
= new CallExp(0, e
);
1202 e
= e
->semantic(sc2
);
1206 { // Call invariant virtually
1207 ThisExp
*v
= new ThisExp(0);
1208 v
->type
= vthis
->type
;
1209 Expression
*se
= new StringExp(0, "null this");
1210 se
= se
->semantic(sc
);
1211 se
->type
= Type::tchar
->arrayOf();
1212 e
= new AssertExp(loc
, v
, se
);
1216 ExpStatement
*s
= new ExpStatement(0, e
);
1226 a
->push(returnLabel
->statement
);
1228 if (type
->nextOf()->ty
!= Tvoid
)
1230 // Create: return vresult;
1232 Expression
*e
= new VarExp(0, vresult
);
1234 { e
= e
->implicitCastTo(sc
, tintro
->nextOf());
1235 e
= e
->semantic(sc
);
1237 ReturnStatement
*s
= new ReturnStatement(0, e
);
1242 fbody
= new CompoundStatement(0, a
);
1251 void FuncDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1253 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1255 type
->toCBuffer(buf
, ident
, hgs
);
1256 bodyToCBuffer(buf
, hgs
);
1260 void FuncDeclaration::bodyToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1263 (!hgs
->hdrgen
|| hgs
->tpltMember
|| canInline(1,1))
1269 { buf
->writestring("in");
1271 frequire
->toCBuffer(buf
, hgs
);
1276 { buf
->writestring("out");
1278 { buf
->writebyte('(');
1279 buf
->writestring(outId
->toChars());
1280 buf
->writebyte(')');
1283 fensure
->toCBuffer(buf
, hgs
);
1286 if (frequire
|| fensure
)
1287 { buf
->writestring("body");
1291 buf
->writebyte('{');
1293 fbody
->toCBuffer(buf
, hgs
);
1294 buf
->writebyte('}');
1298 { buf
->writeByte(';');
1303 /****************************************************
1304 * Determine if 'this' overrides fd.
1305 * Return !=0 if it does.
1308 int FuncDeclaration::overrides(FuncDeclaration
*fd
)
1311 if (fd
->ident
== ident
)
1313 int cov
= type
->covariant(fd
->type
);
1315 { ClassDeclaration
*cd1
= toParent()->isClassDeclaration();
1316 ClassDeclaration
*cd2
= fd
->toParent()->isClassDeclaration();
1318 if (cd1
&& cd2
&& cd2
->isBaseOf(cd1
, NULL
))
1325 /*************************************************
1326 * Find index of function in vtbl[0..dim] that
1327 * this function overrides.
1329 * -1 didn't find one
1330 * -2 can't determine because of forward references
1333 int FuncDeclaration::findVtblIndex(Array
*vtbl
, int dim
)
1335 for (int vi
= 0; vi
< dim
; vi
++)
1337 FuncDeclaration
*fdv
= ((Dsymbol
*)vtbl
->data
[vi
])->isFuncDeclaration();
1338 if (fdv
&& fdv
->ident
== ident
)
1340 int cov
= type
->covariant(fdv
->type
);
1341 //printf("\tbaseclass cov = %d\n", cov);
1344 case 0: // types are distinct
1352 //fdv->type->print();
1353 //printf("%s %s\n", type->deco, fdv->type->deco);
1354 error("of type %s overrides but is not covariant with %s of type %s",
1355 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
1359 return -2; // forward references
1369 /****************************************************
1370 * Overload this FuncDeclaration with the new one f.
1371 * Return !=0 if successful; i.e. no conflict.
1374 int FuncDeclaration::overloadInsert(Dsymbol
*s
)
1377 AliasDeclaration
*a
;
1379 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1380 a
= s
->isAliasDeclaration();
1384 return overnext
->overloadInsert(a
);
1385 if (!a
->aliassym
&& a
->type
->ty
!= Tident
&& a
->type
->ty
!= Tinstance
)
1387 //printf("\ta = '%s'\n", a->type->toChars());
1391 //printf("\ttrue: no conflict\n");
1394 f
= s
->isFuncDeclaration();
1398 if (type
&& f
->type
&& // can be NULL for overloaded constructors
1399 f
->type
->covariant(type
) &&
1400 !isFuncAliasDeclaration())
1402 //printf("\tfalse: conflict %s\n", kind());
1407 return overnext
->overloadInsert(f
);
1409 //printf("\ttrue: no conflict\n");
1413 /********************************************
1414 * Find function in overload list that exactly matches t.
1417 /***************************************************
1418 * Visit each overloaded function in turn, and call
1419 * (*fp)(param, f) on it.
1420 * Exit when no more, or (*fp)(param, f) returns 1.
1426 int overloadApply(FuncDeclaration
*fstart
,
1427 int (*fp
)(void *, FuncDeclaration
*),
1434 for (d
= fstart
; d
; d
= next
)
1435 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1439 if (overloadApply(fa
->funcalias
, fp
, param
))
1441 next
= fa
->overnext
;
1445 AliasDeclaration
*a
= d
->isAliasDeclaration();
1449 Dsymbol
*s
= a
->toAlias();
1450 next
= s
->isDeclaration();
1458 f
= d
->isFuncDeclaration();
1460 { d
->error("is aliased to a function");
1461 break; // BUG: should print error message?
1463 if ((*fp
)(param
, f
))
1473 /********************************************
1474 * Find function in overload list that exactly matches t.
1479 Type
*t
; // type to match
1480 FuncDeclaration
*f
; // return value
1483 int fp1(void *param
, FuncDeclaration
*f
)
1484 { Param1
*p
= (Param1
*)param
;
1487 if (t
->equals(f
->type
))
1493 /* Allow covariant matches, if it's just a const conversion
1494 * of the return type
1496 if (t
->ty
== Tfunction
)
1497 { TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1498 if (tf
->covariant(t
) == 1 &&
1499 tf
->nextOf()->implicitConvTo(t
->nextOf()) >= MATCHconst
)
1509 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1514 overloadApply(this, &fp1
, &p
);
1519 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1525 for (d
= this; d
; d
= next
)
1526 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1530 FuncDeclaration
*f2
= fa
->funcalias
->overloadExactMatch(t
);
1533 next
= fa
->overnext
;
1537 AliasDeclaration
*a
= d
->isAliasDeclaration();
1541 Dsymbol
*s
= a
->toAlias();
1542 next
= s
->isDeclaration();
1548 f
= d
->isFuncDeclaration();
1550 break; // BUG: should print error message?
1551 if (t
->equals(d
->type
))
1561 /********************************************
1562 * Decide which function matches the arguments best.
1568 Expressions
*arguments
;
1571 int fp2(void *param
, FuncDeclaration
*f
)
1572 { Param2
*p
= (Param2
*)param
;
1574 Expressions
*arguments
= p
->arguments
;
1577 if (f
!= m
->lastf
) // skip duplicates
1582 tf
= (TypeFunction
*)f
->type
;
1583 match
= (MATCH
) tf
->callMatch(arguments
);
1584 //printf("match = %d\n", match);
1585 if (match
!= MATCHnomatch
)
1587 if (match
> m
->last
)
1590 if (match
< m
->last
)
1593 /* See if one of the matches overrides the other.
1595 if (m
->lastf
->overrides(f
))
1597 else if (f
->overrides(m
->lastf
))
1619 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
, Expressions
*arguments
)
1623 p
.arguments
= arguments
;
1624 overloadApply(fstart
, &fp2
, &p
);
1628 // Recursive helper function
1630 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
, Expressions
*arguments
)
1636 for (d
= fstart
; d
; d
= next
)
1639 FuncAliasDeclaration
*fa
;
1640 AliasDeclaration
*a
;
1642 fa
= d
->isFuncAliasDeclaration();
1645 overloadResolveX(m
, fa
->funcalias
, arguments
);
1646 next
= fa
->overnext
;
1648 else if ((f
= d
->isFuncDeclaration()) != NULL
)
1652 continue; // skip duplicates
1658 tf
= (TypeFunction
*)f
->type
;
1659 match
= (MATCH
) tf
->callMatch(arguments
);
1660 //printf("match = %d\n", match);
1661 if (match
!= MATCHnomatch
)
1663 if (match
> m
->last
)
1666 if (match
< m
->last
)
1669 /* See if one of the matches overrides the other.
1671 if (m
->lastf
->overrides(f
))
1673 else if (f
->overrides(m
->lastf
))
1692 else if ((a
= d
->isAliasDeclaration()) != NULL
)
1694 Dsymbol
*s
= a
->toAlias();
1695 next
= s
->isDeclaration();
1702 { d
->error("is aliased to a function");
1709 FuncDeclaration
*FuncDeclaration::overloadResolve(Loc loc
, Expressions
*arguments
)
1715 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1719 for (i
= 0; i
< arguments
->dim
; i
++)
1722 arg
= (Expression
*)arguments
->data
[i
];
1724 printf("\t%s: ", arg
->toChars());
1730 memset(&m
, 0, sizeof(m
));
1731 m
.last
= MATCHnomatch
;
1732 overloadResolveX(&m
, this, arguments
);
1734 if (m
.count
== 1) // exactly one match
1746 argExpTypesToCBuffer(&buf
, arguments
, &hgs
);
1749 if (m
.last
== MATCHnomatch
)
1751 tf
= (TypeFunction
*)type
;
1753 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1754 error(loc
, "%s does not match parameter types (%s)",
1755 Argument::argsTypesToChars(tf
->parameters
, tf
->varargs
),
1757 return m
.anyf
; // as long as it's not a FuncAliasDeclaration
1762 TypeFunction
*t1
= (TypeFunction
*)m
.lastf
->type
;
1763 TypeFunction
*t2
= (TypeFunction
*)m
.nextf
->type
;
1765 error(loc
, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1767 m
.lastf
->toPrettyChars(), Argument::argsTypesToChars(t1
->parameters
, t1
->varargs
),
1768 m
.nextf
->toPrettyChars(), Argument::argsTypesToChars(t2
->parameters
, t2
->varargs
));
1770 error(loc
, "overloads %s and %s both match argument list for %s",
1771 m
.lastf
->type
->toChars(),
1772 m
.nextf
->type
->toChars(),
1773 m
.lastf
->toChars());
1780 /********************************
1781 * Labels are in a separate scope, one per function.
1784 LabelDsymbol
*FuncDeclaration::searchLabel(Identifier
*ident
)
1788 labtab
= new DsymbolTable(); // guess we need one
1790 s
= labtab
->lookup(ident
);
1793 s
= new LabelDsymbol(ident
);
1796 return (LabelDsymbol
*)s
;
1798 /****************************************
1799 * If non-static member function that has a 'this' pointer,
1800 * return the aggregate it is a member of.
1801 * Otherwise, return NULL.
1804 AggregateDeclaration
*FuncDeclaration::isThis()
1805 { AggregateDeclaration
*ad
;
1807 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1809 if ((storage_class
& STCstatic
) == 0)
1813 //printf("-FuncDeclaration::isThis() %p\n", ad);
1817 AggregateDeclaration
*FuncDeclaration::isMember2()
1818 { AggregateDeclaration
*ad
;
1820 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1822 for (Dsymbol
*s
= this; s
; s
= s
->parent
)
1824 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1827 { //printf("test4\n");
1831 (!s
->parent
->isTemplateInstance()))
1832 { //printf("test5\n");
1836 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1840 /*****************************************
1841 * Determine lexical level difference from 'this' to nested function 'fd'.
1842 * Error if this cannot call fd.
1845 * -1 increase nesting by 1 (fd is nested within 'this')
1846 * >0 decrease nesting by number
1849 int FuncDeclaration::getLevel(Loc loc
, FuncDeclaration
*fd
)
1854 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1855 fdparent
= fd
->toParent2();
1856 if (fdparent
== this)
1860 while (fd
!= s
&& fdparent
!= s
->toParent2())
1862 //printf("\ts = '%s'\n", s->toChars());
1863 FuncDeclaration
*thisfd
= s
->isFuncDeclaration();
1865 { if (!thisfd
->isNested() && !thisfd
->vthis
)
1870 ClassDeclaration
*thiscd
= s
->isClassDeclaration();
1872 { if (!thiscd
->isNested())
1886 error(loc
, "cannot access frame of function %s", fd
->toChars());
1890 void FuncDeclaration::appendExp(Expression
*e
)
1893 s
= new ExpStatement(0, e
);
1897 void FuncDeclaration::appendState(Statement
*s
)
1898 { CompoundStatement
*cs
;
1903 a
= new Statements();
1904 fbody
= new CompoundStatement(0, a
);
1906 cs
= fbody
->isCompoundStatement();
1907 cs
->statements
->push(s
);
1911 int FuncDeclaration::isMain()
1913 return ident
== Id::main
&&
1914 linkage
!= LINKc
&& !isMember() && !isNested();
1917 int FuncDeclaration::isWinMain()
1919 return ident
== Id::WinMain
&&
1920 linkage
!= LINKc
&& !isMember();
1923 int FuncDeclaration::isDllMain()
1925 return ident
== Id::DllMain
&&
1926 linkage
!= LINKc
&& !isMember();
1929 int FuncDeclaration::isExport()
1931 return protection
== PROTexport
;
1934 int FuncDeclaration::isImportedSymbol()
1936 //printf("isImportedSymbol()\n");
1937 //printf("protection = %d\n", protection);
1938 return (protection
== PROTexport
) && !fbody
;
1941 // Determine if function goes into virtual function pointer table
1943 int FuncDeclaration::isVirtual()
1946 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1947 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
1948 printf("result is %d\n",
1950 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1951 toParent()->isClassDeclaration());
1953 return isMember() &&
1954 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1955 toParent()->isClassDeclaration();
1958 int FuncDeclaration::isAbstract()
1960 return storage_class
& STCabstract
;
1963 int FuncDeclaration::isCodeseg()
1965 return TRUE
; // functions are always in the code segment
1968 // Determine if function needs
1969 // a static frame pointer to its lexically enclosing function
1971 int FuncDeclaration::isNested()
1974 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
1975 //printf("\ttoParent() = '%s'\n", toParent()->toChars());
1976 return ((storage_class
& STCstatic
) == 0) &&
1977 (toParent2()->isFuncDeclaration() != NULL
);
1980 int FuncDeclaration::needThis()
1982 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
1983 int i
= isThis() != NULL
;
1984 //printf("\t%d\n", i);
1985 if (!i
&& isFuncAliasDeclaration())
1986 i
= ((FuncAliasDeclaration
*)this)->funcalias
->needThis();
1990 int FuncDeclaration::addPreInvariant()
1992 AggregateDeclaration
*ad
= isThis();
1994 //ad->isClassDeclaration() &&
1995 global
.params
.useInvariants
&&
1996 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2000 int FuncDeclaration::addPostInvariant()
2002 AggregateDeclaration
*ad
= isThis();
2005 //ad->isClassDeclaration() &&
2006 global
.params
.useInvariants
&&
2007 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2011 /**********************************
2012 * Generate a FuncDeclaration for a runtime library function.
2015 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, char *name
,
2016 Type
*t1
, Type
*t2
, Type
*t3
)
2018 return genCfunc(treturn
, Lexer::idPool(name
), t1
, t2
, t3
);
2021 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, Identifier
*id
,
2022 Type
*t1
, Type
*t2
, Type
*t3
)
2024 FuncDeclaration
*fd
;
2027 static DsymbolTable
*st
= NULL
;
2029 //printf("genCfunc(name = '%s')\n", id->toChars());
2030 //printf("treturn\n\t"); treturn->print();
2032 // See if already in table
2034 st
= new DsymbolTable();
2038 fd
= s
->isFuncDeclaration();
2040 assert(fd
->type
->nextOf()->equals(treturn
));
2044 Arguments
* args
= 0;
2046 args
= new Arguments
;
2047 args
->push(new Argument(STCin
,t1
,0,0));
2050 args
->push(new Argument(STCin
,t2
,0,0));
2052 args
->push(new Argument(STCin
,t3
,0,0));
2056 tf
= new TypeFunction(args
, treturn
, 0, LINKc
);
2057 fd
= new FuncDeclaration(0, 0, id
, STCstatic
, tf
);
2058 fd
->protection
= PROTpublic
;
2059 fd
->linkage
= LINKc
;
2066 char *FuncDeclaration::kind()
2070 /*******************************
2071 * Look at all the variables in this function that are referenced
2072 * by nested functions, and determine if a closure needs to be
2077 int FuncDeclaration::needsClosure()
2079 /* Need a closure for all the closureVars[] if any of the
2080 * closureVars[] are accessed by a
2081 * function that escapes the scope of this function.
2082 * We take the conservative approach and decide that any function that:
2083 * 1) is a virtual function
2084 * 2) has its address taken
2085 * 3) has a parent that escapes
2089 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2090 for (int i
= 0; i
< closureVars
.dim
; i
++)
2091 { VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2092 assert(v
->isVarDeclaration());
2093 //printf("\tv = %s\n", v->toChars());
2095 for (int j
= 0; j
< v
->nestedrefs
.dim
; j
++)
2096 { FuncDeclaration
*f
= (FuncDeclaration
*)v
->nestedrefs
.data
[j
];
2099 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2100 if (f
->isVirtual() || f
->tookAddressOf
)
2101 goto Lyes
; // assume f escapes this function's scope
2103 // Look to see if any parents of f that are below this escape
2104 for (Dsymbol
*s
= f
->parent
; s
!= this; s
= s
->parent
)
2106 f
= s
->isFuncDeclaration();
2107 if (f
&& (f
->isVirtual() || f
->tookAddressOf
))
2115 //printf("\tneeds closure\n");
2120 /****************************** FuncAliasDeclaration ************************/
2122 // Used as a way to import a set of functions from another scope into this one.
2124 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration
*funcalias
)
2125 : FuncDeclaration(funcalias
->loc
, funcalias
->endloc
, funcalias
->ident
,
2126 (enum STC
)funcalias
->storage_class
, funcalias
->type
)
2128 assert(funcalias
!= this);
2129 this->funcalias
= funcalias
;
2132 char *FuncAliasDeclaration::kind()
2134 return "function alias";
2138 /****************************** FuncLiteralDeclaration ************************/
2140 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc
, Loc endloc
, Type
*type
,
2141 enum TOK tok
, ForeachStatement
*fes
)
2142 : FuncDeclaration(loc
, endloc
, NULL
, STCundefined
, type
)
2147 id
= "__foreachbody";
2148 else if (tok
== TOKdelegate
)
2151 id
= "__funcliteral";
2152 this->ident
= Identifier::generateId(id
);
2155 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2158 Dsymbol
*FuncLiteralDeclaration::syntaxCopy(Dsymbol
*s
)
2160 FuncLiteralDeclaration
*f
;
2162 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2164 f
= (FuncLiteralDeclaration
*)s
;
2166 f
= new FuncLiteralDeclaration(loc
, endloc
, type
->syntaxCopy(), tok
, fes
);
2167 FuncDeclaration::syntaxCopy(f
);
2171 int FuncLiteralDeclaration::isNested()
2173 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2174 return (tok
== TOKdelegate
);
2177 char *FuncLiteralDeclaration::kind()
2179 // GCC requires the (char*) casts
2180 return (tok
== TOKdelegate
) ? (char*)"delegate" : (char*)"function";
2183 void FuncLiteralDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2185 static Identifier
*idfunc
;
2186 static Identifier
*iddel
;
2189 idfunc
= new Identifier("function", 0);
2191 iddel
= new Identifier("delegate", 0);
2193 type
->toCBuffer(buf
, ((tok
== TOKdelegate
) ? iddel
: idfunc
), hgs
);
2194 bodyToCBuffer(buf
, hgs
);
2198 /********************************* CtorDeclaration ****************************/
2200 CtorDeclaration::CtorDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2201 : FuncDeclaration(loc
, endloc
, Id::ctor
, STCundefined
, NULL
)
2203 this->arguments
= arguments
;
2204 this->varargs
= varargs
;
2205 //printf("CtorDeclaration() %s\n", toChars());
2208 Dsymbol
*CtorDeclaration::syntaxCopy(Dsymbol
*s
)
2212 f
= new CtorDeclaration(loc
, endloc
, NULL
, varargs
);
2215 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
2216 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
2217 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
2218 assert(!fthrows
); // deprecated
2220 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2225 void CtorDeclaration::semantic(Scope
*sc
)
2227 ClassDeclaration
*cd
;
2230 //printf("CtorDeclaration::semantic()\n");
2235 sc
->stc
&= ~STCstatic
; // not a static constructor
2237 parent
= sc
->parent
;
2238 Dsymbol
*parent
= toParent();
2239 cd
= parent
->isClassDeclaration();
2242 error("constructors are only for class definitions");
2247 tret
= cd
->type
; //->referenceTo();
2249 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
2251 VarDeclaration
*vd
= (VarDeclaration
*) cd
->fields
.data
[i
];
2255 arguments
= new Arguments();
2256 Argument
*a
= new Argument(vd
->storage_class
, vd
->type
, vd
->ident
, 0);
2257 // BUG: We don't really want these arguments in scope...
2260 Statement
*assign
= new ExpStatement(loc
, new AssignExp(loc
,
2261 new DotIdExp(loc
, new ThisExp(loc
), a
->ident
),
2262 new IdentifierExp(loc
, a
->ident
)));
2264 fbody
= new CompoundStatement(loc
, assign
, fbody
);
2271 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2273 sc
->flags
|= SCOPEctor
;
2274 type
= type
->semantic(loc
, sc
);
2275 sc
->flags
&= ~SCOPEctor
;
2279 // to the function body
2285 s
= new ReturnStatement(0, e
);
2286 fbody
= new CompoundStatement(0, fbody
, s
);
2289 FuncDeclaration::semantic(sc
);
2293 // See if it's the default constructor
2294 if (cd
&& varargs
== 0 && Argument::dim(arguments
) == 0)
2295 cd
->defaultCtor
= this;
2298 char *CtorDeclaration::kind()
2300 return "constructor";
2303 char *CtorDeclaration::toChars()
2308 int CtorDeclaration::isVirtual()
2313 int CtorDeclaration::addPreInvariant()
2318 int CtorDeclaration::addPostInvariant()
2320 return (vthis
&& global
.params
.useInvariants
);
2324 void CtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2326 buf
->writestring("this");
2327 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2328 bodyToCBuffer(buf
, hgs
);
2331 /********************************* DtorDeclaration ****************************/
2333 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
)
2334 : FuncDeclaration(loc
, endloc
, Id::dtor
, STCundefined
, NULL
)
2338 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2339 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2343 Dsymbol
*DtorDeclaration::syntaxCopy(Dsymbol
*s
)
2346 DtorDeclaration
*dd
= new DtorDeclaration(loc
, endloc
, ident
);
2347 return FuncDeclaration::syntaxCopy(dd
);
2351 void DtorDeclaration::semantic(Scope
*sc
)
2353 ClassDeclaration
*cd
;
2355 parent
= sc
->parent
;
2356 Dsymbol
*parent
= toParent();
2357 cd
= parent
->isClassDeclaration();
2360 error("destructors only are for class definitions");
2363 cd
->dtors
.push(this);
2364 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2367 sc
->stc
&= ~STCstatic
; // not a static destructor
2368 sc
->linkage
= LINKd
;
2370 FuncDeclaration::semantic(sc
);
2375 int DtorDeclaration::overloadInsert(Dsymbol
*s
)
2377 return FALSE
; // cannot overload destructors
2380 int DtorDeclaration::addPreInvariant()
2382 return (vthis
&& global
.params
.useInvariants
);
2385 int DtorDeclaration::addPostInvariant()
2390 int DtorDeclaration::isVirtual()
2392 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2393 * but doing so will require recompiling everything.
2398 return FuncDeclaration::isVirtual();
2402 void DtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2406 buf
->writestring("~this()");
2407 bodyToCBuffer(buf
, hgs
);
2410 /********************************* StaticCtorDeclaration ****************************/
2412 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
)
2413 : FuncDeclaration(loc
, endloc
,
2414 Identifier::generateId("_staticCtor"), STCstatic
, NULL
)
2418 Dsymbol
*StaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
2420 StaticCtorDeclaration
*scd
;
2423 scd
= new StaticCtorDeclaration(loc
, endloc
);
2424 return FuncDeclaration::syntaxCopy(scd
);
2428 void StaticCtorDeclaration::semantic(Scope
*sc
)
2430 //printf("StaticCtorDeclaration::semantic()\n");
2432 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2434 FuncDeclaration::semantic(sc
);
2436 // We're going to need ModuleInfo
2437 Module
*m
= getModule();
2441 { m
->needmoduleinfo
= 1;
2443 m
->strictlyneedmoduleinfo
= 1;
2448 AggregateDeclaration
*StaticCtorDeclaration::isThis()
2453 int StaticCtorDeclaration::isStaticConstructor()
2458 int StaticCtorDeclaration::isVirtual()
2463 int StaticCtorDeclaration::addPreInvariant()
2468 int StaticCtorDeclaration::addPostInvariant()
2473 void StaticCtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2476 { buf
->writestring("static this();\n");
2479 buf
->writestring("static this()");
2480 bodyToCBuffer(buf
, hgs
);
2483 /********************************* StaticDtorDeclaration ****************************/
2485 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
)
2486 : FuncDeclaration(loc
, endloc
,
2487 Identifier::generateId("_staticDtor"), STCstatic
, NULL
)
2491 Dsymbol
*StaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
2493 StaticDtorDeclaration
*sdd
;
2496 sdd
= new StaticDtorDeclaration(loc
, endloc
);
2497 return FuncDeclaration::syntaxCopy(sdd
);
2501 void StaticDtorDeclaration::semantic(Scope
*sc
)
2503 ClassDeclaration
*cd
;
2506 cd
= sc
->scopesym
->isClassDeclaration();
2510 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2512 FuncDeclaration::semantic(sc
);
2514 // We're going to need ModuleInfo
2515 Module
*m
= getModule();
2519 { m
->needmoduleinfo
= 1;
2521 m
->strictlyneedmoduleinfo
= 1;
2526 AggregateDeclaration
*StaticDtorDeclaration::isThis()
2531 int StaticDtorDeclaration::isStaticDestructor()
2536 int StaticDtorDeclaration::isVirtual()
2541 int StaticDtorDeclaration::addPreInvariant()
2546 int StaticDtorDeclaration::addPostInvariant()
2551 void StaticDtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2555 buf
->writestring("static ~this()");
2556 bodyToCBuffer(buf
, hgs
);
2559 /********************************* InvariantDeclaration ****************************/
2561 InvariantDeclaration::InvariantDeclaration(Loc loc
, Loc endloc
)
2562 : FuncDeclaration(loc
, endloc
, Id::classInvariant
, STCundefined
, NULL
)
2566 Dsymbol
*InvariantDeclaration::syntaxCopy(Dsymbol
*s
)
2568 InvariantDeclaration
*id
;
2571 id
= new InvariantDeclaration(loc
, endloc
);
2572 FuncDeclaration::syntaxCopy(id
);
2577 void InvariantDeclaration::semantic(Scope
*sc
)
2579 AggregateDeclaration
*ad
;
2582 parent
= sc
->parent
;
2583 Dsymbol
*parent
= toParent();
2584 ad
= parent
->isAggregateDeclaration();
2587 error("invariants only are for struct/union/class definitions");
2590 else if (ad
->inv
&& ad
->inv
!= this)
2592 error("more than one invariant for %s", ad
->toChars());
2595 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2598 sc
->stc
&= ~STCstatic
; // not a static invariant
2600 sc
->linkage
= LINKd
;
2602 FuncDeclaration::semantic(sc
);
2607 int InvariantDeclaration::isVirtual()
2612 int InvariantDeclaration::addPreInvariant()
2617 int InvariantDeclaration::addPostInvariant()
2622 void InvariantDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2626 buf
->writestring("invariant");
2627 bodyToCBuffer(buf
, hgs
);
2631 /********************************* UnitTestDeclaration ****************************/
2633 /*******************************
2634 * Generate unique unittest function Id so we can have multiple
2635 * instances per module.
2638 static Identifier
*unitTestId()
2641 char buffer
[10 + sizeof(n
)*3 + 1];
2643 sprintf(buffer
,"__unittest%d", n
);
2645 return Lexer::idPool(buffer
);
2648 UnitTestDeclaration::UnitTestDeclaration(Loc loc
, Loc endloc
)
2649 : FuncDeclaration(loc
, endloc
, unitTestId(), STCundefined
, NULL
)
2653 Dsymbol
*UnitTestDeclaration::syntaxCopy(Dsymbol
*s
)
2655 UnitTestDeclaration
*utd
;
2658 utd
= new UnitTestDeclaration(loc
, endloc
);
2659 return FuncDeclaration::syntaxCopy(utd
);
2663 void UnitTestDeclaration::semantic(Scope
*sc
)
2665 if (global
.params
.useUnitTests
)
2669 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2670 FuncDeclaration::semantic(sc
);
2673 // We're going to need ModuleInfo even if the unit tests are not
2674 // compiled in, because other modules may import this module and refer
2675 // to this ModuleInfo.
2676 Module
*m
= getModule();
2680 m
->needmoduleinfo
= 1;
2683 AggregateDeclaration
*UnitTestDeclaration::isThis()
2688 int UnitTestDeclaration::isVirtual()
2693 int UnitTestDeclaration::addPreInvariant()
2698 int UnitTestDeclaration::addPostInvariant()
2703 void UnitTestDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2707 buf
->writestring("unittest");
2708 bodyToCBuffer(buf
, hgs
);
2711 /********************************* NewDeclaration ****************************/
2713 NewDeclaration::NewDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2714 : FuncDeclaration(loc
, endloc
, Id::classNew
, STCstatic
, NULL
)
2716 this->arguments
= arguments
;
2717 this->varargs
= varargs
;
2720 Dsymbol
*NewDeclaration::syntaxCopy(Dsymbol
*s
)
2724 f
= new NewDeclaration(loc
, endloc
, NULL
, varargs
);
2726 FuncDeclaration::syntaxCopy(f
);
2728 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2734 void NewDeclaration::semantic(Scope
*sc
)
2736 ClassDeclaration
*cd
;
2739 //printf("NewDeclaration::semantic()\n");
2741 parent
= sc
->parent
;
2742 Dsymbol
*parent
= toParent();
2743 cd
= parent
->isClassDeclaration();
2744 if (!cd
&& !parent
->isStructDeclaration())
2746 error("new allocators only are for class or struct definitions");
2748 tret
= Type::tvoid
->pointerTo();
2749 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2751 type
= type
->semantic(loc
, sc
);
2752 assert(type
->ty
== Tfunction
);
2754 // Check that there is at least one argument of type uint
2755 TypeFunction
*tf
= (TypeFunction
*)type
;
2756 if (Argument::dim(tf
->parameters
) < 1)
2758 error("at least one argument of type uint expected");
2762 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2763 if (!a
->type
->equals(Type::tuns32
) &&
2764 (! global
.params
.isX86_64
|| !a
->type
->equals(Type::tuns64
)))
2765 error("first argument must be type uint, not %s", a
->type
->toChars());
2768 FuncDeclaration::semantic(sc
);
2771 char *NewDeclaration::kind()
2776 int NewDeclaration::isVirtual()
2781 int NewDeclaration::addPreInvariant()
2786 int NewDeclaration::addPostInvariant()
2791 void NewDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2793 buf
->writestring("new");
2794 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2795 bodyToCBuffer(buf
, hgs
);
2799 /********************************* DeleteDeclaration ****************************/
2801 DeleteDeclaration::DeleteDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
)
2802 : FuncDeclaration(loc
, endloc
, Id::classDelete
, STCstatic
, NULL
)
2804 this->arguments
= arguments
;
2807 Dsymbol
*DeleteDeclaration::syntaxCopy(Dsymbol
*s
)
2809 DeleteDeclaration
*f
;
2811 f
= new DeleteDeclaration(loc
, endloc
, NULL
);
2813 FuncDeclaration::syntaxCopy(f
);
2815 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2821 void DeleteDeclaration::semantic(Scope
*sc
)
2823 ClassDeclaration
*cd
;
2825 //printf("DeleteDeclaration::semantic()\n");
2827 parent
= sc
->parent
;
2828 Dsymbol
*parent
= toParent();
2829 cd
= parent
->isClassDeclaration();
2830 if (!cd
&& !parent
->isStructDeclaration())
2832 error("new allocators only are for class or struct definitions");
2834 type
= new TypeFunction(arguments
, Type::tvoid
, 0, LINKd
);
2836 type
= type
->semantic(loc
, sc
);
2837 assert(type
->ty
== Tfunction
);
2839 // Check that there is only one argument of type void*
2840 TypeFunction
*tf
= (TypeFunction
*)type
;
2841 if (Argument::dim(tf
->parameters
) != 1)
2843 error("one argument of type void* expected");
2847 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2848 if (!a
->type
->equals(Type::tvoid
->pointerTo()))
2849 error("one argument of type void* expected, not %s", a
->type
->toChars());
2852 FuncDeclaration::semantic(sc
);
2855 char *DeleteDeclaration::kind()
2857 return "deallocator";
2860 int DeleteDeclaration::isDelete()
2865 int DeleteDeclaration::isVirtual()
2870 int DeleteDeclaration::addPreInvariant()
2875 int DeleteDeclaration::addPostInvariant()
2880 void DeleteDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2882 buf
->writestring("delete");
2883 Argument::argsToCBuffer(buf
, hgs
, arguments
, 0);
2884 bodyToCBuffer(buf
, hgs
);