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());
323 if (fdv
->toParent() == parent
)
325 // If both are mixins, then error.
326 // If either is not, the one that is not overrides
328 if (fdv
->parent
->isClassDeclaration())
330 if (!this->parent
->isClassDeclaration()
332 && !isDtorDeclaration()
335 && !isPostBlitDeclaration()
338 error("multiple overrides of same function");
340 cd
->vtbl
.data
[vi
] = (void *)this;
343 /* This works by whenever this function is called,
344 * it actually returns tintro, which gets dynamically
345 * cast to type. But we know that tintro is a base
346 * of type, so we could optimize it by not doing a
347 * dynamic cast, but just subtracting the isBaseOf()
348 * offset if the value is != null.
352 tintro
= fdv
->tintro
;
353 else if (!type
->equals(fdv
->type
))
355 /* Only need to have a tintro if the vptr
358 target_ptrdiff_t offset
;
359 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
368 /* Go through all the interface bases.
369 * If this function is covariant with any members of those interface
370 * functions, set the tintro.
372 for (int i
= 0; i
< cd
->interfaces_dim
; i
++)
375 BaseClass
*b
= cd
->interfaces
[i
];
376 vi
= findVtblIndex(&b
->base
->vtbl
, b
->base
->vtbl
.dim
);
383 cd
->sizeok
= 2; // can't finish due to forward reference
387 { FuncDeclaration
*fdv
= (FuncDeclaration
*)b
->base
->vtbl
.data
[vi
];
392 else if (!type
->equals(fdv
->type
))
394 /* Only need to have a tintro if the vptr
397 target_ptrdiff_t offset
;
398 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
404 else if (type
->nextOf()->ty
== Tclass
)
405 { ClassDeclaration
*cdn
= ((TypeClass
*)type
->nextOf())->sym
;
406 if (cdn
&& cdn
->sizeok
!= 1)
414 if (tintro
&& !tintro
->equals(ti
))
416 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
424 BaseClass
*b
= cd
->interfaces
[i
];
425 for (vi
= 0; vi
< b
->base
->vtbl
.dim
; vi
++)
427 Dsymbol
*s
= (Dsymbol
*)b
->base
->vtbl
.data
[vi
];
428 //printf("interface %d vtbl[%d] %p %s\n", i, vi, s, s->toChars());
429 FuncDeclaration
*fdv
= s
->isFuncDeclaration();
430 if (fdv
&& fdv
->ident
== ident
)
432 int cov
= type
->covariant(fdv
->type
);
433 //printf("\tcov = %d\n", cov);
437 //fdv->type->print();
438 //printf("%s %s\n", type->deco, fdv->type->deco);
439 error("of type %s overrides but is not covariant with %s of type %s",
440 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
447 else if (!type
->equals(fdv
->type
))
449 /* Only need to have a tintro if the vptr
452 target_ptrdiff_t offset
;
453 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
459 else if (type
->nextOf()->ty
== Tclass
)
460 { ClassDeclaration
*cdn
= ((TypeClass
*)type
->nextOf())->sym
;
461 if (cdn
&& cdn
->sizeok
!= 1)
469 if (tintro
&& !tintro
->equals(ti
))
471 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
479 cd
->sizeok
= 2; // can't finish due to forward reference
487 if (introducing
&& isOverride())
489 error("does not override any function");
494 else if (isOverride() && !parent
->isTemplateInstance())
495 error("override only applies to class member functions");
497 /* Do not allow template instances to add virtual functions
502 TemplateInstance
*ti
= parent
->isTemplateInstance();
505 // Take care of nested templates
508 TemplateInstance
*ti2
= ti
->tempdecl
->parent
->isTemplateInstance();
514 // If it's a member template
515 ClassDeclaration
*cd
= ti
->tempdecl
->isClassMember();
518 error("cannot use template to add virtual function to class '%s'", cd
->toChars());
525 // Check parameters to see if they are either () or (char[][] args)
533 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
534 if (arg0
->type
->ty
!= Tarray
||
535 arg0
->type
->nextOf()->ty
!= Tarray
||
536 arg0
->type
->nextOf()->nextOf()->ty
!= Tchar
||
537 arg0
->storageClass
& (STCout
| STCref
| STClazy
))
546 if (f
->nextOf()->ty
!= Tint32
&& f
->nextOf()->ty
!= Tvoid
)
547 error("must return int or void, not %s", f
->nextOf()->toChars());
551 error("parameters must be main() or main(char[][] args)");
555 if (ident
== Id::assign
&& (sd
|| cd
))
556 { // Disallow identity assignment operator.
560 { if (f
->varargs
== 1)
565 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
566 Type
*t0
= arg0
->type
->toBasetype();
567 Type
*tb
= sd
? sd
->type
: cd
->type
;
568 if (arg0
->type
->implicitConvTo(tb
) ||
569 (sd
&& t0
->ty
== Tpointer
&& t0
->nextOf()->implicitConvTo(tb
))
574 Argument
*arg1
= Argument::getNth(f
->parameters
, 1);
575 if (arg1
->defaultArg
)
582 /* Save scope for possible later use (if we need the
583 * function internals)
585 scope
= new Scope(*sc
);
590 error("identity assignment operator overload is illegal");
593 void FuncDeclaration::semantic2(Scope
*sc
)
597 // Do the semantic analysis on the internals of the function.
599 void FuncDeclaration::semantic3(Scope
*sc
)
601 AggregateDeclaration
*ad
;
602 VarDeclaration
*argptr
= NULL
;
603 VarDeclaration
*_arguments
= NULL
;
609 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
612 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
614 //{ static int x; if (++x == 2) *(char*)0=0; }
615 //printf("\tlinkage = %d\n", sc->linkage);
617 //printf(" sc->incontract = %d\n", sc->incontract);
622 if (!type
|| type
->ty
!= Tfunction
)
624 f
= (TypeFunction
*)(type
);
625 size_t nparams
= Argument::dim(f
->parameters
);
627 // Check the 'throws' clause
631 for (i
= 0; i
< fthrows
->dim
; i
++)
633 Type
*t
= (Type
*)fthrows
->data
[i
];
635 t
= t
->semantic(loc
, sc
);
636 if (!t
->isClassHandle())
637 error("can only throw classes, not %s", t
->toChars());
641 if (fbody
|| frequire
)
643 /* Symbol table into which we place parameters and nested functions,
644 * solely to diagnose name collisions.
646 localsymtab
= new DsymbolTable();
648 // Establish function scope
649 ScopeDsymbol
*ss
= new ScopeDsymbol();
650 ss
->parent
= sc
->scopesym
;
651 Scope
*sc2
= sc
->push(ss
);
656 sc2
->scontinue
= NULL
;
659 sc2
->linkage
= LINKd
;
660 sc2
->stc
&= ~(STCauto
| STCscope
| STCstatic
| STCabstract
| STCdeprecated
| STCfinal
);
661 sc2
->attributes
= NULL
;
662 sc2
->protection
= PROTpublic
;
663 sc2
->explicitProtection
= 0;
664 sc2
->structalign
= 8;
674 if (isFuncLiteralDeclaration() && isNested())
676 error("literals cannot be class members");
681 assert(!isNested()); // can't be both member and nested
683 v
= new ThisDeclaration(ad
->handle
);
684 v
->storage_class
|= STCparameter
| STCin
;
696 v
= new ThisDeclaration(Type::tvoid
->pointerTo());
697 v
->storage_class
|= STCparameter
| STCin
;
705 // Declare hidden variable _arguments[] and _argptr
709 if (f
->linkage
== LINKd
)
710 { // Declare _arguments[]
712 v_arguments
= new VarDeclaration(0, Type::typeinfotypelist
->type
, Id::_arguments_typeinfo
, NULL
);
713 v_arguments
->storage_class
= STCparameter
| STCin
;
714 v_arguments
->semantic(sc2
);
715 sc2
->insert(v_arguments
);
716 v_arguments
->parent
= this;
718 t
= Type::typeinfo
->type
->arrayOf();
719 _arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
720 _arguments
->semantic(sc2
);
721 sc2
->insert(_arguments
);
722 _arguments
->parent
= this;
724 t
= Type::typeinfo
->type
->arrayOf();
725 v_arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
726 v_arguments
->storage_class
= STCparameter
| STCin
;
727 v_arguments
->semantic(sc2
);
728 sc2
->insert(v_arguments
);
729 v_arguments
->parent
= this;
732 if (f
->linkage
== LINKd
|| (parameters
&& parameters
->dim
))
735 t
= d_gcc_builtin_va_list_d_type
;
737 t
= Type::tvoid
->pointerTo();
739 argptr
= new VarDeclaration(0, t
, Id::_argptr
, NULL
);
740 argptr
->semantic(sc2
);
742 argptr
->parent
= this;
746 // Propagate storage class from tuple parameters to their element-parameters.
749 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
750 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
752 if (arg
->type
->ty
== Ttuple
)
753 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
754 size_t dim
= Argument::dim(t
->arguments
);
755 for (size_t j
= 0; j
< dim
; j
++)
756 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
757 narg
->storageClass
= arg
->storageClass
;
763 // Declare all the function parameters as variables
765 { /* parameters[] has all the tuples removed, as the back end
766 * doesn't know about tuples
768 parameters
= new Dsymbols();
769 parameters
->reserve(nparams
);
770 for (size_t i
= 0; i
< nparams
; i
++)
772 Argument
*arg
= Argument::getNth(f
->parameters
, i
);
773 Identifier
*id
= arg
->ident
;
776 /* Generate identifier for un-named parameter,
777 * because we need it later on.
780 buf
.printf("_param_%"PRIuSIZE
, i
);
781 char *name
= (char *)buf
.extractData();
782 id
= new Identifier(name
, TOKidentifier
);
785 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, id
, NULL
);
786 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
787 v
->storage_class
|= STCparameter
;
788 if (f
->varargs
== 2 && i
+ 1 == nparams
)
789 v
->storage_class
|= STCvariadic
;
790 v
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STClazy
);
791 if (v
->storage_class
& STClazy
)
792 v
->storage_class
|= STCin
;
795 error("parameter %s.%s is already defined", toChars(), v
->toChars());
798 localsymtab
->insert(v
);
803 // Declare the tuple symbols and put them in the symbol table,
804 // but not in parameters[].
807 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
808 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
811 continue; // never used, so ignore
812 if (arg
->type
->ty
== Ttuple
)
813 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
814 size_t dim
= Argument::dim(t
->arguments
);
815 Objects
*exps
= new Objects();
817 for (size_t j
= 0; j
< dim
; j
++)
818 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
820 VarDeclaration
*v
= sc2
->search(0, narg
->ident
, NULL
)->isVarDeclaration();
822 Expression
*e
= new VarExp(0, v
);
823 exps
->data
[j
] = (void *)e
;
826 TupleDeclaration
*v
= new TupleDeclaration(0, arg
->ident
, exps
);
827 //printf("declaring tuple %s\n", v->toChars());
830 error("parameter %s.%s is already defined", toChars(), v
->toChars());
831 localsymtab
->insert(v
);
837 /* Do the semantic analysis on the [in] preconditions and
838 * [out] postconditions.
843 { /* frequire is composed of the [in] contracts
845 // BUG: need to error if accessing out parameters
846 // BUG: need to treat parameters as const
847 // BUG: need to disallow returns and throws
848 // BUG: verify that all in and ref parameters are read
849 frequire
= frequire
->semantic(sc2
);
850 labtab
= NULL
; // so body can't refer to labels
853 if (fensure
|| addPostInvariant())
854 { /* fensure is composed of the [out] contracts
856 ScopeDsymbol
*sym
= new ScopeDsymbol();
857 sym
->parent
= sc2
->scopesym
;
858 sc2
= sc2
->push(sym
);
860 assert(type
->nextOf());
861 if (type
->nextOf()->ty
== Tvoid
)
864 error("void functions have no result");
869 outId
= Id::result
; // provide a default
873 { // Declare result variable
880 v
= new VarDeclaration(loc
, type
->nextOf(), outId
, NULL
);
882 v
->skipnullcheck
= 1;
887 error("out result %s is already defined", v
->toChars());
891 // vresult gets initialized with the function return value
892 // in ReturnStatement::semantic()
895 // BUG: need to treat parameters as const
896 // BUG: need to disallow returns and throws
898 { fensure
= fensure
->semantic(sc2
);
899 labtab
= NULL
; // so body can't refer to labels
902 if (!global
.params
.useOut
)
903 { fensure
= NULL
; // discard
907 // Postcondition invariant
908 if (addPostInvariant())
910 Expression
*e
= NULL
;
911 if (isCtorDeclaration())
913 // Call invariant directly only if it exists
914 InvariantDeclaration
*inv
= ad
->inv
;
915 ClassDeclaration
*cd
= ad
->isClassDeclaration();
926 e
= new DsymbolExp(0, inv
);
927 e
= new CallExp(0, e
);
928 e
= e
->semantic(sc2
);
932 { // Call invariant virtually
933 ThisExp
*v
= new ThisExp(0);
934 v
->type
= vthis
->type
;
935 e
= new AssertExp(0, v
);
939 ExpStatement
*s
= new ExpStatement(0, e
);
941 fensure
= new CompoundStatement(0, s
, fensure
);
948 { returnLabel
= new LabelDsymbol(Id::returnLabel
);
949 LabelStatement
*ls
= new LabelStatement(0, Id::returnLabel
, fensure
);
950 ls
->isReturnLabel
= 1;
951 returnLabel
->statement
= ls
;
959 { ClassDeclaration
*cd
= isClassMember();
961 /* If this is a class constructor
963 if (isCtorDeclaration() && cd
)
965 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
966 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
972 if (inferRetType
|| f
->retStyle() != RETstack
)
975 fbody
= fbody
->semantic(sc2
);
978 { // If no return type inferred yet, then infer a void
981 ((TypeFunction
*)type
)->next
= Type::tvoid
;
982 type
= type
->semantic(loc
, sc
);
984 f
= (TypeFunction
*)type
;
987 int offend
= fbody
? fbody
->fallOffEnd() : TRUE
;
989 if (isStaticCtorDeclaration())
990 { /* It's a static constructor. Ensure that all
991 * ctor consts were initialized.
994 Dsymbol
*p
= toParent();
995 ScopeDsymbol
*ad
= p
->isScopeDsymbol();
998 error("static constructor can only be member of struct/class/module, not %s %s", p
->kind(), p
->toChars());
1002 for (int i
= 0; i
< ad
->members
->dim
; i
++)
1003 { Dsymbol
*s
= (Dsymbol
*)ad
->members
->data
[i
];
1005 s
->checkCtorConstInit();
1010 if (isCtorDeclaration() && cd
)
1012 //printf("callSuper = x%x\n", sc2->callSuper);
1014 // Verify that all the ctorinit fields got initialized
1015 // Also check that non-null members got set
1016 if (!(sc2
->callSuper
& CSXthis_ctor
))
1018 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
1019 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
1021 if (v
->ctorinit
== 0)
1023 if (v
->isCtorinit())
1024 error("missing initializer for const field %s", v
->toChars());
1025 else if (v
->type
->ty
== Tclass
|| v
->type
->ty
== Tpointer
)
1026 error("missing initializer for non-null field %s", v
->toChars());
1031 if (!(sc2
->callSuper
& CSXany_ctor
) &&
1032 cd
->baseClass
&& cd
->baseClass
->ctor
)
1036 // Insert implicit super() at start of fbody
1037 Expression
*e1
= new SuperExp(0);
1038 Expression
*e
= new CallExp(0, e1
);
1040 unsigned errors
= global
.errors
;
1042 e
= e
->semantic(sc2
);
1044 if (errors
!= global
.errors
)
1045 error("no match for implicit super() call in constructor");
1047 Statement
*s
= new ExpStatement(0, e
);
1048 fbody
= new CompoundStatement(0, s
, fbody
);
1052 { // For foreach(){} body, append a return 0;
1053 Expression
*e
= new IntegerExp(0);
1054 Statement
*s
= new ReturnStatement(0, e
);
1055 fbody
= new CompoundStatement(0, fbody
, s
);
1056 assert(!returnLabel
);
1058 else if (!hasReturnExp
&& type
->nextOf()->ty
!= Tvoid
)
1059 error("expected to return a value of type %s", type
->nextOf()->toChars());
1060 else if (!inlineAsm
)
1062 if (type
->nextOf()->ty
== Tvoid
)
1064 if (offend
&& isMain())
1065 { // Add a return 0; statement
1066 Statement
*s
= new ReturnStatement(0, new IntegerExp(0));
1067 fbody
= new CompoundStatement(0, fbody
, s
);
1075 if (global
.params
.warnings
)
1076 { fprintf(stdmsg
, "warning - ");
1077 error("no return at end of function");
1080 if (global
.params
.useAssert
&&
1081 !global
.params
.useInline
)
1082 { /* Add an assert(0, msg); where the missing return
1088 new StringExp(loc
, "missing return expression")
1092 e
= new HaltExp(endloc
);
1093 e
= new CommaExp(0, e
, type
->nextOf()->defaultInit());
1094 e
= e
->semantic(sc2
);
1095 Statement
*s
= new ExpStatement(0, e
);
1096 fbody
= new CompoundStatement(0, fbody
, s
);
1103 Statements
*a
= new Statements();
1105 // Merge in initialization of 'out' parameters
1107 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1109 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1110 if (v
->storage_class
& STCout
)
1113 ExpInitializer
*ie
= v
->init
->isExpInitializer();
1115 a
->push(new ExpStatement(0, ie
->exp
));
1121 { // Initialize _argptr to point past non-variadic arg
1123 // Handled in FuncDeclaration::toObjFile
1125 v_argptr
->init
= new VoidInitializer(loc
);
1129 Type
*t
= argptr
->type
;
1133 e1
= new VarExp(0, argptr
);
1134 if (parameters
&& parameters
->dim
)
1135 p
= (VarDeclaration
*)parameters
->data
[parameters
->dim
- 1];
1137 p
= v_arguments
; // last parameter is _arguments[]
1138 offset
= p
->type
->size();
1139 offset
= (offset
+ 3) & ~3; // assume stack aligns on 4
1140 e
= new SymOffExp(0, p
, offset
);
1141 e
= new AssignExp(0, e1
, e
);
1143 a
->push(new ExpStatement(0, e
));
1150 v_arguments_var
= _arguments
;
1151 v_arguments_var
->init
= new VoidInitializer(loc
);
1153 /* Advance to elements[] member of TypeInfo_Tuple with:
1154 * _arguments = v_arguments.elements;
1156 Expression
*e
= new VarExp(0, v_arguments
);
1157 e
= new DotIdExp(0, e
, Id::elements
);
1158 Expression
*e1
= new VarExp(0, _arguments
);
1159 e
= new AssignExp(0, e1
, e
);
1160 e
= e
->semantic(sc
);
1161 a
->push(new ExpStatement(0, e
));
1164 // Merge contracts together with body into one compound statement
1167 if (frequire
&& global
.params
.useIn
)
1168 { frequire
->incontract
= 1;
1172 if (frequire
&& global
.params
.useIn
)
1176 // Precondition invariant
1177 if (addPreInvariant())
1179 Expression
*e
= NULL
;
1180 if (isDtorDeclaration())
1182 // Call invariant directly only if it exists
1183 InvariantDeclaration
*inv
= ad
->inv
;
1184 ClassDeclaration
*cd
= ad
->isClassDeclaration();
1195 e
= new DsymbolExp(0, inv
);
1196 e
= new CallExp(0, e
);
1197 e
= e
->semantic(sc2
);
1201 { // Call invariant virtually
1202 ThisExp
*v
= new ThisExp(0);
1203 v
->type
= vthis
->type
;
1204 Expression
*se
= new StringExp(0, "null this");
1205 se
= se
->semantic(sc
);
1206 se
->type
= Type::tchar
->arrayOf();
1207 e
= new AssertExp(loc
, v
, se
);
1211 ExpStatement
*s
= new ExpStatement(0, e
);
1221 a
->push(returnLabel
->statement
);
1223 if (type
->nextOf()->ty
!= Tvoid
)
1225 // Create: return vresult;
1227 Expression
*e
= new VarExp(0, vresult
);
1229 { e
= e
->implicitCastTo(sc
, tintro
->nextOf());
1230 e
= e
->semantic(sc
);
1232 ReturnStatement
*s
= new ReturnStatement(0, e
);
1237 fbody
= new CompoundStatement(0, a
);
1246 void FuncDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1248 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1250 type
->toCBuffer(buf
, ident
, hgs
);
1251 bodyToCBuffer(buf
, hgs
);
1255 void FuncDeclaration::bodyToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1258 (!hgs
->hdrgen
|| hgs
->tpltMember
|| canInline(1,1))
1264 { buf
->writestring("in");
1266 frequire
->toCBuffer(buf
, hgs
);
1271 { buf
->writestring("out");
1273 { buf
->writebyte('(');
1274 buf
->writestring(outId
->toChars());
1275 buf
->writebyte(')');
1278 fensure
->toCBuffer(buf
, hgs
);
1281 if (frequire
|| fensure
)
1282 { buf
->writestring("body");
1286 buf
->writebyte('{');
1288 fbody
->toCBuffer(buf
, hgs
);
1289 buf
->writebyte('}');
1293 { buf
->writeByte(';');
1298 /****************************************************
1299 * Determine if 'this' overrides fd.
1300 * Return !=0 if it does.
1303 int FuncDeclaration::overrides(FuncDeclaration
*fd
)
1306 if (fd
->ident
== ident
)
1308 int cov
= type
->covariant(fd
->type
);
1310 { ClassDeclaration
*cd1
= toParent()->isClassDeclaration();
1311 ClassDeclaration
*cd2
= fd
->toParent()->isClassDeclaration();
1313 if (cd1
&& cd2
&& cd2
->isBaseOf(cd1
, NULL
))
1320 /*************************************************
1321 * Find index of function in vtbl[0..dim] that
1322 * this function overrides.
1324 * -1 didn't find one
1325 * -2 can't determine because of forward references
1328 int FuncDeclaration::findVtblIndex(Array
*vtbl
, int dim
)
1330 for (int vi
= 0; vi
< dim
; vi
++)
1332 FuncDeclaration
*fdv
= ((Dsymbol
*)vtbl
->data
[vi
])->isFuncDeclaration();
1333 if (fdv
&& fdv
->ident
== ident
)
1335 int cov
= type
->covariant(fdv
->type
);
1336 //printf("\tbaseclass cov = %d\n", cov);
1339 case 0: // types are distinct
1347 //fdv->type->print();
1348 //printf("%s %s\n", type->deco, fdv->type->deco);
1349 error("of type %s overrides but is not covariant with %s of type %s",
1350 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
1354 return -2; // forward references
1364 /****************************************************
1365 * Overload this FuncDeclaration with the new one f.
1366 * Return !=0 if successful; i.e. no conflict.
1369 int FuncDeclaration::overloadInsert(Dsymbol
*s
)
1372 AliasDeclaration
*a
;
1374 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1375 a
= s
->isAliasDeclaration();
1379 return overnext
->overloadInsert(a
);
1380 if (!a
->aliassym
&& a
->type
->ty
!= Tident
&& a
->type
->ty
!= Tinstance
)
1382 //printf("\ta = '%s'\n", a->type->toChars());
1386 //printf("\ttrue: no conflict\n");
1389 f
= s
->isFuncDeclaration();
1393 if (type
&& f
->type
&& // can be NULL for overloaded constructors
1394 f
->type
->covariant(type
) &&
1395 !isFuncAliasDeclaration())
1397 //printf("\tfalse: conflict %s\n", kind());
1402 return overnext
->overloadInsert(f
);
1404 //printf("\ttrue: no conflict\n");
1408 /********************************************
1409 * Find function in overload list that exactly matches t.
1412 /***************************************************
1413 * Visit each overloaded function in turn, and call
1414 * (*fp)(param, f) on it.
1415 * Exit when no more, or (*fp)(param, f) returns 1.
1421 int overloadApply(FuncDeclaration
*fstart
,
1422 int (*fp
)(void *, FuncDeclaration
*),
1429 for (d
= fstart
; d
; d
= next
)
1430 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1434 if (overloadApply(fa
->funcalias
, fp
, param
))
1436 next
= fa
->overnext
;
1440 AliasDeclaration
*a
= d
->isAliasDeclaration();
1444 Dsymbol
*s
= a
->toAlias();
1445 next
= s
->isDeclaration();
1453 f
= d
->isFuncDeclaration();
1455 { d
->error("is aliased to a function");
1456 break; // BUG: should print error message?
1458 if ((*fp
)(param
, f
))
1468 /********************************************
1469 * Find function in overload list that exactly matches t.
1474 Type
*t
; // type to match
1475 FuncDeclaration
*f
; // return value
1478 int fp1(void *param
, FuncDeclaration
*f
)
1479 { Param1
*p
= (Param1
*)param
;
1482 if (t
->equals(f
->type
))
1488 /* Allow covariant matches, if it's just a const conversion
1489 * of the return type
1491 if (t
->ty
== Tfunction
)
1492 { TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1493 if (tf
->covariant(t
) == 1 &&
1494 tf
->nextOf()->implicitConvTo(t
->nextOf()) >= MATCHconst
)
1504 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1509 overloadApply(this, &fp1
, &p
);
1514 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1520 for (d
= this; d
; d
= next
)
1521 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1525 FuncDeclaration
*f2
= fa
->funcalias
->overloadExactMatch(t
);
1528 next
= fa
->overnext
;
1532 AliasDeclaration
*a
= d
->isAliasDeclaration();
1536 Dsymbol
*s
= a
->toAlias();
1537 next
= s
->isDeclaration();
1543 f
= d
->isFuncDeclaration();
1545 break; // BUG: should print error message?
1546 if (t
->equals(d
->type
))
1556 /********************************************
1557 * Decide which function matches the arguments best.
1563 Expressions
*arguments
;
1566 int fp2(void *param
, FuncDeclaration
*f
)
1567 { Param2
*p
= (Param2
*)param
;
1569 Expressions
*arguments
= p
->arguments
;
1572 if (f
!= m
->lastf
) // skip duplicates
1577 tf
= (TypeFunction
*)f
->type
;
1578 match
= (MATCH
) tf
->callMatch(arguments
);
1579 //printf("match = %d\n", match);
1580 if (match
!= MATCHnomatch
)
1582 if (match
> m
->last
)
1585 if (match
< m
->last
)
1588 /* See if one of the matches overrides the other.
1590 if (m
->lastf
->overrides(f
))
1592 else if (f
->overrides(m
->lastf
))
1614 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
, Expressions
*arguments
)
1618 p
.arguments
= arguments
;
1619 overloadApply(fstart
, &fp2
, &p
);
1623 // Recursive helper function
1625 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
, Expressions
*arguments
)
1631 for (d
= fstart
; d
; d
= next
)
1634 FuncAliasDeclaration
*fa
;
1635 AliasDeclaration
*a
;
1637 fa
= d
->isFuncAliasDeclaration();
1640 overloadResolveX(m
, fa
->funcalias
, arguments
);
1641 next
= fa
->overnext
;
1643 else if ((f
= d
->isFuncDeclaration()) != NULL
)
1647 continue; // skip duplicates
1653 tf
= (TypeFunction
*)f
->type
;
1654 match
= (MATCH
) tf
->callMatch(arguments
);
1655 //printf("match = %d\n", match);
1656 if (match
!= MATCHnomatch
)
1658 if (match
> m
->last
)
1661 if (match
< m
->last
)
1664 /* See if one of the matches overrides the other.
1666 if (m
->lastf
->overrides(f
))
1668 else if (f
->overrides(m
->lastf
))
1687 else if ((a
= d
->isAliasDeclaration()) != NULL
)
1689 Dsymbol
*s
= a
->toAlias();
1690 next
= s
->isDeclaration();
1697 { d
->error("is aliased to a function");
1704 FuncDeclaration
*FuncDeclaration::overloadResolve(Loc loc
, Expressions
*arguments
)
1710 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1714 for (i
= 0; i
< arguments
->dim
; i
++)
1717 arg
= (Expression
*)arguments
->data
[i
];
1719 printf("\t%s: ", arg
->toChars());
1725 memset(&m
, 0, sizeof(m
));
1726 m
.last
= MATCHnomatch
;
1727 overloadResolveX(&m
, this, arguments
);
1729 if (m
.count
== 1) // exactly one match
1741 argExpTypesToCBuffer(&buf
, arguments
, &hgs
);
1744 if (m
.last
== MATCHnomatch
)
1746 tf
= (TypeFunction
*)type
;
1748 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1749 error(loc
, "%s does not match parameter types (%s)",
1750 Argument::argsTypesToChars(tf
->parameters
, tf
->varargs
),
1752 return m
.anyf
; // as long as it's not a FuncAliasDeclaration
1757 TypeFunction
*t1
= (TypeFunction
*)m
.lastf
->type
;
1758 TypeFunction
*t2
= (TypeFunction
*)m
.nextf
->type
;
1760 error(loc
, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1762 m
.lastf
->toPrettyChars(), Argument::argsTypesToChars(t1
->parameters
, t1
->varargs
),
1763 m
.nextf
->toPrettyChars(), Argument::argsTypesToChars(t2
->parameters
, t2
->varargs
));
1765 error(loc
, "overloads %s and %s both match argument list for %s",
1766 m
.lastf
->type
->toChars(),
1767 m
.nextf
->type
->toChars(),
1768 m
.lastf
->toChars());
1775 /********************************
1776 * Labels are in a separate scope, one per function.
1779 LabelDsymbol
*FuncDeclaration::searchLabel(Identifier
*ident
)
1783 labtab
= new DsymbolTable(); // guess we need one
1785 s
= labtab
->lookup(ident
);
1788 s
= new LabelDsymbol(ident
);
1791 return (LabelDsymbol
*)s
;
1793 /****************************************
1794 * If non-static member function that has a 'this' pointer,
1795 * return the aggregate it is a member of.
1796 * Otherwise, return NULL.
1799 AggregateDeclaration
*FuncDeclaration::isThis()
1800 { AggregateDeclaration
*ad
;
1802 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1804 if ((storage_class
& STCstatic
) == 0)
1808 //printf("-FuncDeclaration::isThis() %p\n", ad);
1812 AggregateDeclaration
*FuncDeclaration::isMember2()
1813 { AggregateDeclaration
*ad
;
1815 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1817 for (Dsymbol
*s
= this; s
; s
= s
->parent
)
1819 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1822 { //printf("test4\n");
1826 (!s
->parent
->isTemplateInstance()))
1827 { //printf("test5\n");
1831 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1835 /*****************************************
1836 * Determine lexical level difference from 'this' to nested function 'fd'.
1837 * Error if this cannot call fd.
1840 * -1 increase nesting by 1 (fd is nested within 'this')
1841 * >0 decrease nesting by number
1844 int FuncDeclaration::getLevel(Loc loc
, FuncDeclaration
*fd
)
1849 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1850 fdparent
= fd
->toParent2();
1851 if (fdparent
== this)
1855 while (fd
!= s
&& fdparent
!= s
->toParent2())
1857 //printf("\ts = '%s'\n", s->toChars());
1858 FuncDeclaration
*thisfd
= s
->isFuncDeclaration();
1860 { if (!thisfd
->isNested() && !thisfd
->vthis
)
1865 ClassDeclaration
*thiscd
= s
->isClassDeclaration();
1867 { if (!thiscd
->isNested())
1881 error(loc
, "cannot access frame of function %s", fd
->toChars());
1885 void FuncDeclaration::appendExp(Expression
*e
)
1888 s
= new ExpStatement(0, e
);
1892 void FuncDeclaration::appendState(Statement
*s
)
1893 { CompoundStatement
*cs
;
1898 a
= new Statements();
1899 fbody
= new CompoundStatement(0, a
);
1901 cs
= fbody
->isCompoundStatement();
1902 cs
->statements
->push(s
);
1906 int FuncDeclaration::isMain()
1908 return ident
== Id::main
&&
1909 linkage
!= LINKc
&& !isMember() && !isNested();
1912 int FuncDeclaration::isWinMain()
1914 return ident
== Id::WinMain
&&
1915 linkage
!= LINKc
&& !isMember();
1918 int FuncDeclaration::isDllMain()
1920 return ident
== Id::DllMain
&&
1921 linkage
!= LINKc
&& !isMember();
1924 int FuncDeclaration::isExport()
1926 return protection
== PROTexport
;
1929 int FuncDeclaration::isImportedSymbol()
1931 //printf("isImportedSymbol()\n");
1932 //printf("protection = %d\n", protection);
1933 return (protection
== PROTexport
) && !fbody
;
1936 // Determine if function goes into virtual function pointer table
1938 int FuncDeclaration::isVirtual()
1941 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1942 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
1943 printf("result is %d\n",
1945 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1946 toParent()->isClassDeclaration());
1948 return isMember() &&
1949 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1950 toParent()->isClassDeclaration();
1953 int FuncDeclaration::isAbstract()
1955 return storage_class
& STCabstract
;
1958 int FuncDeclaration::isCodeseg()
1960 return TRUE
; // functions are always in the code segment
1963 // Determine if function needs
1964 // a static frame pointer to its lexically enclosing function
1966 int FuncDeclaration::isNested()
1969 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
1970 //printf("\ttoParent() = '%s'\n", toParent()->toChars());
1971 return ((storage_class
& STCstatic
) == 0) &&
1972 (toParent2()->isFuncDeclaration() != NULL
);
1975 int FuncDeclaration::needThis()
1977 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
1978 int i
= isThis() != NULL
;
1979 //printf("\t%d\n", i);
1980 if (!i
&& isFuncAliasDeclaration())
1981 i
= ((FuncAliasDeclaration
*)this)->funcalias
->needThis();
1985 int FuncDeclaration::addPreInvariant()
1987 AggregateDeclaration
*ad
= isThis();
1989 //ad->isClassDeclaration() &&
1990 global
.params
.useInvariants
&&
1991 (protection
== PROTpublic
|| protection
== PROTexport
) &&
1995 int FuncDeclaration::addPostInvariant()
1997 AggregateDeclaration
*ad
= isThis();
2000 //ad->isClassDeclaration() &&
2001 global
.params
.useInvariants
&&
2002 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2006 /**********************************
2007 * Generate a FuncDeclaration for a runtime library function.
2010 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, char *name
,
2011 Type
*t1
, Type
*t2
, Type
*t3
)
2013 return genCfunc(treturn
, Lexer::idPool(name
), t1
, t2
, t3
);
2016 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, Identifier
*id
,
2017 Type
*t1
, Type
*t2
, Type
*t3
)
2019 FuncDeclaration
*fd
;
2022 static DsymbolTable
*st
= NULL
;
2024 //printf("genCfunc(name = '%s')\n", id->toChars());
2025 //printf("treturn\n\t"); treturn->print();
2027 // See if already in table
2029 st
= new DsymbolTable();
2033 fd
= s
->isFuncDeclaration();
2035 assert(fd
->type
->nextOf()->equals(treturn
));
2039 Arguments
* args
= 0;
2041 args
= new Arguments
;
2042 args
->push(new Argument(STCin
,t1
,0,0));
2045 args
->push(new Argument(STCin
,t2
,0,0));
2047 args
->push(new Argument(STCin
,t3
,0,0));
2051 tf
= new TypeFunction(args
, treturn
, 0, LINKc
);
2052 fd
= new FuncDeclaration(0, 0, id
, STCstatic
, tf
);
2053 fd
->protection
= PROTpublic
;
2054 fd
->linkage
= LINKc
;
2061 char *FuncDeclaration::kind()
2065 /*******************************
2066 * Look at all the variables in this function that are referenced
2067 * by nested functions, and determine if a closure needs to be
2072 int FuncDeclaration::needsClosure()
2074 /* Need a closure for all the closureVars[] if any of the
2075 * closureVars[] are accessed by a
2076 * function that escapes the scope of this function.
2077 * We take the conservative approach and decide that any function that:
2078 * 1) is a virtual function
2079 * 2) has its address taken
2080 * 3) has a parent that escapes
2084 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2085 for (int i
= 0; i
< closureVars
.dim
; i
++)
2086 { VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2087 assert(v
->isVarDeclaration());
2088 //printf("\tv = %s\n", v->toChars());
2090 for (int j
= 0; j
< v
->nestedrefs
.dim
; j
++)
2091 { FuncDeclaration
*f
= (FuncDeclaration
*)v
->nestedrefs
.data
[j
];
2094 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2095 if (f
->isVirtual() || f
->tookAddressOf
)
2096 goto Lyes
; // assume f escapes this function's scope
2098 // Look to see if any parents of f that are below this escape
2099 for (Dsymbol
*s
= f
->parent
; s
!= this; s
= s
->parent
)
2101 f
= s
->isFuncDeclaration();
2102 if (f
&& (f
->isVirtual() || f
->tookAddressOf
))
2110 //printf("\tneeds closure\n");
2115 /****************************** FuncAliasDeclaration ************************/
2117 // Used as a way to import a set of functions from another scope into this one.
2119 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration
*funcalias
)
2120 : FuncDeclaration(funcalias
->loc
, funcalias
->endloc
, funcalias
->ident
,
2121 (enum STC
)funcalias
->storage_class
, funcalias
->type
)
2123 assert(funcalias
!= this);
2124 this->funcalias
= funcalias
;
2127 char *FuncAliasDeclaration::kind()
2129 return "function alias";
2133 /****************************** FuncLiteralDeclaration ************************/
2135 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc
, Loc endloc
, Type
*type
,
2136 enum TOK tok
, ForeachStatement
*fes
)
2137 : FuncDeclaration(loc
, endloc
, NULL
, STCundefined
, type
)
2142 id
= "__foreachbody";
2143 else if (tok
== TOKdelegate
)
2146 id
= "__funcliteral";
2147 this->ident
= Identifier::generateId(id
);
2150 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2153 Dsymbol
*FuncLiteralDeclaration::syntaxCopy(Dsymbol
*s
)
2155 FuncLiteralDeclaration
*f
;
2157 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2159 f
= (FuncLiteralDeclaration
*)s
;
2161 f
= new FuncLiteralDeclaration(loc
, endloc
, type
->syntaxCopy(), tok
, fes
);
2162 FuncDeclaration::syntaxCopy(f
);
2166 int FuncLiteralDeclaration::isNested()
2168 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2169 return (tok
== TOKdelegate
);
2172 char *FuncLiteralDeclaration::kind()
2174 // GCC requires the (char*) casts
2175 return (tok
== TOKdelegate
) ? (char*)"delegate" : (char*)"function";
2178 void FuncLiteralDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2180 static Identifier
*idfunc
;
2181 static Identifier
*iddel
;
2184 idfunc
= new Identifier("function", 0);
2186 iddel
= new Identifier("delegate", 0);
2188 type
->toCBuffer(buf
, ((tok
== TOKdelegate
) ? iddel
: idfunc
), hgs
);
2189 bodyToCBuffer(buf
, hgs
);
2193 /********************************* CtorDeclaration ****************************/
2195 CtorDeclaration::CtorDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2196 : FuncDeclaration(loc
, endloc
, Id::ctor
, STCundefined
, NULL
)
2198 this->arguments
= arguments
;
2199 this->varargs
= varargs
;
2200 //printf("CtorDeclaration() %s\n", toChars());
2203 Dsymbol
*CtorDeclaration::syntaxCopy(Dsymbol
*s
)
2207 f
= new CtorDeclaration(loc
, endloc
, NULL
, varargs
);
2210 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
2211 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
2212 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
2213 assert(!fthrows
); // deprecated
2215 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2220 void CtorDeclaration::semantic(Scope
*sc
)
2222 ClassDeclaration
*cd
;
2225 //printf("CtorDeclaration::semantic()\n");
2230 sc
->stc
&= ~STCstatic
; // not a static constructor
2232 parent
= sc
->parent
;
2233 Dsymbol
*parent
= toParent();
2234 cd
= parent
->isClassDeclaration();
2237 error("constructors are only for class definitions");
2242 tret
= cd
->type
; //->referenceTo();
2244 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
2246 VarDeclaration
*vd
= (VarDeclaration
*) cd
->fields
.data
[i
];
2250 arguments
= new Arguments();
2251 Argument
*a
= new Argument(vd
->storage_class
, vd
->type
, vd
->ident
, 0);
2252 // BUG: We don't really want these arguments in scope...
2255 Statement
*assign
= new ExpStatement(loc
, new AssignExp(loc
,
2256 new DotIdExp(loc
, new ThisExp(loc
), a
->ident
),
2257 new IdentifierExp(loc
, a
->ident
)));
2259 fbody
= new CompoundStatement(loc
, assign
, fbody
);
2266 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2268 sc
->flags
|= SCOPEctor
;
2269 type
= type
->semantic(loc
, sc
);
2270 sc
->flags
&= ~SCOPEctor
;
2274 // to the function body
2280 s
= new ReturnStatement(0, e
);
2281 fbody
= new CompoundStatement(0, fbody
, s
);
2284 FuncDeclaration::semantic(sc
);
2288 // See if it's the default constructor
2289 if (cd
&& varargs
== 0 && Argument::dim(arguments
) == 0)
2290 cd
->defaultCtor
= this;
2293 char *CtorDeclaration::kind()
2295 return "constructor";
2298 char *CtorDeclaration::toChars()
2303 int CtorDeclaration::isVirtual()
2308 int CtorDeclaration::addPreInvariant()
2313 int CtorDeclaration::addPostInvariant()
2315 return (vthis
&& global
.params
.useInvariants
);
2319 void CtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2321 buf
->writestring("this");
2322 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2323 bodyToCBuffer(buf
, hgs
);
2326 /********************************* DtorDeclaration ****************************/
2328 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
)
2329 : FuncDeclaration(loc
, endloc
, Id::dtor
, STCundefined
, NULL
)
2333 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2334 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2338 Dsymbol
*DtorDeclaration::syntaxCopy(Dsymbol
*s
)
2341 DtorDeclaration
*dd
= new DtorDeclaration(loc
, endloc
, ident
);
2342 return FuncDeclaration::syntaxCopy(dd
);
2346 void DtorDeclaration::semantic(Scope
*sc
)
2348 ClassDeclaration
*cd
;
2350 parent
= sc
->parent
;
2351 Dsymbol
*parent
= toParent();
2352 cd
= parent
->isClassDeclaration();
2355 error("destructors only are for class definitions");
2358 cd
->dtors
.push(this);
2359 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2362 sc
->stc
&= ~STCstatic
; // not a static destructor
2363 sc
->linkage
= LINKd
;
2365 FuncDeclaration::semantic(sc
);
2370 int DtorDeclaration::overloadInsert(Dsymbol
*s
)
2372 return FALSE
; // cannot overload destructors
2375 int DtorDeclaration::addPreInvariant()
2377 return (vthis
&& global
.params
.useInvariants
);
2380 int DtorDeclaration::addPostInvariant()
2385 int DtorDeclaration::isVirtual()
2387 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2388 * but doing so will require recompiling everything.
2393 return FuncDeclaration::isVirtual();
2397 void DtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2401 buf
->writestring("~this()");
2402 bodyToCBuffer(buf
, hgs
);
2405 /********************************* StaticCtorDeclaration ****************************/
2407 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
)
2408 : FuncDeclaration(loc
, endloc
,
2409 Identifier::generateId("_staticCtor"), STCstatic
, NULL
)
2413 Dsymbol
*StaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
2415 StaticCtorDeclaration
*scd
;
2418 scd
= new StaticCtorDeclaration(loc
, endloc
);
2419 return FuncDeclaration::syntaxCopy(scd
);
2423 void StaticCtorDeclaration::semantic(Scope
*sc
)
2425 //printf("StaticCtorDeclaration::semantic()\n");
2427 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2429 FuncDeclaration::semantic(sc
);
2431 // We're going to need ModuleInfo
2432 Module
*m
= getModule();
2436 { m
->needmoduleinfo
= 1;
2438 m
->strictlyneedmoduleinfo
= 1;
2443 AggregateDeclaration
*StaticCtorDeclaration::isThis()
2448 int StaticCtorDeclaration::isStaticConstructor()
2453 int StaticCtorDeclaration::isVirtual()
2458 int StaticCtorDeclaration::addPreInvariant()
2463 int StaticCtorDeclaration::addPostInvariant()
2468 void StaticCtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2471 { buf
->writestring("static this();\n");
2474 buf
->writestring("static this()");
2475 bodyToCBuffer(buf
, hgs
);
2478 /********************************* StaticDtorDeclaration ****************************/
2480 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
)
2481 : FuncDeclaration(loc
, endloc
,
2482 Identifier::generateId("_staticDtor"), STCstatic
, NULL
)
2486 Dsymbol
*StaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
2488 StaticDtorDeclaration
*sdd
;
2491 sdd
= new StaticDtorDeclaration(loc
, endloc
);
2492 return FuncDeclaration::syntaxCopy(sdd
);
2496 void StaticDtorDeclaration::semantic(Scope
*sc
)
2498 ClassDeclaration
*cd
;
2501 cd
= sc
->scopesym
->isClassDeclaration();
2505 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2507 FuncDeclaration::semantic(sc
);
2509 // We're going to need ModuleInfo
2510 Module
*m
= getModule();
2514 { m
->needmoduleinfo
= 1;
2516 m
->strictlyneedmoduleinfo
= 1;
2521 AggregateDeclaration
*StaticDtorDeclaration::isThis()
2526 int StaticDtorDeclaration::isStaticDestructor()
2531 int StaticDtorDeclaration::isVirtual()
2536 int StaticDtorDeclaration::addPreInvariant()
2541 int StaticDtorDeclaration::addPostInvariant()
2546 void StaticDtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2550 buf
->writestring("static ~this()");
2551 bodyToCBuffer(buf
, hgs
);
2554 /********************************* InvariantDeclaration ****************************/
2556 InvariantDeclaration::InvariantDeclaration(Loc loc
, Loc endloc
)
2557 : FuncDeclaration(loc
, endloc
, Id::classInvariant
, STCundefined
, NULL
)
2561 Dsymbol
*InvariantDeclaration::syntaxCopy(Dsymbol
*s
)
2563 InvariantDeclaration
*id
;
2566 id
= new InvariantDeclaration(loc
, endloc
);
2567 FuncDeclaration::syntaxCopy(id
);
2572 void InvariantDeclaration::semantic(Scope
*sc
)
2574 AggregateDeclaration
*ad
;
2577 parent
= sc
->parent
;
2578 Dsymbol
*parent
= toParent();
2579 ad
= parent
->isAggregateDeclaration();
2582 error("invariants only are for struct/union/class definitions");
2585 else if (ad
->inv
&& ad
->inv
!= this)
2587 error("more than one invariant for %s", ad
->toChars());
2590 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2593 sc
->stc
&= ~STCstatic
; // not a static invariant
2595 sc
->linkage
= LINKd
;
2597 FuncDeclaration::semantic(sc
);
2602 int InvariantDeclaration::isVirtual()
2607 int InvariantDeclaration::addPreInvariant()
2612 int InvariantDeclaration::addPostInvariant()
2617 void InvariantDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2621 buf
->writestring("invariant");
2622 bodyToCBuffer(buf
, hgs
);
2626 /********************************* UnitTestDeclaration ****************************/
2628 /*******************************
2629 * Generate unique unittest function Id so we can have multiple
2630 * instances per module.
2633 static Identifier
*unitTestId()
2636 char buffer
[10 + sizeof(n
)*3 + 1];
2638 sprintf(buffer
,"__unittest%d", n
);
2640 return Lexer::idPool(buffer
);
2643 UnitTestDeclaration::UnitTestDeclaration(Loc loc
, Loc endloc
)
2644 : FuncDeclaration(loc
, endloc
, unitTestId(), STCundefined
, NULL
)
2648 Dsymbol
*UnitTestDeclaration::syntaxCopy(Dsymbol
*s
)
2650 UnitTestDeclaration
*utd
;
2653 utd
= new UnitTestDeclaration(loc
, endloc
);
2654 return FuncDeclaration::syntaxCopy(utd
);
2658 void UnitTestDeclaration::semantic(Scope
*sc
)
2660 if (global
.params
.useUnitTests
)
2664 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2665 FuncDeclaration::semantic(sc
);
2668 // We're going to need ModuleInfo even if the unit tests are not
2669 // compiled in, because other modules may import this module and refer
2670 // to this ModuleInfo.
2671 Module
*m
= getModule();
2675 m
->needmoduleinfo
= 1;
2678 AggregateDeclaration
*UnitTestDeclaration::isThis()
2683 int UnitTestDeclaration::isVirtual()
2688 int UnitTestDeclaration::addPreInvariant()
2693 int UnitTestDeclaration::addPostInvariant()
2698 void UnitTestDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2702 buf
->writestring("unittest");
2703 bodyToCBuffer(buf
, hgs
);
2706 /********************************* NewDeclaration ****************************/
2708 NewDeclaration::NewDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2709 : FuncDeclaration(loc
, endloc
, Id::classNew
, STCstatic
, NULL
)
2711 this->arguments
= arguments
;
2712 this->varargs
= varargs
;
2715 Dsymbol
*NewDeclaration::syntaxCopy(Dsymbol
*s
)
2719 f
= new NewDeclaration(loc
, endloc
, NULL
, varargs
);
2721 FuncDeclaration::syntaxCopy(f
);
2723 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2729 void NewDeclaration::semantic(Scope
*sc
)
2731 ClassDeclaration
*cd
;
2734 //printf("NewDeclaration::semantic()\n");
2736 parent
= sc
->parent
;
2737 Dsymbol
*parent
= toParent();
2738 cd
= parent
->isClassDeclaration();
2739 if (!cd
&& !parent
->isStructDeclaration())
2741 error("new allocators only are for class or struct definitions");
2743 tret
= Type::tvoid
->pointerTo();
2744 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2746 type
= type
->semantic(loc
, sc
);
2747 assert(type
->ty
== Tfunction
);
2749 // Check that there is at least one argument of type uint
2750 TypeFunction
*tf
= (TypeFunction
*)type
;
2751 if (Argument::dim(tf
->parameters
) < 1)
2753 error("at least one argument of type uint expected");
2757 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2758 if (!a
->type
->equals(Type::tuns32
) &&
2759 (! global
.params
.isX86_64
|| !a
->type
->equals(Type::tuns64
)))
2760 error("first argument must be type uint, not %s", a
->type
->toChars());
2763 FuncDeclaration::semantic(sc
);
2766 char *NewDeclaration::kind()
2771 int NewDeclaration::isVirtual()
2776 int NewDeclaration::addPreInvariant()
2781 int NewDeclaration::addPostInvariant()
2786 void NewDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2788 buf
->writestring("new");
2789 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2790 bodyToCBuffer(buf
, hgs
);
2794 /********************************* DeleteDeclaration ****************************/
2796 DeleteDeclaration::DeleteDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
)
2797 : FuncDeclaration(loc
, endloc
, Id::classDelete
, STCstatic
, NULL
)
2799 this->arguments
= arguments
;
2802 Dsymbol
*DeleteDeclaration::syntaxCopy(Dsymbol
*s
)
2804 DeleteDeclaration
*f
;
2806 f
= new DeleteDeclaration(loc
, endloc
, NULL
);
2808 FuncDeclaration::syntaxCopy(f
);
2810 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2816 void DeleteDeclaration::semantic(Scope
*sc
)
2818 ClassDeclaration
*cd
;
2820 //printf("DeleteDeclaration::semantic()\n");
2822 parent
= sc
->parent
;
2823 Dsymbol
*parent
= toParent();
2824 cd
= parent
->isClassDeclaration();
2825 if (!cd
&& !parent
->isStructDeclaration())
2827 error("new allocators only are for class or struct definitions");
2829 type
= new TypeFunction(arguments
, Type::tvoid
, 0, LINKd
);
2831 type
= type
->semantic(loc
, sc
);
2832 assert(type
->ty
== Tfunction
);
2834 // Check that there is only one argument of type void*
2835 TypeFunction
*tf
= (TypeFunction
*)type
;
2836 if (Argument::dim(tf
->parameters
) != 1)
2838 error("one argument of type void* expected");
2842 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2843 if (!a
->type
->equals(Type::tvoid
->pointerTo()))
2844 error("one argument of type void* expected, not %s", a
->type
->toChars());
2847 FuncDeclaration::semantic(sc
);
2850 char *DeleteDeclaration::kind()
2852 return "deallocator";
2855 int DeleteDeclaration::isDelete()
2860 int DeleteDeclaration::isVirtual()
2865 int DeleteDeclaration::addPreInvariant()
2870 int DeleteDeclaration::addPostInvariant()
2875 void DeleteDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2877 buf
->writestring("delete");
2878 Argument::argsToCBuffer(buf
, hgs
, arguments
, 0);
2879 bodyToCBuffer(buf
, hgs
);