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
;
77 inferRetType
= (type
&& type
->nextOf() == NULL
);
83 builtin
= BUILTINunknown
;
87 Dsymbol
*FuncDeclaration::syntaxCopy(Dsymbol
*s
)
91 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
93 f
= (FuncDeclaration
*)s
;
95 f
= new FuncDeclaration(loc
, endloc
, ident
, (enum STC
) storage_class
, type
->syntaxCopy());
97 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
98 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
99 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
100 assert(!fthrows
); // deprecated
105 // Do the semantic analysis on the external interface to the function.
107 void FuncDeclaration::semantic(Scope
*sc
)
109 StructDeclaration
*sd
;
110 ClassDeclaration
*cd
;
111 InterfaceDeclaration
*id
;
114 printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc
, this, toPrettyChars(), sc
->linkage
);
115 if (isFuncLiteralDeclaration())
116 printf("\tFuncLiteralDeclaration()\n");
117 printf("sc->parent = %s\n", sc
->parent
->toChars());
118 printf("type: %p, %s\n", type
, type
->toChars());
121 storage_class
|= sc
->stc
;
122 //printf("function storage_class = x%x\n", storage_class);
127 if (!type
->deco
&& type
->nextOf())
130 /* Apply const and invariant storage class
131 * to the function type
133 type
= type
->semantic(loc
, sc
);
134 if (storage_class
& STCinvariant
)
135 { // Don't use toInvariant(), as that will do a merge()
136 type
= type
->makeInvariant();
137 type
->deco
= type
->merge()->deco
;
139 else if (storage_class
& STCconst
)
141 if (!type
->isInvariant())
142 { // Don't use toConst(), as that will do a merge()
143 type
= type
->makeConst();
144 type
->deco
= type
->merge()->deco
;
148 if (storage_class
& (STCconst
| STCinvariant
))
150 /* Apply const and invariant storage class
151 * to the function's return type
153 Type
*tn
= type
->nextOf();
154 if (storage_class
& STCconst
)
155 tn
= tn
->makeConst();
156 if (storage_class
& STCinvariant
)
157 tn
= tn
->makeInvariant();
158 ((TypeNext
*)type
)->next
= tn
;
161 type
= type
->semantic(loc
, sc
);
165 if (type
->ty
!= Tfunction
)
167 error("%s must be a function", toChars());
170 f
= (TypeFunction
*)(type
);
172 size_t nparams
= Argument::dim(f
->parameters
);
174 linkage
= sc
->linkage
;
177 //parent = sc->scopesym;
180 protection
= sc
->protection
;
182 attributes
->append(sc
->attributes
);
184 attributes
= sc
->attributes
;
185 Dsymbol
*parent
= toParent();
187 if (isAuto() || isScope())
188 error("functions cannot be scope or auto");
190 if (isAbstract() && !isVirtual())
191 error("non-virtual functions cannot be abstract");
193 if ((f
->isConst() || f
->isInvariant()) && !isThis())
194 error("without 'this' cannot be const/invariant");
196 if (isAbstract() && isFinal())
197 error("cannot be both final and abstract");
199 if (isAbstract() && fbody
)
200 error("abstract functions cannot have bodies");
204 if (isStaticConstructor() || isStaticDestructor())
206 if (!isStatic() || type
->nextOf()->ty
!= Tvoid
)
207 error("static constructors / destructors must be static void");
208 if (f
->arguments
&& f
->arguments
->dim
)
209 error("static constructors / destructors must have empty parameter list");
210 // BUG: check for invalid storage classes
215 AggregateDeclaration
*ad
;
217 ad
= parent
->isAggregateDeclaration();
219 ad
->methods
.push(this);
221 sd
= parent
->isStructDeclaration();
224 // Verify no constructors, destructors, etc.
225 if (isCtorDeclaration()
226 //||isDtorDeclaration()
227 //|| isInvariantDeclaration()
228 //|| isUnitTestDeclaration()
231 error("special member functions not allowed for %ss", sd
->kind());
236 sd
->inv
= isInvariantDeclaration();
239 sd
->aggNew
= isNewDeclaration();
244 error("multiple delete's for struct %s", sd
->toChars());
245 sd
->aggDelete
= (DeleteDeclaration
*)(this);
250 id
= parent
->isInterfaceDeclaration();
253 storage_class
|= STCabstract
;
255 if (isCtorDeclaration() ||
256 isPostBlitDeclaration() ||
257 isDtorDeclaration() ||
258 isInvariantDeclaration() ||
259 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
260 error("special function not allowed in interface %s", id
->toChars());
262 error("function body is not abstract in interface %s", id
->toChars());
265 cd
= parent
->isClassDeclaration();
268 CtorDeclaration
*ctor
;
269 DtorDeclaration
*dtor
;
270 InvariantDeclaration
*inv
;
272 if (isCtorDeclaration())
274 // ctor = (CtorDeclaration *)this;
281 dtor
= isDtorDeclaration();
285 error("multiple destructors for class %s", cd
->toChars());
289 inv
= isInvariantDeclaration();
295 if (isNewDeclaration())
298 cd
->aggNew
= (NewDeclaration
*)(this);
304 error("multiple delete's for class %s", cd
->toChars());
305 cd
->aggDelete
= (DeleteDeclaration
*)(this);
309 if (storage_class
& STCabstract
)
312 // if static function, do not put in vtbl[]
315 //printf("\tnot virtual\n");
319 // Find index of existing function in vtbl[] to override
320 vi
= findVtblIndex(&cd
->vtbl
, cd
->baseClass
? cd
->baseClass
->vtbl
.dim
: 0);
324 /* Didn't find one, so
325 * This is an 'introducing' function which gets a new
326 * slot in the vtbl[].
329 // Verify this doesn't override previous final function
331 { Dsymbol
*s
= cd
->baseClass
->search(loc
, ident
, 0);
334 FuncDeclaration
*f
= s
->isFuncDeclaration();
335 f
= f
->overloadExactMatch(type
);
336 if (f
&& f
->isFinal() && f
->prot() != PROTprivate
)
337 error("cannot override final function %s", f
->toPrettyChars());
343 cd
->vtblFinal
.push(this);
347 // Append to end of vtbl[]
348 //printf("\tintroducing function\n");
357 case -2: // can't determine because of fwd refs
358 cd
->sizeok
= 2; // can't finish due to forward reference
362 { FuncDeclaration
*fdv
= (FuncDeclaration
*)cd
->vtbl
.data
[vi
];
363 // This function is covariant with fdv
365 error("cannot override final function %s", fdv
->toPrettyChars());
367 if (!isOverride() && (global
.params
.warnings
|| sc
->module
->isDltFile
))
368 error("overrides base class function %s, but is not marked with 'override'", fdv
->toPrettyChars());
370 if (fdv
->toParent() == parent
)
372 // If both are mixins, then error.
373 // If either is not, the one that is not overrides
375 if (fdv
->parent
->isClassDeclaration())
377 if (!this->parent
->isClassDeclaration()
379 && !isDtorDeclaration()
381 && !isPostBlitDeclaration()
383 error("multiple overrides of same function");
385 cd
->vtbl
.data
[vi
] = (void *)this;
388 /* This works by whenever this function is called,
389 * it actually returns tintro, which gets dynamically
390 * cast to type. But we know that tintro is a base
391 * of type, so we could optimize it by not doing a
392 * dynamic cast, but just subtracting the isBaseOf()
393 * offset if the value is != null.
397 tintro
= fdv
->tintro
;
398 else if (!type
->equals(fdv
->type
))
400 /* Only need to have a tintro if the vptr
403 target_ptrdiff_t offset
;
404 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
413 /* Go through all the interface bases.
414 * If this function is covariant with any members of those interface
415 * functions, set the tintro.
417 for (int i
= 0; i
< cd
->interfaces_dim
; i
++)
419 BaseClass
*b
= cd
->interfaces
[i
];
420 vi
= findVtblIndex(&b
->base
->vtbl
, b
->base
->vtbl
.dim
);
427 cd
->sizeok
= 2; // can't finish due to forward reference
431 { FuncDeclaration
*fdv
= (FuncDeclaration
*)b
->base
->vtbl
.data
[vi
];
436 else if (!type
->equals(fdv
->type
))
438 /* Only need to have a tintro if the vptr
441 target_ptrdiff_t offset
;
442 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
448 else if (type
->nextOf()->ty
== Tclass
)
449 { ClassDeclaration
*cdn
= ((TypeClass
*)type
->nextOf())->sym
;
450 if (cdn
&& cdn
->sizeok
!= 1)
458 if (tintro
&& !tintro
->equals(ti
))
460 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
469 if (introducing
&& isOverride())
471 error("does not override any function");
476 else if (isOverride() && !parent
->isTemplateInstance())
477 error("override only applies to class member functions");
479 /* Do not allow template instances to add virtual functions
484 TemplateInstance
*ti
= parent
->isTemplateInstance();
487 // Take care of nested templates
490 TemplateInstance
*ti2
= ti
->tempdecl
->parent
->isTemplateInstance();
496 // If it's a member template
497 ClassDeclaration
*cd
= ti
->tempdecl
->isClassMember();
500 error("cannot use template to add virtual function to class '%s'", cd
->toChars());
507 // Check parameters to see if they are either () or (char[][] args)
515 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
516 if (arg0
->type
->ty
!= Tarray
||
517 arg0
->type
->nextOf()->ty
!= Tarray
||
518 arg0
->type
->nextOf()->nextOf()->ty
!= Tchar
||
519 arg0
->storageClass
& (STCout
| STCref
| STClazy
))
528 if (f
->nextOf()->ty
!= Tint32
&& f
->nextOf()->ty
!= Tvoid
)
529 error("must return int or void, not %s", f
->nextOf()->toChars());
533 error("parameters must be main() or main(char[][] args)");
537 if (ident
== Id::assign
&& (sd
|| cd
))
538 { // Disallow identity assignment operator.
542 { if (f
->varargs
== 1)
547 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
548 Type
*t0
= arg0
->type
->toBasetype();
549 Type
*tb
= sd
? sd
->type
: cd
->type
;
550 if (arg0
->type
->implicitConvTo(tb
) ||
551 (sd
&& t0
->ty
== Tpointer
&& t0
->nextOf()->implicitConvTo(tb
))
556 Argument
*arg1
= Argument::getNth(f
->parameters
, 1);
557 if (arg1
->defaultArg
)
564 /* Save scope for possible later use (if we need the
565 * function internals)
567 scope
= new Scope(*sc
);
574 sd
->hasIdentityAssign
= 1; // don't need to generate it
577 error("identity assignment operator overload is illegal");
580 void FuncDeclaration::semantic2(Scope
*sc
)
584 // Do the semantic analysis on the internals of the function.
586 void FuncDeclaration::semantic3(Scope
*sc
)
588 AggregateDeclaration
*ad
;
589 VarDeclaration
*argptr
= NULL
;
590 VarDeclaration
*_arguments
= NULL
;
596 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
599 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
601 //{ static int x; if (++x == 2) *(char*)0=0; }
602 //printf("\tlinkage = %d\n", sc->linkage);
604 //printf(" sc->incontract = %d\n", sc->incontract);
609 if (!type
|| type
->ty
!= Tfunction
)
611 f
= (TypeFunction
*)(type
);
613 // Check the 'throws' clause
617 for (i
= 0; i
< fthrows
->dim
; i
++)
619 Type
*t
= (Type
*)fthrows
->data
[i
];
621 t
= t
->semantic(loc
, sc
);
622 if (!t
->isClassHandle())
623 error("can only throw classes, not %s", t
->toChars());
627 if (fbody
|| frequire
)
629 /* Symbol table into which we place parameters and nested functions,
630 * solely to diagnose name collisions.
632 localsymtab
= new DsymbolTable();
634 // Establish function scope
635 ScopeDsymbol
*ss
= new ScopeDsymbol();
636 ss
->parent
= sc
->scopesym
;
637 Scope
*sc2
= sc
->push(ss
);
642 sc2
->scontinue
= NULL
;
645 sc2
->linkage
= LINKd
;
646 sc2
->stc
&= ~(STCauto
| STCscope
| STCstatic
| STCabstract
| STCdeprecated
| STCconst
| STCfinal
| STCinvariant
| STCtls
);
647 sc2
->attributes
= NULL
;
648 sc2
->protection
= PROTpublic
;
649 sc2
->explicitProtection
= 0;
650 sc2
->structalign
= 8;
660 if (isFuncLiteralDeclaration() && isNested())
662 error("literals cannot be class members");
667 assert(!isNested()); // can't be both member and nested
669 Type
*thandle
= ad
->handle
;
670 if (storage_class
& STCconst
|| type
->isConst())
672 if (thandle
->ty
== Tclass
)
673 thandle
= thandle
->constOf();
675 { assert(thandle
->ty
== Tpointer
);
676 thandle
= thandle
->nextOf()->constOf()->pointerTo();
679 else if (storage_class
& STCinvariant
|| type
->isInvariant())
681 if (thandle
->ty
== Tclass
)
682 thandle
= thandle
->invariantOf();
684 { assert(thandle
->ty
== Tpointer
);
685 thandle
= thandle
->nextOf()->invariantOf()->pointerTo();
688 v
= new ThisDeclaration(thandle
);
689 v
->storage_class
|= STCparameter
;
699 /* The 'this' for a nested function is the link to the
700 * enclosing function's stack frame.
701 * Note that nested functions and member functions are disjoint.
703 VarDeclaration
*v
= new ThisDeclaration(Type::tvoid
->pointerTo());
704 v
->storage_class
|= STCparameter
;
712 // Declare hidden variable _arguments[] and _argptr
716 if (f
->linkage
== LINKd
)
717 { // Declare _arguments[]
719 v_arguments
= new VarDeclaration(0, Type::typeinfotypelist
->type
, Id::_arguments_typeinfo
, NULL
);
720 v_arguments
->storage_class
= STCparameter
;
721 v_arguments
->semantic(sc2
);
722 sc2
->insert(v_arguments
);
723 v_arguments
->parent
= this;
725 //t = Type::typeinfo->type->constOf()->arrayOf();
726 t
= Type::typeinfo
->type
->arrayOf();
727 _arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
728 _arguments
->semantic(sc2
);
729 sc2
->insert(_arguments
);
730 _arguments
->parent
= this;
732 t
= Type::typeinfo
->type
->arrayOf();
733 v_arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
734 v_arguments
->storage_class
= STCparameter
| STCin
;
735 v_arguments
->semantic(sc2
);
736 sc2
->insert(v_arguments
);
737 v_arguments
->parent
= this;
740 if (f
->linkage
== LINKd
|| (parameters
&& parameters
->dim
))
743 t
= d_gcc_builtin_va_list_d_type
;
745 t
= Type::tvoid
->pointerTo();
747 argptr
= new VarDeclaration(0, t
, Id::_argptr
, NULL
);
748 argptr
->semantic(sc2
);
750 argptr
->parent
= this;
754 // Propagate storage class from tuple parameters to their element-parameters.
757 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
758 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
760 if (arg
->type
->ty
== Ttuple
)
761 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
762 size_t dim
= Argument::dim(t
->arguments
);
763 for (size_t j
= 0; j
< dim
; j
++)
764 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
765 narg
->storageClass
= arg
->storageClass
;
771 /* Declare all the function parameters as variables
772 * and install them in parameters[]
774 size_t nparams
= Argument::dim(f
->parameters
);
776 { /* parameters[] has all the tuples removed, as the back end
777 * doesn't know about tuples
779 parameters
= new Dsymbols();
780 parameters
->reserve(nparams
);
781 for (size_t i
= 0; i
< nparams
; i
++)
783 Argument
*arg
= Argument::getNth(f
->parameters
, i
);
784 Identifier
*id
= arg
->ident
;
787 /* Generate identifier for un-named parameter,
788 * because we need it later on.
791 buf
.printf("_param_%"PRIuSIZE
, i
);
792 char *name
= (char *)buf
.extractData();
793 id
= new Identifier(name
, TOKidentifier
);
796 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, id
, NULL
);
797 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
798 v
->storage_class
|= STCparameter
;
799 if (f
->varargs
== 2 && i
+ 1 == nparams
)
800 v
->storage_class
|= STCvariadic
;
801 v
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STClazy
| STCfinal
| STCconst
| STCinvariant
| STCnodtor
);
804 error("parameter %s.%s is already defined", toChars(), v
->toChars());
807 localsymtab
->insert(v
);
812 // Declare the tuple symbols and put them in the symbol table,
813 // but not in parameters[].
816 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
817 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
820 continue; // never used, so ignore
821 if (arg
->type
->ty
== Ttuple
)
822 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
823 size_t dim
= Argument::dim(t
->arguments
);
824 Objects
*exps
= new Objects();
826 for (size_t j
= 0; j
< dim
; j
++)
827 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
829 VarDeclaration
*v
= sc2
->search(0, narg
->ident
, NULL
)->isVarDeclaration();
831 Expression
*e
= new VarExp(v
->loc
, v
);
832 exps
->data
[j
] = (void *)e
;
835 TupleDeclaration
*v
= new TupleDeclaration(loc
, arg
->ident
, exps
);
836 //printf("declaring tuple %s\n", v->toChars());
839 error("parameter %s.%s is already defined", toChars(), v
->toChars());
840 localsymtab
->insert(v
);
846 /* Do the semantic analysis on the [in] preconditions and
847 * [out] postconditions.
852 { /* frequire is composed of the [in] contracts
854 // BUG: need to error if accessing out parameters
855 // BUG: need to treat parameters as const
856 // BUG: need to disallow returns and throws
857 // BUG: verify that all in and ref parameters are read
858 frequire
= frequire
->semantic(sc2
);
859 labtab
= NULL
; // so body can't refer to labels
862 if (fensure
|| addPostInvariant())
863 { /* fensure is composed of the [out] contracts
865 ScopeDsymbol
*sym
= new ScopeDsymbol();
866 sym
->parent
= sc2
->scopesym
;
867 sc2
= sc2
->push(sym
);
869 assert(type
->nextOf());
870 if (type
->nextOf()->ty
== Tvoid
)
873 error("void functions have no result");
878 outId
= Id::result
; // provide a default
882 { // Declare result variable
889 v
= new VarDeclaration(loc
, type
->nextOf(), outId
, NULL
);
895 error("out result %s is already defined", v
->toChars());
899 // vresult gets initialized with the function return value
900 // in ReturnStatement::semantic()
903 // BUG: need to treat parameters as const
904 // BUG: need to disallow returns and throws
906 { fensure
= fensure
->semantic(sc2
);
907 labtab
= NULL
; // so body can't refer to labels
910 if (!global
.params
.useOut
)
911 { fensure
= NULL
; // discard
915 // Postcondition invariant
916 if (addPostInvariant())
918 Expression
*e
= NULL
;
919 if (isCtorDeclaration())
921 // Call invariant directly only if it exists
922 InvariantDeclaration
*inv
= ad
->inv
;
923 ClassDeclaration
*cd
= ad
->isClassDeclaration();
934 e
= new DsymbolExp(0, inv
);
935 e
= new CallExp(0, e
);
936 e
= e
->semantic(sc2
);
940 { // Call invariant virtually
941 ThisExp
*v
= new ThisExp(0);
942 v
->type
= vthis
->type
;
943 e
= new AssertExp(0, v
);
947 ExpStatement
*s
= new ExpStatement(0, e
);
949 fensure
= new CompoundStatement(0, s
, fensure
);
956 { returnLabel
= new LabelDsymbol(Id::returnLabel
);
957 LabelStatement
*ls
= new LabelStatement(0, Id::returnLabel
, fensure
);
958 ls
->isReturnLabel
= 1;
959 returnLabel
->statement
= ls
;
967 { ClassDeclaration
*cd
= isClassMember();
969 /* If this is a class constructor
971 if (isCtorDeclaration() && cd
)
973 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
974 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
980 if (inferRetType
|| f
->retStyle() != RETstack
)
983 fbody
= fbody
->semantic(sc2
);
986 { // If no return type inferred yet, then infer a void
989 ((TypeFunction
*)type
)->next
= Type::tvoid
;
990 type
= type
->semantic(loc
, sc
);
992 f
= (TypeFunction
*)type
;
995 if (isStaticCtorDeclaration())
996 { /* It's a static constructor. Ensure that all
997 * ctor consts were initialized.
1000 Dsymbol
*p
= toParent();
1001 ScopeDsymbol
*ad
= p
->isScopeDsymbol();
1004 error("static constructor can only be member of struct/class/module, not %s %s", p
->kind(), p
->toChars());
1008 for (int i
= 0; i
< ad
->members
->dim
; i
++)
1009 { Dsymbol
*s
= (Dsymbol
*)ad
->members
->data
[i
];
1011 s
->checkCtorConstInit();
1016 if (isCtorDeclaration() && cd
)
1018 //printf("callSuper = x%x\n", sc2->callSuper);
1020 // Verify that all the ctorinit fields got initialized
1021 // Also check that non-null members got set
1022 if (!(sc2
->callSuper
& CSXthis_ctor
))
1024 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
1025 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
1027 if (v
->ctorinit
== 0)
1029 if (v
->isCtorinit())
1030 error("missing initializer for final field %s", v
->toChars());
1031 else if (v
->requirePointerInit
&&
1032 (v
->type
->ty
== Tclass
|| v
->type
->ty
== Tpointer
))
1033 error("missing initializer for non-null field %s", v
->toChars());
1038 if (!(sc2
->callSuper
& CSXany_ctor
) &&
1039 cd
->baseClass
&& cd
->baseClass
->ctor
)
1043 // Insert implicit super() at start of fbody
1044 Expression
*e1
= new SuperExp(0);
1045 Expression
*e
= new CallExp(0, e1
);
1047 unsigned errors
= global
.errors
;
1049 e
= e
->semantic(sc2
);
1051 if (errors
!= global
.errors
)
1052 error("no match for implicit super() call in constructor");
1054 Statement
*s
= new ExpStatement(0, e
);
1055 fbody
= new CompoundStatement(0, s
, fbody
);
1059 { // For foreach(){} body, append a return 0;
1060 Expression
*e
= new IntegerExp(0);
1061 Statement
*s
= new ReturnStatement(0, e
);
1062 fbody
= new CompoundStatement(0, fbody
, s
);
1063 assert(!returnLabel
);
1065 else if (!hasReturnExp
&& type
->nextOf()->ty
!= Tvoid
)
1066 error("expected to return a value of type %s", type
->nextOf()->toChars());
1067 else if (!inlineAsm
)
1069 int offend
= fbody
? fbody
->blockExit() & BEfallthru
: TRUE
;
1070 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1072 if (type
->nextOf()->ty
== Tvoid
)
1074 if (offend
&& isMain())
1075 { // Add a return 0; statement
1076 Statement
*s
= new ReturnStatement(0, new IntegerExp(0));
1077 fbody
= new CompoundStatement(0, fbody
, s
);
1085 if (global
.params
.warnings
)
1086 { fprintf(stdmsg
, "warning - ");
1087 error("no return at end of function");
1090 if (global
.params
.useAssert
&&
1091 !global
.params
.useInline
)
1092 { /* Add an assert(0, msg); where the missing return
1098 new StringExp(loc
, "missing return expression")
1102 e
= new HaltExp(endloc
);
1103 e
= new CommaExp(0, e
, type
->nextOf()->defaultInit());
1104 e
= e
->semantic(sc2
);
1105 Statement
*s
= new ExpStatement(0, e
);
1106 fbody
= new CompoundStatement(0, fbody
, s
);
1113 Statements
*a
= new Statements();
1115 // Merge in initialization of 'out' parameters
1117 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1119 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1120 if (v
->storage_class
& STCout
)
1123 ExpInitializer
*ie
= v
->init
->isExpInitializer();
1125 a
->push(new ExpStatement(0, ie
->exp
));
1131 { // Initialize _argptr to point past non-variadic arg
1133 // Handled in FuncDeclaration::toObjFile
1135 v_argptr
->init
= new VoidInitializer(loc
);
1139 Type
*t
= argptr
->type
;
1143 e1
= new VarExp(0, argptr
);
1144 if (parameters
&& parameters
->dim
)
1145 p
= (VarDeclaration
*)parameters
->data
[parameters
->dim
- 1];
1147 p
= v_arguments
; // last parameter is _arguments[]
1148 offset
= p
->type
->size();
1149 offset
= (offset
+ 3) & ~3; // assume stack aligns on 4
1150 e
= new SymOffExp(0, p
, offset
);
1151 e
= new AssignExp(0, e1
, e
);
1153 a
->push(new ExpStatement(0, e
));
1160 v_arguments_var
= _arguments
;
1161 v_arguments_var
->init
= new VoidInitializer(loc
);
1163 /* Advance to elements[] member of TypeInfo_Tuple with:
1164 * _arguments = v_arguments.elements;
1166 Expression
*e
= new VarExp(0, v_arguments
);
1167 e
= new DotIdExp(0, e
, Id::elements
);
1168 Expression
*e1
= new VarExp(0, _arguments
);
1169 e
= new AssignExp(0, e1
, e
);
1170 e
->op
= TOKconstruct
;
1171 e
= e
->semantic(sc
);
1172 a
->push(new ExpStatement(0, e
));
1175 // Merge contracts together with body into one compound statement
1178 if (frequire
&& global
.params
.useIn
)
1179 { frequire
->incontract
= 1;
1183 if (frequire
&& global
.params
.useIn
)
1187 // Precondition invariant
1188 if (addPreInvariant())
1190 Expression
*e
= NULL
;
1191 if (isDtorDeclaration())
1193 // Call invariant directly only if it exists
1194 InvariantDeclaration
*inv
= ad
->inv
;
1195 ClassDeclaration
*cd
= ad
->isClassDeclaration();
1206 e
= new DsymbolExp(0, inv
);
1207 e
= new CallExp(0, e
);
1208 e
= e
->semantic(sc2
);
1212 { // Call invariant virtually
1213 ThisExp
*v
= new ThisExp(0);
1214 v
->type
= vthis
->type
;
1215 Expression
*se
= new StringExp(0, "null this");
1216 se
= se
->semantic(sc
);
1217 se
->type
= Type::tchar
->arrayOf();
1218 e
= new AssertExp(loc
, v
, se
);
1222 ExpStatement
*s
= new ExpStatement(0, e
);
1232 a
->push(returnLabel
->statement
);
1234 if (type
->nextOf()->ty
!= Tvoid
)
1236 // Create: return vresult;
1238 Expression
*e
= new VarExp(0, vresult
);
1240 { e
= e
->implicitCastTo(sc
, tintro
->nextOf());
1241 e
= e
->semantic(sc
);
1243 ReturnStatement
*s
= new ReturnStatement(0, e
);
1248 fbody
= new CompoundStatement(0, a
);
1250 /* Append destructor calls for parameters as finally blocks.
1253 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1255 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1257 if (v
->storage_class
& (STCref
| STCout
))
1260 /* Don't do this for static arrays, since static
1261 * arrays are called by reference. Remove this
1262 * when we change them to call by value.
1264 if (v
->type
->toBasetype()->ty
== Tsarray
)
1267 Expression
*e
= v
->callAutoDtor(sc
);
1269 { Statement
*s
= new ExpStatement(0, e
);
1270 s
= s
->semantic(sc
);
1271 if (fbody
->blockExit() == BEfallthru
)
1272 fbody
= new CompoundStatement(0, fbody
, s
);
1274 fbody
= new TryFinallyStatement(0, fbody
, s
);
1286 void FuncDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1288 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1290 type
->toCBuffer(buf
, ident
, hgs
);
1291 bodyToCBuffer(buf
, hgs
);
1295 void FuncDeclaration::bodyToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1298 (!hgs
->hdrgen
|| hgs
->tpltMember
|| canInline(1,1))
1304 { buf
->writestring("in");
1306 frequire
->toCBuffer(buf
, hgs
);
1311 { buf
->writestring("out");
1313 { buf
->writebyte('(');
1314 buf
->writestring(outId
->toChars());
1315 buf
->writebyte(')');
1318 fensure
->toCBuffer(buf
, hgs
);
1321 if (frequire
|| fensure
)
1322 { buf
->writestring("body");
1326 buf
->writebyte('{');
1328 fbody
->toCBuffer(buf
, hgs
);
1329 buf
->writebyte('}');
1333 { buf
->writeByte(';');
1338 /****************************************************
1339 * Determine if 'this' overrides fd.
1340 * Return !=0 if it does.
1343 int FuncDeclaration::overrides(FuncDeclaration
*fd
)
1346 if (fd
->ident
== ident
)
1348 int cov
= type
->covariant(fd
->type
);
1350 { ClassDeclaration
*cd1
= toParent()->isClassDeclaration();
1351 ClassDeclaration
*cd2
= fd
->toParent()->isClassDeclaration();
1353 if (cd1
&& cd2
&& cd2
->isBaseOf(cd1
, NULL
))
1360 /*************************************************
1361 * Find index of function in vtbl[0..dim] that
1362 * this function overrides.
1364 * -1 didn't find one
1365 * -2 can't determine because of forward references
1368 int FuncDeclaration::findVtblIndex(Array
*vtbl
, int dim
)
1370 for (int vi
= 0; vi
< dim
; vi
++)
1372 FuncDeclaration
*fdv
= ((Dsymbol
*)vtbl
->data
[vi
])->isFuncDeclaration();
1373 if (fdv
&& fdv
->ident
== ident
)
1375 int cov
= type
->covariant(fdv
->type
);
1376 //printf("\tbaseclass cov = %d\n", cov);
1379 case 0: // types are distinct
1387 //fdv->type->print();
1388 //printf("%s %s\n", type->deco, fdv->type->deco);
1389 error("of type %s overrides but is not covariant with %s of type %s",
1390 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
1394 return -2; // forward references
1404 /****************************************************
1405 * Overload this FuncDeclaration with the new one f.
1406 * Return !=0 if successful; i.e. no conflict.
1409 int FuncDeclaration::overloadInsert(Dsymbol
*s
)
1412 AliasDeclaration
*a
;
1414 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1415 a
= s
->isAliasDeclaration();
1419 return overnext
->overloadInsert(a
);
1420 if (!a
->aliassym
&& a
->type
->ty
!= Tident
&& a
->type
->ty
!= Tinstance
)
1422 //printf("\ta = '%s'\n", a->type->toChars());
1426 //printf("\ttrue: no conflict\n");
1429 f
= s
->isFuncDeclaration();
1434 /* Disable this check because:
1436 * semantic() isn't run yet on foo(), so the const hasn't been
1440 { printf("type = %s\n", type
->toChars());
1441 printf("f->type = %s\n", f
->type
->toChars());
1443 if (type
&& f
->type
&& // can be NULL for overloaded constructors
1444 f
->type
->covariant(type
) &&
1445 f
->type
->mod
== type
->mod
&&
1446 !isFuncAliasDeclaration())
1448 //printf("\tfalse: conflict %s\n", kind());
1454 return overnext
->overloadInsert(f
);
1456 //printf("\ttrue: no conflict\n");
1460 /***************************************************
1461 * Visit each overloaded function in turn, and call
1462 * (*fp)(param, f) on it.
1463 * Exit when no more, or (*fp)(param, f) returns 1.
1469 int overloadApply(FuncDeclaration
*fstart
,
1470 int (*fp
)(void *, FuncDeclaration
*),
1477 for (d
= fstart
; d
; d
= next
)
1478 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1482 if (overloadApply(fa
->funcalias
, fp
, param
))
1484 next
= fa
->overnext
;
1488 AliasDeclaration
*a
= d
->isAliasDeclaration();
1492 Dsymbol
*s
= a
->toAlias();
1493 next
= s
->isDeclaration();
1501 f
= d
->isFuncDeclaration();
1503 { d
->error("is aliased to a function");
1504 break; // BUG: should print error message?
1506 if ((*fp
)(param
, f
))
1516 /********************************************
1517 * If there are no overloads of function f, return that function,
1518 * otherwise return NULL.
1521 static int fpunique(void *param
, FuncDeclaration
*f
)
1522 { FuncDeclaration
**pf
= (FuncDeclaration
**)param
;
1526 return 1; // ambiguous, done
1534 FuncDeclaration
*FuncDeclaration::isUnique()
1535 { FuncDeclaration
*result
= NULL
;
1537 overloadApply(this, &fpunique
, &result
);
1541 /********************************************
1542 * Find function in overload list that exactly matches t.
1547 Type
*t
; // type to match
1548 FuncDeclaration
*f
; // return value
1551 int fp1(void *param
, FuncDeclaration
*f
)
1552 { Param1
*p
= (Param1
*)param
;
1555 if (t
->equals(f
->type
))
1561 /* Allow covariant matches, if it's just a const conversion
1562 * of the return type
1564 if (t
->ty
== Tfunction
)
1565 { TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1566 if (tf
->covariant(t
) == 1 &&
1567 tf
->nextOf()->implicitConvTo(t
->nextOf()) >= MATCHconst
)
1577 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1582 overloadApply(this, &fp1
, &p
);
1587 /********************************************
1588 * Decide which function matches the arguments best.
1595 Expressions
*arguments
;
1598 int fp2(void *param
, FuncDeclaration
*f
)
1599 { Param2
*p
= (Param2
*)param
;
1601 Expressions
*arguments
= p
->arguments
;
1604 if (f
!= m
->lastf
) // skip duplicates
1607 TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1608 match
= (MATCH
) tf
->callMatch(f
->needThis() ? p
->ethis
: NULL
, arguments
);
1609 //printf("match = %d\n", match);
1610 if (match
!= MATCHnomatch
)
1612 if (match
> m
->last
)
1615 if (match
< m
->last
)
1618 /* See if one of the matches overrides the other.
1620 if (m
->lastf
->overrides(f
))
1622 else if (f
->overrides(m
->lastf
))
1625 /* Try to disambiguate using template-style partial ordering rules.
1626 * In essence, if f() and g() are ambiguous, if f() can call g(),
1627 * but g() cannot call f(), then pick f().
1628 * This is because f() is "more specialized."
1631 MATCH c1
= f
->leastAsSpecialized(m
->lastf
);
1632 MATCH c2
= m
->lastf
->leastAsSpecialized(f
);
1657 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
,
1658 Expression
*ethis
, Expressions
*arguments
)
1663 p
.arguments
= arguments
;
1664 overloadApply(fstart
, &fp2
, &p
);
1668 FuncDeclaration
*FuncDeclaration::overloadResolve(Loc loc
, Expression
*ethis
, Expressions
*arguments
, int flags
)
1674 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1678 for (i
= 0; i
< arguments
->dim
; i
++)
1681 arg
= (Expression
*)arguments
->data
[i
];
1683 printf("\t%s: ", arg
->toChars());
1689 memset(&m
, 0, sizeof(m
));
1690 m
.last
= MATCHnomatch
;
1691 overloadResolveX(&m
, this, ethis
, arguments
);
1693 if (m
.count
== 1) // exactly one match
1705 argExpTypesToCBuffer(&buf
, arguments
, &hgs
);
1708 if (m
.last
== MATCHnomatch
)
1710 if (flags
& 1) // if do not print error messages
1711 return NULL
; // no match
1713 tf
= (TypeFunction
*)type
;
1715 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1716 error(loc
, "%s does not match parameter types (%s)",
1717 Argument::argsTypesToChars(tf
->parameters
, tf
->varargs
),
1719 return m
.anyf
; // as long as it's not a FuncAliasDeclaration
1724 TypeFunction
*t1
= (TypeFunction
*)m
.lastf
->type
;
1725 TypeFunction
*t2
= (TypeFunction
*)m
.nextf
->type
;
1727 error(loc
, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1729 m
.lastf
->toPrettyChars(), Argument::argsTypesToChars(t1
->parameters
, t1
->varargs
),
1730 m
.nextf
->toPrettyChars(), Argument::argsTypesToChars(t2
->parameters
, t2
->varargs
));
1732 error(loc
, "overloads %s and %s both match argument list for %s",
1733 m
.lastf
->type
->toChars(),
1734 m
.nextf
->type
->toChars(),
1735 m
.lastf
->toChars());
1742 /*************************************
1743 * Determine partial specialization order of 'this' vs g.
1744 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1746 * match 'this' is at least as specialized as g
1747 * 0 g is more specialized than 'this'
1750 MATCH
FuncDeclaration::leastAsSpecialized(FuncDeclaration
*g
)
1752 #define LOG_LEASTAS 0
1755 printf("%s.leastAsSpecialized(%s)\n", toChars(), g
->toChars());
1758 /* This works by calling g() with f()'s parameters, and
1759 * if that is possible, then f() is at least as specialized
1763 TypeFunction
*tf
= (TypeFunction
*)type
;
1764 TypeFunction
*tg
= (TypeFunction
*)g
->type
;
1765 size_t nfparams
= Argument::dim(tf
->parameters
);
1766 size_t ngparams
= Argument::dim(tg
->parameters
);
1767 MATCH match
= MATCHexact
;
1769 /* If both functions have a 'this' pointer, and the mods are not
1770 * the same and g's is not const, then this is less specialized.
1772 if (needThis() && g
->needThis())
1774 if (tf
->mod
!= tg
->mod
)
1776 if (tg
->mod
== MODconst
)
1779 return MATCHnomatch
;
1783 /* Create a dummy array of arguments out of the parameters to f()
1786 args
.setDim(nfparams
);
1787 for (int u
= 0; u
< nfparams
; u
++)
1789 Argument
*p
= Argument::getNth(tf
->parameters
, u
);
1790 Expression
*e
= p
->type
->defaultInit();
1794 MATCH m
= (MATCH
) tg
->callMatch(NULL
, &args
);
1797 /* A variadic template is less specialized than a
1800 if (tf
->varargs
&& !tg
->varargs
)
1801 goto L1
; // less specialized
1804 printf(" matches %d, so is least as specialized\n", m
);
1810 printf(" doesn't match, so is not as specialized\n");
1812 return MATCHnomatch
;
1815 /********************************
1816 * Labels are in a separate scope, one per function.
1819 LabelDsymbol
*FuncDeclaration::searchLabel(Identifier
*ident
)
1823 labtab
= new DsymbolTable(); // guess we need one
1825 s
= labtab
->lookup(ident
);
1828 s
= new LabelDsymbol(ident
);
1831 return (LabelDsymbol
*)s
;
1834 /****************************************
1835 * If non-static member function that has a 'this' pointer,
1836 * return the aggregate it is a member of.
1837 * Otherwise, return NULL.
1840 AggregateDeclaration
*FuncDeclaration::isThis()
1841 { AggregateDeclaration
*ad
;
1843 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1845 if ((storage_class
& STCstatic
) == 0)
1849 //printf("-FuncDeclaration::isThis() %p\n", ad);
1853 AggregateDeclaration
*FuncDeclaration::isMember2()
1854 { AggregateDeclaration
*ad
;
1856 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1858 for (Dsymbol
*s
= this; s
; s
= s
->parent
)
1860 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1863 { //printf("test4\n");
1867 (!s
->parent
->isTemplateInstance()))
1868 { //printf("test5\n");
1872 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1876 /*****************************************
1877 * Determine lexical level difference from 'this' to nested function 'fd'.
1878 * Error if this cannot call fd.
1881 * -1 increase nesting by 1 (fd is nested within 'this')
1882 * >0 decrease nesting by number
1885 int FuncDeclaration::getLevel(Loc loc
, FuncDeclaration
*fd
)
1890 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1891 fdparent
= fd
->toParent2();
1892 if (fdparent
== this)
1896 while (fd
!= s
&& fdparent
!= s
->toParent2())
1898 //printf("\ts = '%s'\n", s->toChars());
1899 FuncDeclaration
*thisfd
= s
->isFuncDeclaration();
1901 { if (!thisfd
->isNested() && !thisfd
->vthis
)
1906 ClassDeclaration
*thiscd
= s
->isClassDeclaration();
1908 { if (!thiscd
->isNested())
1922 error(loc
, "cannot access frame of function %s", fd
->toChars());
1926 void FuncDeclaration::appendExp(Expression
*e
)
1929 s
= new ExpStatement(0, e
);
1933 void FuncDeclaration::appendState(Statement
*s
)
1934 { CompoundStatement
*cs
;
1939 a
= new Statements();
1940 fbody
= new CompoundStatement(0, a
);
1942 cs
= fbody
->isCompoundStatement();
1943 cs
->statements
->push(s
);
1947 int FuncDeclaration::isMain()
1949 return ident
== Id::main
&&
1950 linkage
!= LINKc
&& !isMember() && !isNested();
1953 int FuncDeclaration::isWinMain()
1955 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1957 int x
= ident
== Id::WinMain
&&
1958 linkage
!= LINKc
&& !isMember();
1959 printf("%s\n", x
? "yes" : "no");
1962 return ident
== Id::WinMain
&&
1963 linkage
!= LINKc
&& !isMember();
1967 int FuncDeclaration::isDllMain()
1969 return ident
== Id::DllMain
&&
1970 linkage
!= LINKc
&& !isMember();
1973 int FuncDeclaration::isExport()
1975 return protection
== PROTexport
;
1978 int FuncDeclaration::isImportedSymbol()
1980 //printf("isImportedSymbol()\n");
1981 //printf("protection = %d\n", protection);
1982 return (protection
== PROTexport
) && !fbody
;
1985 // Determine if function goes into virtual function pointer table
1987 int FuncDeclaration::isVirtual()
1990 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1991 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
1992 printf("result is %d\n",
1994 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1995 toParent()->isClassDeclaration());
1997 return isMember() &&
1998 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1999 toParent()->isClassDeclaration();
2002 int FuncDeclaration::isFinal()
2005 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2006 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
2007 printf("result is %d\n",
2009 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
2010 toParent()->isClassDeclaration());
2012 ClassDeclaration
*cd
;
2013 return isMember() &&
2014 (Declaration::isFinal() ||
2015 ((cd
= toParent()->isClassDeclaration()) != NULL
&& cd
->storage_class
& STCfinal
));
2018 int FuncDeclaration::isAbstract()
2020 return storage_class
& STCabstract
;
2023 int FuncDeclaration::isCodeseg()
2025 return TRUE
; // functions are always in the code segment
2028 int FuncDeclaration::isOverloadable()
2030 return 1; // functions can be overloaded
2033 // Determine if function needs
2034 // a static frame pointer to its lexically enclosing function
2036 int FuncDeclaration::isNested()
2039 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2040 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2041 return ((storage_class
& STCstatic
) == 0) &&
2042 (toParent2()->isFuncDeclaration() != NULL
);
2045 int FuncDeclaration::needThis()
2047 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2048 int i
= isThis() != NULL
;
2049 //printf("\t%d\n", i);
2050 if (!i
&& isFuncAliasDeclaration())
2051 i
= ((FuncAliasDeclaration
*)this)->funcalias
->needThis();
2055 int FuncDeclaration::addPreInvariant()
2057 AggregateDeclaration
*ad
= isThis();
2059 //ad->isClassDeclaration() &&
2060 global
.params
.useInvariants
&&
2061 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2063 ident
!= Id::cpctor
);
2066 int FuncDeclaration::addPostInvariant()
2068 AggregateDeclaration
*ad
= isThis();
2071 //ad->isClassDeclaration() &&
2072 global
.params
.useInvariants
&&
2073 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2075 ident
!= Id::cpctor
);
2078 /**********************************
2079 * Generate a FuncDeclaration for a runtime library function.
2082 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, char *name
,
2083 Type
*t1
, Type
*t2
, Type
*t3
)
2085 return genCfunc(treturn
, Lexer::idPool(name
), t1
, t2
, t3
);
2088 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, Identifier
*id
,
2089 Type
*t1
, Type
*t2
, Type
*t3
)
2091 FuncDeclaration
*fd
;
2094 static DsymbolTable
*st
= NULL
;
2096 //printf("genCfunc(name = '%s')\n", id->toChars());
2097 //printf("treturn\n\t"); treturn->print();
2099 // See if already in table
2101 st
= new DsymbolTable();
2105 fd
= s
->isFuncDeclaration();
2107 assert(fd
->type
->nextOf()->equals(treturn
));
2111 Arguments
* args
= 0;
2113 args
= new Arguments
;
2114 args
->push(new Argument(STCin
,t1
,0,0));
2117 args
->push(new Argument(STCin
,t2
,0,0));
2119 args
->push(new Argument(STCin
,t3
,0,0));
2123 tf
= new TypeFunction(args
, treturn
, 0, LINKc
);
2124 fd
= new FuncDeclaration(0, 0, id
, STCstatic
, tf
);
2125 fd
->protection
= PROTpublic
;
2126 fd
->linkage
= LINKc
;
2133 char *FuncDeclaration::kind()
2138 /*******************************
2139 * Look at all the variables in this function that are referenced
2140 * by nested functions, and determine if a closure needs to be
2145 int FuncDeclaration::needsClosure()
2147 /* Need a closure for all the closureVars[] if any of the
2148 * closureVars[] are accessed by a
2149 * function that escapes the scope of this function.
2150 * We take the conservative approach and decide that any function that:
2151 * 1) is a virtual function
2152 * 2) has its address taken
2153 * 3) has a parent that escapes
2155 * Note that since a non-virtual function can be called by
2156 * a virtual one, if that non-virtual function accesses a closure
2157 * var, the closure still has to be taken. Hence, we check for isThis()
2158 * instead of isVirtual(). (thanks to David Friedman)
2161 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2162 for (int i
= 0; i
< closureVars
.dim
; i
++)
2163 { VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2164 assert(v
->isVarDeclaration());
2165 //printf("\tv = %s\n", v->toChars());
2167 for (int j
= 0; j
< v
->nestedrefs
.dim
; j
++)
2168 { FuncDeclaration
*f
= (FuncDeclaration
*)v
->nestedrefs
.data
[j
];
2171 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2172 if (f
->isThis() || f
->tookAddressOf
)
2173 goto Lyes
; // assume f escapes this function's scope
2175 // Look to see if any parents of f that are below this escape
2176 for (Dsymbol
*s
= f
->parent
; s
!= this; s
= s
->parent
)
2178 f
= s
->isFuncDeclaration();
2179 if (f
&& (f
->isThis() || f
->tookAddressOf
))
2187 //printf("\tneeds closure\n");
2192 /****************************** FuncAliasDeclaration ************************/
2194 // Used as a way to import a set of functions from another scope into this one.
2196 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration
*funcalias
)
2197 : FuncDeclaration(funcalias
->loc
, funcalias
->endloc
, funcalias
->ident
,
2198 (enum STC
)funcalias
->storage_class
, funcalias
->type
)
2200 assert(funcalias
!= this);
2201 this->funcalias
= funcalias
;
2204 char *FuncAliasDeclaration::kind()
2206 return "function alias";
2210 /****************************** FuncLiteralDeclaration ************************/
2212 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc
, Loc endloc
, Type
*type
,
2213 enum TOK tok
, ForeachStatement
*fes
)
2214 : FuncDeclaration(loc
, endloc
, NULL
, STCundefined
, type
)
2219 id
= "__foreachbody";
2220 else if (tok
== TOKdelegate
)
2223 id
= "__funcliteral";
2224 this->ident
= Identifier::generateId(id
);
2227 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2230 Dsymbol
*FuncLiteralDeclaration::syntaxCopy(Dsymbol
*s
)
2232 FuncLiteralDeclaration
*f
;
2234 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2236 f
= (FuncLiteralDeclaration
*)s
;
2238 f
= new FuncLiteralDeclaration(loc
, endloc
, type
->syntaxCopy(), tok
, fes
);
2239 FuncDeclaration::syntaxCopy(f
);
2243 int FuncLiteralDeclaration::isNested()
2245 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2246 return (tok
== TOKdelegate
);
2249 char *FuncLiteralDeclaration::kind()
2251 // GCC requires the (char*) casts
2252 return (tok
== TOKdelegate
) ? (char*)"delegate" : (char*)"function";
2255 void FuncLiteralDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2257 static Identifier
*idfunc
;
2258 static Identifier
*iddel
;
2261 idfunc
= new Identifier("function", 0);
2263 iddel
= new Identifier("delegate", 0);
2265 type
->toCBuffer(buf
, ((tok
== TOKdelegate
) ? iddel
: idfunc
), hgs
);
2266 bodyToCBuffer(buf
, hgs
);
2270 /********************************* CtorDeclaration ****************************/
2272 CtorDeclaration::CtorDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2273 : FuncDeclaration(loc
, endloc
, Id::ctor
, STCundefined
, NULL
)
2275 this->arguments
= arguments
;
2276 this->varargs
= varargs
;
2277 //printf("CtorDeclaration() %s\n", toChars());
2280 Dsymbol
*CtorDeclaration::syntaxCopy(Dsymbol
*s
)
2284 f
= new CtorDeclaration(loc
, endloc
, NULL
, varargs
);
2287 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
2288 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
2289 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
2290 assert(!fthrows
); // deprecated
2292 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2297 void CtorDeclaration::semantic(Scope
*sc
)
2299 ClassDeclaration
*cd
;
2302 //printf("CtorDeclaration::semantic()\n");
2307 sc
->stc
&= ~STCstatic
; // not a static constructor
2309 parent
= sc
->parent
;
2310 Dsymbol
*parent
= toParent();
2311 cd
= parent
->isClassDeclaration();
2314 error("constructors are only for class definitions");
2319 tret
= cd
->type
; //->referenceTo();
2321 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
2323 VarDeclaration
*vd
= (VarDeclaration
*) cd
->fields
.data
[i
];
2324 if (vd
->storage_class
& STCinject
)
2327 arguments
= new Arguments();
2328 Argument
*a
= new Argument(vd
->storage_class
, vd
->type
, vd
->ident
, 0);
2329 // BUG: We don't really want these arguments in scope...
2332 Statement
*assign
= new ExpStatement(loc
, new AssignExp(loc
,
2333 new DotIdExp(loc
, new ThisExp(loc
), a
->ident
),
2334 new IdentifierExp(loc
, a
->ident
)));
2336 fbody
= new CompoundStatement(loc
, assign
, fbody
);
2343 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2345 sc
->flags
|= SCOPEctor
;
2346 type
= type
->semantic(loc
, sc
);
2347 sc
->flags
&= ~SCOPEctor
;
2351 // to the function body
2357 s
= new ReturnStatement(0, e
);
2358 fbody
= new CompoundStatement(0, fbody
, s
);
2361 FuncDeclaration::semantic(sc
);
2365 // See if it's the default constructor
2366 if (cd
&& varargs
== 0 && Argument::dim(arguments
) == 0)
2367 cd
->defaultCtor
= this;
2370 char *CtorDeclaration::kind()
2372 return "constructor";
2375 char *CtorDeclaration::toChars()
2380 int CtorDeclaration::isVirtual()
2385 int CtorDeclaration::addPreInvariant()
2390 int CtorDeclaration::addPostInvariant()
2392 return (vthis
&& global
.params
.useInvariants
);
2396 void CtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2398 buf
->writestring("this");
2399 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2400 bodyToCBuffer(buf
, hgs
);
2403 /********************************* PostBlitDeclaration ****************************/
2405 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
)
2406 : FuncDeclaration(loc
, endloc
, Id::_postblit
, STCundefined
, NULL
)
2410 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2411 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2415 Dsymbol
*PostBlitDeclaration::syntaxCopy(Dsymbol
*s
)
2418 PostBlitDeclaration
*dd
= new PostBlitDeclaration(loc
, endloc
, ident
);
2419 return FuncDeclaration::syntaxCopy(dd
);
2423 void PostBlitDeclaration::semantic(Scope
*sc
)
2425 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2426 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2427 parent
= sc
->parent
;
2428 Dsymbol
*parent
= toParent();
2429 StructDeclaration
*ad
= parent
->isStructDeclaration();
2432 error("post blits are only for struct/union definitions, not %s %s", parent
->kind(), parent
->toChars());
2434 else if (ident
== Id::_postblit
)
2435 ad
->postblits
.push(this);
2436 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2439 sc
->stc
&= ~STCstatic
; // not static
2440 sc
->linkage
= LINKd
;
2442 FuncDeclaration::semantic(sc
);
2447 int PostBlitDeclaration::overloadInsert(Dsymbol
*s
)
2449 return FALSE
; // cannot overload postblits
2452 int PostBlitDeclaration::addPreInvariant()
2457 int PostBlitDeclaration::addPostInvariant()
2459 return (vthis
&& global
.params
.useInvariants
);
2462 int PostBlitDeclaration::isVirtual()
2467 void PostBlitDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2471 buf
->writestring("=this()");
2472 bodyToCBuffer(buf
, hgs
);
2475 /********************************* DtorDeclaration ****************************/
2477 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
)
2478 : FuncDeclaration(loc
, endloc
, Id::dtor
, STCundefined
, NULL
)
2482 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2483 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2487 Dsymbol
*DtorDeclaration::syntaxCopy(Dsymbol
*s
)
2490 DtorDeclaration
*dd
= new DtorDeclaration(loc
, endloc
, ident
);
2491 return FuncDeclaration::syntaxCopy(dd
);
2495 void DtorDeclaration::semantic(Scope
*sc
)
2497 //printf("DtorDeclaration::semantic() %s\n", toChars());
2498 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2499 parent
= sc
->parent
;
2500 Dsymbol
*parent
= toParent();
2501 AggregateDeclaration
*ad
= parent
->isAggregateDeclaration();
2504 error("destructors are only for class/struct/union definitions, not %s %s", parent
->kind(), parent
->toChars());
2506 else if (ident
== Id::dtor
)
2507 ad
->dtors
.push(this);
2508 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2511 sc
->stc
&= ~STCstatic
; // not a static destructor
2512 sc
->linkage
= LINKd
;
2514 FuncDeclaration::semantic(sc
);
2519 int DtorDeclaration::overloadInsert(Dsymbol
*s
)
2521 return FALSE
; // cannot overload destructors
2524 int DtorDeclaration::addPreInvariant()
2526 return (vthis
&& global
.params
.useInvariants
);
2529 int DtorDeclaration::addPostInvariant()
2534 int DtorDeclaration::isVirtual()
2536 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2537 * but doing so will require recompiling everything.
2542 return FuncDeclaration::isVirtual();
2546 void DtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2550 buf
->writestring("~this()");
2551 bodyToCBuffer(buf
, hgs
);
2554 /********************************* StaticCtorDeclaration ****************************/
2556 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
)
2557 : FuncDeclaration(loc
, endloc
,
2558 Identifier::generateId("_staticCtor"), STCstatic
, NULL
)
2562 Dsymbol
*StaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
2564 StaticCtorDeclaration
*scd
;
2567 scd
= new StaticCtorDeclaration(loc
, endloc
);
2568 return FuncDeclaration::syntaxCopy(scd
);
2572 void StaticCtorDeclaration::semantic(Scope
*sc
)
2574 //printf("StaticCtorDeclaration::semantic()\n");
2576 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2578 FuncDeclaration::semantic(sc
);
2580 // We're going to need ModuleInfo
2581 Module
*m
= getModule();
2585 { m
->needmoduleinfo
= 1;
2587 m
->strictlyneedmoduleinfo
= 1;
2592 AggregateDeclaration
*StaticCtorDeclaration::isThis()
2597 int StaticCtorDeclaration::isStaticConstructor()
2602 int StaticCtorDeclaration::isVirtual()
2607 int StaticCtorDeclaration::addPreInvariant()
2612 int StaticCtorDeclaration::addPostInvariant()
2617 void StaticCtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2620 { buf
->writestring("static this();\n");
2623 buf
->writestring("static this()");
2624 bodyToCBuffer(buf
, hgs
);
2627 /********************************* StaticDtorDeclaration ****************************/
2629 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
)
2630 : FuncDeclaration(loc
, endloc
,
2631 Identifier::generateId("_staticDtor"), STCstatic
, NULL
)
2635 Dsymbol
*StaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
2637 StaticDtorDeclaration
*sdd
;
2640 sdd
= new StaticDtorDeclaration(loc
, endloc
);
2641 return FuncDeclaration::syntaxCopy(sdd
);
2645 void StaticDtorDeclaration::semantic(Scope
*sc
)
2647 ClassDeclaration
*cd
;
2650 cd
= sc
->scopesym
->isClassDeclaration();
2654 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2656 FuncDeclaration::semantic(sc
);
2658 // We're going to need ModuleInfo
2659 Module
*m
= getModule();
2663 { m
->needmoduleinfo
= 1;
2665 m
->strictlyneedmoduleinfo
= 1;
2670 AggregateDeclaration
*StaticDtorDeclaration::isThis()
2675 int StaticDtorDeclaration::isStaticDestructor()
2680 int StaticDtorDeclaration::isVirtual()
2685 int StaticDtorDeclaration::addPreInvariant()
2690 int StaticDtorDeclaration::addPostInvariant()
2695 void StaticDtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2699 buf
->writestring("static ~this()");
2700 bodyToCBuffer(buf
, hgs
);
2703 /********************************* InvariantDeclaration ****************************/
2705 InvariantDeclaration::InvariantDeclaration(Loc loc
, Loc endloc
)
2706 : FuncDeclaration(loc
, endloc
, Id::classInvariant
, STCundefined
, NULL
)
2710 Dsymbol
*InvariantDeclaration::syntaxCopy(Dsymbol
*s
)
2712 InvariantDeclaration
*id
;
2715 id
= new InvariantDeclaration(loc
, endloc
);
2716 FuncDeclaration::syntaxCopy(id
);
2721 void InvariantDeclaration::semantic(Scope
*sc
)
2723 AggregateDeclaration
*ad
;
2726 parent
= sc
->parent
;
2727 Dsymbol
*parent
= toParent();
2728 ad
= parent
->isAggregateDeclaration();
2731 error("invariants only are for struct/union/class definitions");
2734 else if (ad
->inv
&& ad
->inv
!= this)
2736 error("more than one invariant for %s", ad
->toChars());
2739 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2742 sc
->stc
&= ~STCstatic
; // not a static invariant
2744 sc
->linkage
= LINKd
;
2746 FuncDeclaration::semantic(sc
);
2751 int InvariantDeclaration::isVirtual()
2756 int InvariantDeclaration::addPreInvariant()
2761 int InvariantDeclaration::addPostInvariant()
2766 void InvariantDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2770 buf
->writestring("invariant");
2771 bodyToCBuffer(buf
, hgs
);
2775 /********************************* UnitTestDeclaration ****************************/
2777 /*******************************
2778 * Generate unique unittest function Id so we can have multiple
2779 * instances per module.
2782 static Identifier
*unitTestId()
2784 return Lexer::uniqueId("__unittest");
2787 UnitTestDeclaration::UnitTestDeclaration(Loc loc
, Loc endloc
)
2788 : FuncDeclaration(loc
, endloc
, unitTestId(), STCundefined
, NULL
)
2792 Dsymbol
*UnitTestDeclaration::syntaxCopy(Dsymbol
*s
)
2794 UnitTestDeclaration
*utd
;
2797 utd
= new UnitTestDeclaration(loc
, endloc
);
2798 return FuncDeclaration::syntaxCopy(utd
);
2802 void UnitTestDeclaration::semantic(Scope
*sc
)
2804 if (global
.params
.useUnitTests
)
2808 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2809 FuncDeclaration::semantic(sc
);
2812 // We're going to need ModuleInfo even if the unit tests are not
2813 // compiled in, because other modules may import this module and refer
2814 // to this ModuleInfo.
2815 Module
*m
= getModule();
2819 m
->needmoduleinfo
= 1;
2822 AggregateDeclaration
*UnitTestDeclaration::isThis()
2827 int UnitTestDeclaration::isVirtual()
2832 int UnitTestDeclaration::addPreInvariant()
2837 int UnitTestDeclaration::addPostInvariant()
2842 void UnitTestDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2846 buf
->writestring("unittest");
2847 bodyToCBuffer(buf
, hgs
);
2850 /********************************* NewDeclaration ****************************/
2852 NewDeclaration::NewDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2853 : FuncDeclaration(loc
, endloc
, Id::classNew
, STCstatic
, NULL
)
2855 this->arguments
= arguments
;
2856 this->varargs
= varargs
;
2859 Dsymbol
*NewDeclaration::syntaxCopy(Dsymbol
*s
)
2863 f
= new NewDeclaration(loc
, endloc
, NULL
, varargs
);
2865 FuncDeclaration::syntaxCopy(f
);
2867 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2873 void NewDeclaration::semantic(Scope
*sc
)
2875 ClassDeclaration
*cd
;
2878 //printf("NewDeclaration::semantic()\n");
2880 parent
= sc
->parent
;
2881 Dsymbol
*parent
= toParent();
2882 cd
= parent
->isClassDeclaration();
2883 if (!cd
&& !parent
->isStructDeclaration())
2885 error("new allocators only are for class or struct definitions");
2887 tret
= Type::tvoid
->pointerTo();
2888 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2890 type
= type
->semantic(loc
, sc
);
2891 assert(type
->ty
== Tfunction
);
2893 // Check that there is at least one argument of type uint
2894 TypeFunction
*tf
= (TypeFunction
*)type
;
2895 if (Argument::dim(tf
->parameters
) < 1)
2897 error("at least one argument of type uint expected");
2901 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2902 if (!a
->type
->equals(Type::tuns32
) &&
2903 (! global
.params
.isX86_64
|| !a
->type
->equals(Type::tuns64
)))
2904 error("first argument must be type uint, not %s", a
->type
->toChars());
2907 FuncDeclaration::semantic(sc
);
2910 char *NewDeclaration::kind()
2915 int NewDeclaration::isVirtual()
2920 int NewDeclaration::addPreInvariant()
2925 int NewDeclaration::addPostInvariant()
2930 void NewDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2932 buf
->writestring("new");
2933 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2934 bodyToCBuffer(buf
, hgs
);
2938 /********************************* DeleteDeclaration ****************************/
2940 DeleteDeclaration::DeleteDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
)
2941 : FuncDeclaration(loc
, endloc
, Id::classDelete
, STCstatic
, NULL
)
2943 this->arguments
= arguments
;
2946 Dsymbol
*DeleteDeclaration::syntaxCopy(Dsymbol
*s
)
2948 DeleteDeclaration
*f
;
2950 f
= new DeleteDeclaration(loc
, endloc
, NULL
);
2952 FuncDeclaration::syntaxCopy(f
);
2954 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2960 void DeleteDeclaration::semantic(Scope
*sc
)
2962 ClassDeclaration
*cd
;
2964 //printf("DeleteDeclaration::semantic()\n");
2966 parent
= sc
->parent
;
2967 Dsymbol
*parent
= toParent();
2968 cd
= parent
->isClassDeclaration();
2969 if (!cd
&& !parent
->isStructDeclaration())
2971 error("new allocators only are for class or struct definitions");
2973 type
= new TypeFunction(arguments
, Type::tvoid
, 0, LINKd
);
2975 type
= type
->semantic(loc
, sc
);
2976 assert(type
->ty
== Tfunction
);
2978 // Check that there is only one argument of type void*
2979 TypeFunction
*tf
= (TypeFunction
*)type
;
2980 if (Argument::dim(tf
->parameters
) != 1)
2982 error("one argument of type void* expected");
2986 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2987 if (!a
->type
->equals(Type::tvoid
->pointerTo()))
2988 error("one argument of type void* expected, not %s", a
->type
->toChars());
2991 FuncDeclaration::semantic(sc
);
2994 char *DeleteDeclaration::kind()
2996 return "deallocator";
2999 int DeleteDeclaration::isDelete()
3004 int DeleteDeclaration::isVirtual()
3009 int DeleteDeclaration::addPreInvariant()
3014 int DeleteDeclaration::addPostInvariant()
3019 void DeleteDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3021 buf
->writestring("delete");
3022 Argument::argsToCBuffer(buf
, hgs
, arguments
, 0);
3023 bodyToCBuffer(buf
, hgs
);