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
))
1035 "missing initializer for non-null field %s",
1042 if (!(sc2
->callSuper
& CSXany_ctor
) &&
1043 cd
->baseClass
&& cd
->baseClass
->ctor
)
1047 // Insert implicit super() at start of fbody
1048 Expression
*e1
= new SuperExp(0);
1049 Expression
*e
= new CallExp(0, e1
);
1051 unsigned errors
= global
.errors
;
1053 e
= e
->semantic(sc2
);
1055 if (errors
!= global
.errors
)
1056 error("no match for implicit super() call in constructor");
1058 Statement
*s
= new ExpStatement(0, e
);
1059 fbody
= new CompoundStatement(0, s
, fbody
);
1063 { // For foreach(){} body, append a return 0;
1064 Expression
*e
= new IntegerExp(0);
1065 Statement
*s
= new ReturnStatement(0, e
);
1066 fbody
= new CompoundStatement(0, fbody
, s
);
1067 assert(!returnLabel
);
1069 else if (!hasReturnExp
&& type
->nextOf()->ty
!= Tvoid
)
1070 error("expected to return a value of type %s", type
->nextOf()->toChars());
1071 else if (!inlineAsm
)
1073 int offend
= fbody
? fbody
->blockExit() & BEfallthru
: TRUE
;
1074 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1076 if (type
->nextOf()->ty
== Tvoid
)
1078 if (offend
&& isMain())
1079 { // Add a return 0; statement
1080 Statement
*s
= new ReturnStatement(0, new IntegerExp(0));
1081 fbody
= new CompoundStatement(0, fbody
, s
);
1089 if (global
.params
.warnings
)
1090 { fprintf(stdmsg
, "warning - ");
1091 error("no return at end of function");
1094 if (global
.params
.useAssert
&&
1095 !global
.params
.useInline
)
1096 { /* Add an assert(0, msg); where the missing return
1102 new StringExp(loc
, "missing return expression")
1106 e
= new HaltExp(endloc
);
1107 e
= new CommaExp(0, e
, type
->nextOf()->defaultInit());
1108 e
= e
->semantic(sc2
);
1109 Statement
*s
= new ExpStatement(0, e
);
1110 fbody
= new CompoundStatement(0, fbody
, s
);
1117 Statements
*a
= new Statements();
1119 // Merge in initialization of 'out' parameters
1121 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1123 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1124 if (v
->storage_class
& STCout
)
1127 ExpInitializer
*ie
= v
->init
->isExpInitializer();
1129 a
->push(new ExpStatement(0, ie
->exp
));
1135 { // Initialize _argptr to point past non-variadic arg
1137 // Handled in FuncDeclaration::toObjFile
1139 v_argptr
->init
= new VoidInitializer(loc
);
1143 Type
*t
= argptr
->type
;
1147 e1
= new VarExp(0, argptr
);
1148 if (parameters
&& parameters
->dim
)
1149 p
= (VarDeclaration
*)parameters
->data
[parameters
->dim
- 1];
1151 p
= v_arguments
; // last parameter is _arguments[]
1152 offset
= p
->type
->size();
1153 offset
= (offset
+ 3) & ~3; // assume stack aligns on 4
1154 e
= new SymOffExp(0, p
, offset
);
1155 e
= new AssignExp(0, e1
, e
);
1157 a
->push(new ExpStatement(0, e
));
1164 v_arguments_var
= _arguments
;
1165 v_arguments_var
->init
= new VoidInitializer(loc
);
1167 /* Advance to elements[] member of TypeInfo_Tuple with:
1168 * _arguments = v_arguments.elements;
1170 Expression
*e
= new VarExp(0, v_arguments
);
1171 e
= new DotIdExp(0, e
, Id::elements
);
1172 Expression
*e1
= new VarExp(0, _arguments
);
1173 e
= new AssignExp(0, e1
, e
);
1174 e
->op
= TOKconstruct
;
1175 e
= e
->semantic(sc
);
1176 a
->push(new ExpStatement(0, e
));
1179 // Merge contracts together with body into one compound statement
1182 if (frequire
&& global
.params
.useIn
)
1183 { frequire
->incontract
= 1;
1187 if (frequire
&& global
.params
.useIn
)
1191 // Precondition invariant
1192 if (addPreInvariant())
1194 Expression
*e
= NULL
;
1195 if (isDtorDeclaration())
1197 // Call invariant directly only if it exists
1198 InvariantDeclaration
*inv
= ad
->inv
;
1199 ClassDeclaration
*cd
= ad
->isClassDeclaration();
1210 e
= new DsymbolExp(0, inv
);
1211 e
= new CallExp(0, e
);
1212 e
= e
->semantic(sc2
);
1216 { // Call invariant virtually
1217 ThisExp
*v
= new ThisExp(0);
1218 v
->type
= vthis
->type
;
1219 Expression
*se
= new StringExp(0, "null this");
1220 se
= se
->semantic(sc
);
1221 se
->type
= Type::tchar
->arrayOf();
1222 e
= new AssertExp(loc
, v
, se
);
1226 ExpStatement
*s
= new ExpStatement(0, e
);
1236 a
->push(returnLabel
->statement
);
1238 if (type
->nextOf()->ty
!= Tvoid
)
1240 // Create: return vresult;
1242 Expression
*e
= new VarExp(0, vresult
);
1244 { e
= e
->implicitCastTo(sc
, tintro
->nextOf());
1245 e
= e
->semantic(sc
);
1247 ReturnStatement
*s
= new ReturnStatement(0, e
);
1252 fbody
= new CompoundStatement(0, a
);
1254 /* Append destructor calls for parameters as finally blocks.
1257 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1259 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1261 if (v
->storage_class
& (STCref
| STCout
))
1264 /* Don't do this for static arrays, since static
1265 * arrays are called by reference. Remove this
1266 * when we change them to call by value.
1268 if (v
->type
->toBasetype()->ty
== Tsarray
)
1271 Expression
*e
= v
->callAutoDtor(sc
);
1273 { Statement
*s
= new ExpStatement(0, e
);
1274 s
= s
->semantic(sc
);
1275 if (fbody
->blockExit() == BEfallthru
)
1276 fbody
= new CompoundStatement(0, fbody
, s
);
1278 fbody
= new TryFinallyStatement(0, fbody
, s
);
1290 void FuncDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1292 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1294 type
->toCBuffer(buf
, ident
, hgs
);
1295 bodyToCBuffer(buf
, hgs
);
1299 void FuncDeclaration::bodyToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1302 (!hgs
->hdrgen
|| hgs
->tpltMember
|| canInline(1,1))
1308 { buf
->writestring("in");
1310 frequire
->toCBuffer(buf
, hgs
);
1315 { buf
->writestring("out");
1317 { buf
->writebyte('(');
1318 buf
->writestring(outId
->toChars());
1319 buf
->writebyte(')');
1322 fensure
->toCBuffer(buf
, hgs
);
1325 if (frequire
|| fensure
)
1326 { buf
->writestring("body");
1330 buf
->writebyte('{');
1332 fbody
->toCBuffer(buf
, hgs
);
1333 buf
->writebyte('}');
1337 { buf
->writeByte(';');
1342 /****************************************************
1343 * Determine if 'this' overrides fd.
1344 * Return !=0 if it does.
1347 int FuncDeclaration::overrides(FuncDeclaration
*fd
)
1350 if (fd
->ident
== ident
)
1352 int cov
= type
->covariant(fd
->type
);
1354 { ClassDeclaration
*cd1
= toParent()->isClassDeclaration();
1355 ClassDeclaration
*cd2
= fd
->toParent()->isClassDeclaration();
1357 if (cd1
&& cd2
&& cd2
->isBaseOf(cd1
, NULL
))
1364 /*************************************************
1365 * Find index of function in vtbl[0..dim] that
1366 * this function overrides.
1368 * -1 didn't find one
1369 * -2 can't determine because of forward references
1372 int FuncDeclaration::findVtblIndex(Array
*vtbl
, int dim
)
1374 for (int vi
= 0; vi
< dim
; vi
++)
1376 FuncDeclaration
*fdv
= ((Dsymbol
*)vtbl
->data
[vi
])->isFuncDeclaration();
1377 if (fdv
&& fdv
->ident
== ident
)
1379 int cov
= type
->covariant(fdv
->type
);
1380 //printf("\tbaseclass cov = %d\n", cov);
1383 case 0: // types are distinct
1391 //fdv->type->print();
1392 //printf("%s %s\n", type->deco, fdv->type->deco);
1393 error("of type %s overrides but is not covariant with %s of type %s",
1394 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
1398 return -2; // forward references
1408 /****************************************************
1409 * Overload this FuncDeclaration with the new one f.
1410 * Return !=0 if successful; i.e. no conflict.
1413 int FuncDeclaration::overloadInsert(Dsymbol
*s
)
1416 AliasDeclaration
*a
;
1418 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1419 a
= s
->isAliasDeclaration();
1423 return overnext
->overloadInsert(a
);
1424 if (!a
->aliassym
&& a
->type
->ty
!= Tident
&& a
->type
->ty
!= Tinstance
)
1426 //printf("\ta = '%s'\n", a->type->toChars());
1430 //printf("\ttrue: no conflict\n");
1433 f
= s
->isFuncDeclaration();
1438 /* Disable this check because:
1440 * semantic() isn't run yet on foo(), so the const hasn't been
1444 { printf("type = %s\n", type
->toChars());
1445 printf("f->type = %s\n", f
->type
->toChars());
1447 if (type
&& f
->type
&& // can be NULL for overloaded constructors
1448 f
->type
->covariant(type
) &&
1449 f
->type
->mod
== type
->mod
&&
1450 !isFuncAliasDeclaration())
1452 //printf("\tfalse: conflict %s\n", kind());
1458 return overnext
->overloadInsert(f
);
1460 //printf("\ttrue: no conflict\n");
1464 /***************************************************
1465 * Visit each overloaded function in turn, and call
1466 * (*fp)(param, f) on it.
1467 * Exit when no more, or (*fp)(param, f) returns 1.
1473 int overloadApply(FuncDeclaration
*fstart
,
1474 int (*fp
)(void *, FuncDeclaration
*),
1481 for (d
= fstart
; d
; d
= next
)
1482 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1486 if (overloadApply(fa
->funcalias
, fp
, param
))
1488 next
= fa
->overnext
;
1492 AliasDeclaration
*a
= d
->isAliasDeclaration();
1496 Dsymbol
*s
= a
->toAlias();
1497 next
= s
->isDeclaration();
1505 f
= d
->isFuncDeclaration();
1507 { d
->error("is aliased to a function");
1508 break; // BUG: should print error message?
1510 if ((*fp
)(param
, f
))
1520 /********************************************
1521 * If there are no overloads of function f, return that function,
1522 * otherwise return NULL.
1525 static int fpunique(void *param
, FuncDeclaration
*f
)
1526 { FuncDeclaration
**pf
= (FuncDeclaration
**)param
;
1530 return 1; // ambiguous, done
1538 FuncDeclaration
*FuncDeclaration::isUnique()
1539 { FuncDeclaration
*result
= NULL
;
1541 overloadApply(this, &fpunique
, &result
);
1545 /********************************************
1546 * Find function in overload list that exactly matches t.
1551 Type
*t
; // type to match
1552 FuncDeclaration
*f
; // return value
1555 int fp1(void *param
, FuncDeclaration
*f
)
1556 { Param1
*p
= (Param1
*)param
;
1559 if (t
->equals(f
->type
))
1565 /* Allow covariant matches, if it's just a const conversion
1566 * of the return type
1568 if (t
->ty
== Tfunction
)
1569 { TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1570 if (tf
->covariant(t
) == 1 &&
1571 tf
->nextOf()->implicitConvTo(t
->nextOf()) >= MATCHconst
)
1581 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1586 overloadApply(this, &fp1
, &p
);
1591 /********************************************
1592 * Decide which function matches the arguments best.
1599 Expressions
*arguments
;
1602 int fp2(void *param
, FuncDeclaration
*f
)
1603 { Param2
*p
= (Param2
*)param
;
1605 Expressions
*arguments
= p
->arguments
;
1608 if (f
!= m
->lastf
) // skip duplicates
1611 TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1612 match
= (MATCH
) tf
->callMatch(f
->needThis() ? p
->ethis
: NULL
, arguments
);
1613 //printf("match = %d\n", match);
1614 if (match
!= MATCHnomatch
)
1616 if (match
> m
->last
)
1619 if (match
< m
->last
)
1622 /* See if one of the matches overrides the other.
1624 if (m
->lastf
->overrides(f
))
1626 else if (f
->overrides(m
->lastf
))
1629 /* Try to disambiguate using template-style partial ordering rules.
1630 * In essence, if f() and g() are ambiguous, if f() can call g(),
1631 * but g() cannot call f(), then pick f().
1632 * This is because f() is "more specialized."
1635 MATCH c1
= f
->leastAsSpecialized(m
->lastf
);
1636 MATCH c2
= m
->lastf
->leastAsSpecialized(f
);
1661 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
,
1662 Expression
*ethis
, Expressions
*arguments
)
1667 p
.arguments
= arguments
;
1668 overloadApply(fstart
, &fp2
, &p
);
1672 FuncDeclaration
*FuncDeclaration::overloadResolve(Loc loc
, Expression
*ethis
, Expressions
*arguments
, int flags
)
1678 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1682 for (i
= 0; i
< arguments
->dim
; i
++)
1685 arg
= (Expression
*)arguments
->data
[i
];
1687 printf("\t%s: ", arg
->toChars());
1693 memset(&m
, 0, sizeof(m
));
1694 m
.last
= MATCHnomatch
;
1695 overloadResolveX(&m
, this, ethis
, arguments
);
1697 if (m
.count
== 1) // exactly one match
1709 argExpTypesToCBuffer(&buf
, arguments
, &hgs
);
1712 if (m
.last
== MATCHnomatch
)
1714 if (flags
& 1) // if do not print error messages
1715 return NULL
; // no match
1717 tf
= (TypeFunction
*)type
;
1719 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1720 error(loc
, "%s does not match parameter types (%s)",
1721 Argument::argsTypesToChars(tf
->parameters
, tf
->varargs
),
1723 return m
.anyf
; // as long as it's not a FuncAliasDeclaration
1728 TypeFunction
*t1
= (TypeFunction
*)m
.lastf
->type
;
1729 TypeFunction
*t2
= (TypeFunction
*)m
.nextf
->type
;
1731 error(loc
, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1733 m
.lastf
->toPrettyChars(), Argument::argsTypesToChars(t1
->parameters
, t1
->varargs
),
1734 m
.nextf
->toPrettyChars(), Argument::argsTypesToChars(t2
->parameters
, t2
->varargs
));
1736 error(loc
, "overloads %s and %s both match argument list for %s",
1737 m
.lastf
->type
->toChars(),
1738 m
.nextf
->type
->toChars(),
1739 m
.lastf
->toChars());
1746 /*************************************
1747 * Determine partial specialization order of 'this' vs g.
1748 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1750 * match 'this' is at least as specialized as g
1751 * 0 g is more specialized than 'this'
1754 MATCH
FuncDeclaration::leastAsSpecialized(FuncDeclaration
*g
)
1756 #define LOG_LEASTAS 0
1759 printf("%s.leastAsSpecialized(%s)\n", toChars(), g
->toChars());
1762 /* This works by calling g() with f()'s parameters, and
1763 * if that is possible, then f() is at least as specialized
1767 TypeFunction
*tf
= (TypeFunction
*)type
;
1768 TypeFunction
*tg
= (TypeFunction
*)g
->type
;
1769 size_t nfparams
= Argument::dim(tf
->parameters
);
1770 size_t ngparams
= Argument::dim(tg
->parameters
);
1771 MATCH match
= MATCHexact
;
1773 /* If both functions have a 'this' pointer, and the mods are not
1774 * the same and g's is not const, then this is less specialized.
1776 if (needThis() && g
->needThis())
1778 if (tf
->mod
!= tg
->mod
)
1780 if (tg
->mod
== MODconst
)
1783 return MATCHnomatch
;
1787 /* Create a dummy array of arguments out of the parameters to f()
1790 args
.setDim(nfparams
);
1791 for (int u
= 0; u
< nfparams
; u
++)
1793 Argument
*p
= Argument::getNth(tf
->parameters
, u
);
1794 Expression
*e
= p
->type
->defaultInit();
1798 MATCH m
= (MATCH
) tg
->callMatch(NULL
, &args
);
1801 /* A variadic template is less specialized than a
1804 if (tf
->varargs
&& !tg
->varargs
)
1805 goto L1
; // less specialized
1808 printf(" matches %d, so is least as specialized\n", m
);
1814 printf(" doesn't match, so is not as specialized\n");
1816 return MATCHnomatch
;
1819 /********************************
1820 * Labels are in a separate scope, one per function.
1823 LabelDsymbol
*FuncDeclaration::searchLabel(Identifier
*ident
)
1827 labtab
= new DsymbolTable(); // guess we need one
1829 s
= labtab
->lookup(ident
);
1832 s
= new LabelDsymbol(ident
);
1835 return (LabelDsymbol
*)s
;
1838 /****************************************
1839 * If non-static member function that has a 'this' pointer,
1840 * return the aggregate it is a member of.
1841 * Otherwise, return NULL.
1844 AggregateDeclaration
*FuncDeclaration::isThis()
1845 { AggregateDeclaration
*ad
;
1847 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1849 if ((storage_class
& STCstatic
) == 0)
1853 //printf("-FuncDeclaration::isThis() %p\n", ad);
1857 AggregateDeclaration
*FuncDeclaration::isMember2()
1858 { AggregateDeclaration
*ad
;
1860 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1862 for (Dsymbol
*s
= this; s
; s
= s
->parent
)
1864 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1867 { //printf("test4\n");
1871 (!s
->parent
->isTemplateInstance()))
1872 { //printf("test5\n");
1876 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1880 /*****************************************
1881 * Determine lexical level difference from 'this' to nested function 'fd'.
1882 * Error if this cannot call fd.
1885 * -1 increase nesting by 1 (fd is nested within 'this')
1886 * >0 decrease nesting by number
1889 int FuncDeclaration::getLevel(Loc loc
, FuncDeclaration
*fd
)
1894 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1895 fdparent
= fd
->toParent2();
1896 if (fdparent
== this)
1900 while (fd
!= s
&& fdparent
!= s
->toParent2())
1902 //printf("\ts = '%s'\n", s->toChars());
1903 FuncDeclaration
*thisfd
= s
->isFuncDeclaration();
1905 { if (!thisfd
->isNested() && !thisfd
->vthis
)
1910 ClassDeclaration
*thiscd
= s
->isClassDeclaration();
1912 { if (!thiscd
->isNested())
1926 error(loc
, "cannot access frame of function %s", fd
->toChars());
1930 void FuncDeclaration::appendExp(Expression
*e
)
1933 s
= new ExpStatement(0, e
);
1937 void FuncDeclaration::appendState(Statement
*s
)
1938 { CompoundStatement
*cs
;
1943 a
= new Statements();
1944 fbody
= new CompoundStatement(0, a
);
1946 cs
= fbody
->isCompoundStatement();
1947 cs
->statements
->push(s
);
1951 int FuncDeclaration::isMain()
1953 return ident
== Id::main
&&
1954 linkage
!= LINKc
&& !isMember() && !isNested();
1957 int FuncDeclaration::isWinMain()
1959 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1961 int x
= ident
== Id::WinMain
&&
1962 linkage
!= LINKc
&& !isMember();
1963 printf("%s\n", x
? "yes" : "no");
1966 return ident
== Id::WinMain
&&
1967 linkage
!= LINKc
&& !isMember();
1971 int FuncDeclaration::isDllMain()
1973 return ident
== Id::DllMain
&&
1974 linkage
!= LINKc
&& !isMember();
1977 int FuncDeclaration::isExport()
1979 return protection
== PROTexport
;
1982 int FuncDeclaration::isImportedSymbol()
1984 //printf("isImportedSymbol()\n");
1985 //printf("protection = %d\n", protection);
1986 return (protection
== PROTexport
) && !fbody
;
1989 // Determine if function goes into virtual function pointer table
1991 int FuncDeclaration::isVirtual()
1994 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1995 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
1996 printf("result is %d\n",
1998 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1999 toParent()->isClassDeclaration());
2001 return isMember() &&
2002 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
2003 toParent()->isClassDeclaration();
2006 int FuncDeclaration::isFinal()
2009 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2010 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
2011 printf("result is %d\n",
2013 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
2014 toParent()->isClassDeclaration());
2016 ClassDeclaration
*cd
;
2017 return isMember() &&
2018 (Declaration::isFinal() ||
2019 ((cd
= toParent()->isClassDeclaration()) != NULL
&& cd
->storage_class
& STCfinal
));
2022 int FuncDeclaration::isAbstract()
2024 return storage_class
& STCabstract
;
2027 int FuncDeclaration::isCodeseg()
2029 return TRUE
; // functions are always in the code segment
2032 int FuncDeclaration::isOverloadable()
2034 return 1; // functions can be overloaded
2037 // Determine if function needs
2038 // a static frame pointer to its lexically enclosing function
2040 int FuncDeclaration::isNested()
2043 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2044 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2045 return ((storage_class
& STCstatic
) == 0) &&
2046 (toParent2()->isFuncDeclaration() != NULL
);
2049 int FuncDeclaration::needThis()
2051 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2052 int i
= isThis() != NULL
;
2053 //printf("\t%d\n", i);
2054 if (!i
&& isFuncAliasDeclaration())
2055 i
= ((FuncAliasDeclaration
*)this)->funcalias
->needThis();
2059 int FuncDeclaration::addPreInvariant()
2061 AggregateDeclaration
*ad
= isThis();
2063 //ad->isClassDeclaration() &&
2064 global
.params
.useInvariants
&&
2065 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2067 ident
!= Id::cpctor
);
2070 int FuncDeclaration::addPostInvariant()
2072 AggregateDeclaration
*ad
= isThis();
2075 //ad->isClassDeclaration() &&
2076 global
.params
.useInvariants
&&
2077 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2079 ident
!= Id::cpctor
);
2082 /**********************************
2083 * Generate a FuncDeclaration for a runtime library function.
2086 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, char *name
,
2087 Type
*t1
, Type
*t2
, Type
*t3
)
2089 return genCfunc(treturn
, Lexer::idPool(name
), t1
, t2
, t3
);
2092 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, Identifier
*id
,
2093 Type
*t1
, Type
*t2
, Type
*t3
)
2095 FuncDeclaration
*fd
;
2098 static DsymbolTable
*st
= NULL
;
2100 //printf("genCfunc(name = '%s')\n", id->toChars());
2101 //printf("treturn\n\t"); treturn->print();
2103 // See if already in table
2105 st
= new DsymbolTable();
2109 fd
= s
->isFuncDeclaration();
2111 assert(fd
->type
->nextOf()->equals(treturn
));
2115 Arguments
* args
= 0;
2117 args
= new Arguments
;
2118 args
->push(new Argument(STCin
,t1
,0,0));
2121 args
->push(new Argument(STCin
,t2
,0,0));
2123 args
->push(new Argument(STCin
,t3
,0,0));
2127 tf
= new TypeFunction(args
, treturn
, 0, LINKc
);
2128 fd
= new FuncDeclaration(0, 0, id
, STCstatic
, tf
);
2129 fd
->protection
= PROTpublic
;
2130 fd
->linkage
= LINKc
;
2137 char *FuncDeclaration::kind()
2142 /*******************************
2143 * Look at all the variables in this function that are referenced
2144 * by nested functions, and determine if a closure needs to be
2149 int FuncDeclaration::needsClosure()
2151 /* Need a closure for all the closureVars[] if any of the
2152 * closureVars[] are accessed by a
2153 * function that escapes the scope of this function.
2154 * We take the conservative approach and decide that any function that:
2155 * 1) is a virtual function
2156 * 2) has its address taken
2157 * 3) has a parent that escapes
2159 * Note that since a non-virtual function can be called by
2160 * a virtual one, if that non-virtual function accesses a closure
2161 * var, the closure still has to be taken. Hence, we check for isThis()
2162 * instead of isVirtual(). (thanks to David Friedman)
2165 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2166 for (int i
= 0; i
< closureVars
.dim
; i
++)
2167 { VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2168 assert(v
->isVarDeclaration());
2169 //printf("\tv = %s\n", v->toChars());
2171 for (int j
= 0; j
< v
->nestedrefs
.dim
; j
++)
2172 { FuncDeclaration
*f
= (FuncDeclaration
*)v
->nestedrefs
.data
[j
];
2175 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2176 if (f
->isThis() || f
->tookAddressOf
)
2177 goto Lyes
; // assume f escapes this function's scope
2179 // Look to see if any parents of f that are below this escape
2180 for (Dsymbol
*s
= f
->parent
; s
!= this; s
= s
->parent
)
2182 f
= s
->isFuncDeclaration();
2183 if (f
&& (f
->isThis() || f
->tookAddressOf
))
2191 //printf("\tneeds closure\n");
2196 /****************************** FuncAliasDeclaration ************************/
2198 // Used as a way to import a set of functions from another scope into this one.
2200 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration
*funcalias
)
2201 : FuncDeclaration(funcalias
->loc
, funcalias
->endloc
, funcalias
->ident
,
2202 (enum STC
)funcalias
->storage_class
, funcalias
->type
)
2204 assert(funcalias
!= this);
2205 this->funcalias
= funcalias
;
2208 char *FuncAliasDeclaration::kind()
2210 return "function alias";
2214 /****************************** FuncLiteralDeclaration ************************/
2216 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc
, Loc endloc
, Type
*type
,
2217 enum TOK tok
, ForeachStatement
*fes
)
2218 : FuncDeclaration(loc
, endloc
, NULL
, STCundefined
, type
)
2223 id
= "__foreachbody";
2224 else if (tok
== TOKdelegate
)
2227 id
= "__funcliteral";
2228 this->ident
= Identifier::generateId(id
);
2231 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2234 Dsymbol
*FuncLiteralDeclaration::syntaxCopy(Dsymbol
*s
)
2236 FuncLiteralDeclaration
*f
;
2238 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2240 f
= (FuncLiteralDeclaration
*)s
;
2242 f
= new FuncLiteralDeclaration(loc
, endloc
, type
->syntaxCopy(), tok
, fes
);
2243 FuncDeclaration::syntaxCopy(f
);
2247 int FuncLiteralDeclaration::isNested()
2249 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2250 return (tok
== TOKdelegate
);
2253 char *FuncLiteralDeclaration::kind()
2255 // GCC requires the (char*) casts
2256 return (tok
== TOKdelegate
) ? (char*)"delegate" : (char*)"function";
2259 void FuncLiteralDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2261 static Identifier
*idfunc
;
2262 static Identifier
*iddel
;
2265 idfunc
= new Identifier("function", 0);
2267 iddel
= new Identifier("delegate", 0);
2269 type
->toCBuffer(buf
, ((tok
== TOKdelegate
) ? iddel
: idfunc
), hgs
);
2270 bodyToCBuffer(buf
, hgs
);
2274 /********************************* CtorDeclaration ****************************/
2276 CtorDeclaration::CtorDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2277 : FuncDeclaration(loc
, endloc
, Id::ctor
, STCundefined
, NULL
)
2279 this->arguments
= arguments
;
2280 this->varargs
= varargs
;
2281 //printf("CtorDeclaration() %s\n", toChars());
2284 Dsymbol
*CtorDeclaration::syntaxCopy(Dsymbol
*s
)
2288 f
= new CtorDeclaration(loc
, endloc
, NULL
, varargs
);
2291 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
2292 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
2293 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
2294 assert(!fthrows
); // deprecated
2296 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2301 void CtorDeclaration::semantic(Scope
*sc
)
2303 ClassDeclaration
*cd
;
2306 //printf("CtorDeclaration::semantic()\n");
2311 sc
->stc
&= ~STCstatic
; // not a static constructor
2313 parent
= sc
->parent
;
2314 Dsymbol
*parent
= toParent();
2315 cd
= parent
->isClassDeclaration();
2318 error("constructors are only for class definitions");
2323 tret
= cd
->type
; //->referenceTo();
2325 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
2327 VarDeclaration
*vd
= (VarDeclaration
*) cd
->fields
.data
[i
];
2328 if (vd
->storage_class
& STCinject
)
2331 arguments
= new Arguments();
2332 Argument
*a
= new Argument(vd
->storage_class
, vd
->type
, vd
->ident
, 0);
2333 // BUG: We don't really want these arguments in scope...
2336 Statement
*assign
= new ExpStatement(loc
, new AssignExp(loc
,
2337 new DotIdExp(loc
, new ThisExp(loc
), a
->ident
),
2338 new IdentifierExp(loc
, a
->ident
)));
2340 fbody
= new CompoundStatement(loc
, assign
, fbody
);
2347 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2349 sc
->flags
|= SCOPEctor
;
2350 type
= type
->semantic(loc
, sc
);
2351 sc
->flags
&= ~SCOPEctor
;
2355 // to the function body
2361 s
= new ReturnStatement(0, e
);
2362 fbody
= new CompoundStatement(0, fbody
, s
);
2365 FuncDeclaration::semantic(sc
);
2369 // See if it's the default constructor
2370 if (cd
&& varargs
== 0 && Argument::dim(arguments
) == 0)
2371 cd
->defaultCtor
= this;
2374 char *CtorDeclaration::kind()
2376 return "constructor";
2379 char *CtorDeclaration::toChars()
2384 int CtorDeclaration::isVirtual()
2389 int CtorDeclaration::addPreInvariant()
2394 int CtorDeclaration::addPostInvariant()
2396 return (vthis
&& global
.params
.useInvariants
);
2400 void CtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2402 buf
->writestring("this");
2403 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2404 bodyToCBuffer(buf
, hgs
);
2407 /********************************* PostBlitDeclaration ****************************/
2409 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
)
2410 : FuncDeclaration(loc
, endloc
, Id::_postblit
, STCundefined
, NULL
)
2414 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2415 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2419 Dsymbol
*PostBlitDeclaration::syntaxCopy(Dsymbol
*s
)
2422 PostBlitDeclaration
*dd
= new PostBlitDeclaration(loc
, endloc
, ident
);
2423 return FuncDeclaration::syntaxCopy(dd
);
2427 void PostBlitDeclaration::semantic(Scope
*sc
)
2429 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2430 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2431 parent
= sc
->parent
;
2432 Dsymbol
*parent
= toParent();
2433 StructDeclaration
*ad
= parent
->isStructDeclaration();
2436 error("post blits are only for struct/union definitions, not %s %s", parent
->kind(), parent
->toChars());
2438 else if (ident
== Id::_postblit
)
2439 ad
->postblits
.push(this);
2440 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2443 sc
->stc
&= ~STCstatic
; // not static
2444 sc
->linkage
= LINKd
;
2446 FuncDeclaration::semantic(sc
);
2451 int PostBlitDeclaration::overloadInsert(Dsymbol
*s
)
2453 return FALSE
; // cannot overload postblits
2456 int PostBlitDeclaration::addPreInvariant()
2461 int PostBlitDeclaration::addPostInvariant()
2463 return (vthis
&& global
.params
.useInvariants
);
2466 int PostBlitDeclaration::isVirtual()
2471 void PostBlitDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2475 buf
->writestring("=this()");
2476 bodyToCBuffer(buf
, hgs
);
2479 /********************************* DtorDeclaration ****************************/
2481 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
)
2482 : FuncDeclaration(loc
, endloc
, Id::dtor
, STCundefined
, NULL
)
2486 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2487 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2491 Dsymbol
*DtorDeclaration::syntaxCopy(Dsymbol
*s
)
2494 DtorDeclaration
*dd
= new DtorDeclaration(loc
, endloc
, ident
);
2495 return FuncDeclaration::syntaxCopy(dd
);
2499 void DtorDeclaration::semantic(Scope
*sc
)
2501 //printf("DtorDeclaration::semantic() %s\n", toChars());
2502 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2503 parent
= sc
->parent
;
2504 Dsymbol
*parent
= toParent();
2505 AggregateDeclaration
*ad
= parent
->isAggregateDeclaration();
2508 error("destructors are only for class/struct/union definitions, not %s %s", parent
->kind(), parent
->toChars());
2510 else if (ident
== Id::dtor
)
2511 ad
->dtors
.push(this);
2512 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2515 sc
->stc
&= ~STCstatic
; // not a static destructor
2516 sc
->linkage
= LINKd
;
2518 FuncDeclaration::semantic(sc
);
2523 int DtorDeclaration::overloadInsert(Dsymbol
*s
)
2525 return FALSE
; // cannot overload destructors
2528 int DtorDeclaration::addPreInvariant()
2530 return (vthis
&& global
.params
.useInvariants
);
2533 int DtorDeclaration::addPostInvariant()
2538 int DtorDeclaration::isVirtual()
2540 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2541 * but doing so will require recompiling everything.
2546 return FuncDeclaration::isVirtual();
2550 void DtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2554 buf
->writestring("~this()");
2555 bodyToCBuffer(buf
, hgs
);
2558 /********************************* StaticCtorDeclaration ****************************/
2560 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
)
2561 : FuncDeclaration(loc
, endloc
,
2562 Identifier::generateId("_staticCtor"), STCstatic
, NULL
)
2566 Dsymbol
*StaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
2568 StaticCtorDeclaration
*scd
;
2571 scd
= new StaticCtorDeclaration(loc
, endloc
);
2572 return FuncDeclaration::syntaxCopy(scd
);
2576 void StaticCtorDeclaration::semantic(Scope
*sc
)
2578 //printf("StaticCtorDeclaration::semantic()\n");
2580 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2582 FuncDeclaration::semantic(sc
);
2584 // We're going to need ModuleInfo
2585 Module
*m
= getModule();
2589 { m
->needmoduleinfo
= 1;
2591 m
->strictlyneedmoduleinfo
= 1;
2596 AggregateDeclaration
*StaticCtorDeclaration::isThis()
2601 int StaticCtorDeclaration::isStaticConstructor()
2606 int StaticCtorDeclaration::isVirtual()
2611 int StaticCtorDeclaration::addPreInvariant()
2616 int StaticCtorDeclaration::addPostInvariant()
2621 void StaticCtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2624 { buf
->writestring("static this();\n");
2627 buf
->writestring("static this()");
2628 bodyToCBuffer(buf
, hgs
);
2631 /********************************* StaticDtorDeclaration ****************************/
2633 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
)
2634 : FuncDeclaration(loc
, endloc
,
2635 Identifier::generateId("_staticDtor"), STCstatic
, NULL
)
2639 Dsymbol
*StaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
2641 StaticDtorDeclaration
*sdd
;
2644 sdd
= new StaticDtorDeclaration(loc
, endloc
);
2645 return FuncDeclaration::syntaxCopy(sdd
);
2649 void StaticDtorDeclaration::semantic(Scope
*sc
)
2651 ClassDeclaration
*cd
;
2654 cd
= sc
->scopesym
->isClassDeclaration();
2658 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2660 FuncDeclaration::semantic(sc
);
2662 // We're going to need ModuleInfo
2663 Module
*m
= getModule();
2667 { m
->needmoduleinfo
= 1;
2669 m
->strictlyneedmoduleinfo
= 1;
2674 AggregateDeclaration
*StaticDtorDeclaration::isThis()
2679 int StaticDtorDeclaration::isStaticDestructor()
2684 int StaticDtorDeclaration::isVirtual()
2689 int StaticDtorDeclaration::addPreInvariant()
2694 int StaticDtorDeclaration::addPostInvariant()
2699 void StaticDtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2703 buf
->writestring("static ~this()");
2704 bodyToCBuffer(buf
, hgs
);
2707 /********************************* InvariantDeclaration ****************************/
2709 InvariantDeclaration::InvariantDeclaration(Loc loc
, Loc endloc
)
2710 : FuncDeclaration(loc
, endloc
, Id::classInvariant
, STCundefined
, NULL
)
2714 Dsymbol
*InvariantDeclaration::syntaxCopy(Dsymbol
*s
)
2716 InvariantDeclaration
*id
;
2719 id
= new InvariantDeclaration(loc
, endloc
);
2720 FuncDeclaration::syntaxCopy(id
);
2725 void InvariantDeclaration::semantic(Scope
*sc
)
2727 AggregateDeclaration
*ad
;
2730 parent
= sc
->parent
;
2731 Dsymbol
*parent
= toParent();
2732 ad
= parent
->isAggregateDeclaration();
2735 error("invariants only are for struct/union/class definitions");
2738 else if (ad
->inv
&& ad
->inv
!= this)
2740 error("more than one invariant for %s", ad
->toChars());
2743 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2746 sc
->stc
&= ~STCstatic
; // not a static invariant
2748 sc
->linkage
= LINKd
;
2750 FuncDeclaration::semantic(sc
);
2755 int InvariantDeclaration::isVirtual()
2760 int InvariantDeclaration::addPreInvariant()
2765 int InvariantDeclaration::addPostInvariant()
2770 void InvariantDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2774 buf
->writestring("invariant");
2775 bodyToCBuffer(buf
, hgs
);
2779 /********************************* UnitTestDeclaration ****************************/
2781 /*******************************
2782 * Generate unique unittest function Id so we can have multiple
2783 * instances per module.
2786 static Identifier
*unitTestId()
2788 return Lexer::uniqueId("__unittest");
2791 UnitTestDeclaration::UnitTestDeclaration(Loc loc
, Loc endloc
)
2792 : FuncDeclaration(loc
, endloc
, unitTestId(), STCundefined
, NULL
)
2796 Dsymbol
*UnitTestDeclaration::syntaxCopy(Dsymbol
*s
)
2798 UnitTestDeclaration
*utd
;
2801 utd
= new UnitTestDeclaration(loc
, endloc
);
2802 return FuncDeclaration::syntaxCopy(utd
);
2806 void UnitTestDeclaration::semantic(Scope
*sc
)
2808 if (global
.params
.useUnitTests
)
2812 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2813 FuncDeclaration::semantic(sc
);
2816 // We're going to need ModuleInfo even if the unit tests are not
2817 // compiled in, because other modules may import this module and refer
2818 // to this ModuleInfo.
2819 Module
*m
= getModule();
2823 m
->needmoduleinfo
= 1;
2826 AggregateDeclaration
*UnitTestDeclaration::isThis()
2831 int UnitTestDeclaration::isVirtual()
2836 int UnitTestDeclaration::addPreInvariant()
2841 int UnitTestDeclaration::addPostInvariant()
2846 void UnitTestDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2850 buf
->writestring("unittest");
2851 bodyToCBuffer(buf
, hgs
);
2854 /********************************* NewDeclaration ****************************/
2856 NewDeclaration::NewDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2857 : FuncDeclaration(loc
, endloc
, Id::classNew
, STCstatic
, NULL
)
2859 this->arguments
= arguments
;
2860 this->varargs
= varargs
;
2863 Dsymbol
*NewDeclaration::syntaxCopy(Dsymbol
*s
)
2867 f
= new NewDeclaration(loc
, endloc
, NULL
, varargs
);
2869 FuncDeclaration::syntaxCopy(f
);
2871 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2877 void NewDeclaration::semantic(Scope
*sc
)
2879 ClassDeclaration
*cd
;
2882 //printf("NewDeclaration::semantic()\n");
2884 parent
= sc
->parent
;
2885 Dsymbol
*parent
= toParent();
2886 cd
= parent
->isClassDeclaration();
2887 if (!cd
&& !parent
->isStructDeclaration())
2889 error("new allocators only are for class or struct definitions");
2891 tret
= Type::tvoid
->pointerTo();
2892 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2894 type
= type
->semantic(loc
, sc
);
2895 assert(type
->ty
== Tfunction
);
2897 // Check that there is at least one argument of type uint
2898 TypeFunction
*tf
= (TypeFunction
*)type
;
2899 if (Argument::dim(tf
->parameters
) < 1)
2901 error("at least one argument of type uint expected");
2905 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2906 if (!a
->type
->equals(Type::tuns32
) &&
2907 (! global
.params
.isX86_64
|| !a
->type
->equals(Type::tuns64
)))
2908 error("first argument must be type uint, not %s", a
->type
->toChars());
2911 FuncDeclaration::semantic(sc
);
2914 char *NewDeclaration::kind()
2919 int NewDeclaration::isVirtual()
2924 int NewDeclaration::addPreInvariant()
2929 int NewDeclaration::addPostInvariant()
2934 void NewDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2936 buf
->writestring("new");
2937 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2938 bodyToCBuffer(buf
, hgs
);
2942 /********************************* DeleteDeclaration ****************************/
2944 DeleteDeclaration::DeleteDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
)
2945 : FuncDeclaration(loc
, endloc
, Id::classDelete
, STCstatic
, NULL
)
2947 this->arguments
= arguments
;
2950 Dsymbol
*DeleteDeclaration::syntaxCopy(Dsymbol
*s
)
2952 DeleteDeclaration
*f
;
2954 f
= new DeleteDeclaration(loc
, endloc
, NULL
);
2956 FuncDeclaration::syntaxCopy(f
);
2958 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2964 void DeleteDeclaration::semantic(Scope
*sc
)
2966 ClassDeclaration
*cd
;
2968 //printf("DeleteDeclaration::semantic()\n");
2970 parent
= sc
->parent
;
2971 Dsymbol
*parent
= toParent();
2972 cd
= parent
->isClassDeclaration();
2973 if (!cd
&& !parent
->isStructDeclaration())
2975 error("new allocators only are for class or struct definitions");
2977 type
= new TypeFunction(arguments
, Type::tvoid
, 0, LINKd
);
2979 type
= type
->semantic(loc
, sc
);
2980 assert(type
->ty
== Tfunction
);
2982 // Check that there is only one argument of type void*
2983 TypeFunction
*tf
= (TypeFunction
*)type
;
2984 if (Argument::dim(tf
->parameters
) != 1)
2986 error("one argument of type void* expected");
2990 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2991 if (!a
->type
->equals(Type::tvoid
->pointerTo()))
2992 error("one argument of type void* expected, not %s", a
->type
->toChars());
2995 FuncDeclaration::semantic(sc
);
2998 char *DeleteDeclaration::kind()
3000 return "deallocator";
3003 int DeleteDeclaration::isDelete()
3008 int DeleteDeclaration::isVirtual()
3013 int DeleteDeclaration::addPreInvariant()
3018 int DeleteDeclaration::addPostInvariant()
3023 void DeleteDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3025 buf
->writestring("delete");
3026 Argument::argsToCBuffer(buf
, hgs
, arguments
, 0);
3027 bodyToCBuffer(buf
, hgs
);