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);
126 if (!type
->deco
&& type
->nextOf())
129 /* Apply const and invariant storage class
130 * to the function type
132 type
= type
->semantic(loc
, sc
);
133 if (storage_class
& STCinvariant
)
134 { // Don't use toInvariant(), as that will do a merge()
135 type
= type
->makeInvariant();
136 type
->deco
= type
->merge()->deco
;
138 else if (storage_class
& STCconst
)
140 if (!type
->isInvariant())
141 { // Don't use toConst(), as that will do a merge()
142 type
= type
->makeConst();
143 type
->deco
= type
->merge()->deco
;
147 if (storage_class
& (STCconst
| STCinvariant
))
149 /* Apply const and invariant storage class
150 * to the function's return type
152 Type
*tn
= type
->nextOf();
153 if (storage_class
& STCconst
)
154 tn
= tn
->makeConst();
155 if (storage_class
& STCinvariant
)
156 tn
= tn
->makeInvariant();
157 ((TypeNext
*)type
)->next
= tn
;
160 type
= type
->semantic(loc
, sc
);
164 if (type
->ty
!= Tfunction
)
166 error("%s must be a function", toChars());
169 f
= (TypeFunction
*)(type
);
171 size_t nparams
= Argument::dim(f
->parameters
);
173 linkage
= sc
->linkage
;
176 //parent = sc->scopesym;
179 protection
= sc
->protection
;
181 attributes
->append(sc
->attributes
);
183 attributes
= sc
->attributes
;
184 Dsymbol
*parent
= toParent();
186 if (isAuto() || isScope())
187 error("functions cannot be scope or auto");
189 if (isAbstract() && !isVirtual())
190 error("non-virtual functions cannot be abstract");
192 if ((f
->isConst() || f
->isInvariant()) && !isThis())
193 error("without 'this' cannot be const/invariant");
195 if (isAbstract() && isFinal())
196 error("cannot be both final and abstract");
198 if (isAbstract() && fbody
)
199 error("abstract functions cannot have bodies");
203 if (isStaticConstructor() || isStaticDestructor())
205 if (!isStatic() || type
->nextOf()->ty
!= Tvoid
)
206 error("static constructors / destructors must be static void");
207 if (f
->arguments
&& f
->arguments
->dim
)
208 error("static constructors / destructors must have empty parameter list");
209 // BUG: check for invalid storage classes
214 AggregateDeclaration
*ad
;
216 ad
= parent
->isAggregateDeclaration();
218 ad
->methods
.push(this);
220 sd
= parent
->isStructDeclaration();
223 // Verify no constructors, destructors, etc.
224 if (isCtorDeclaration()
225 //||isDtorDeclaration()
226 //|| isInvariantDeclaration()
227 //|| isUnitTestDeclaration()
230 error("special member functions not allowed for %ss", sd
->kind());
235 sd
->inv
= isInvariantDeclaration();
238 sd
->aggNew
= isNewDeclaration();
243 error("multiple delete's for struct %s", sd
->toChars());
244 sd
->aggDelete
= (DeleteDeclaration
*)(this);
249 id
= parent
->isInterfaceDeclaration();
252 storage_class
|= STCabstract
;
254 if (isCtorDeclaration() ||
255 isPostBlitDeclaration() ||
256 isDtorDeclaration() ||
257 isInvariantDeclaration() ||
258 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
259 error("special function not allowed in interface %s", id
->toChars());
261 error("function body is not abstract in interface %s", id
->toChars());
264 cd
= parent
->isClassDeclaration();
267 CtorDeclaration
*ctor
;
268 DtorDeclaration
*dtor
;
269 InvariantDeclaration
*inv
;
271 if (isCtorDeclaration())
273 // ctor = (CtorDeclaration *)this;
280 dtor
= isDtorDeclaration();
284 error("multiple destructors for class %s", cd
->toChars());
288 inv
= isInvariantDeclaration();
294 if (isNewDeclaration())
297 cd
->aggNew
= (NewDeclaration
*)(this);
303 error("multiple delete's for class %s", cd
->toChars());
304 cd
->aggDelete
= (DeleteDeclaration
*)(this);
308 if (storage_class
& STCabstract
)
311 // if static function, do not put in vtbl[]
314 //printf("\tnot virtual\n");
318 // Find index of existing function in vtbl[] to override
319 vi
= findVtblIndex(&cd
->vtbl
, cd
->baseClass
? cd
->baseClass
->vtbl
.dim
: 0);
323 /* Didn't find one, so
324 * This is an 'introducing' function which gets a new
325 * slot in the vtbl[].
328 // Verify this doesn't override previous final function
330 { Dsymbol
*s
= cd
->baseClass
->search(loc
, ident
, 0);
333 FuncDeclaration
*f
= s
->isFuncDeclaration();
334 f
= f
->overloadExactMatch(type
);
335 if (f
&& f
->isFinal() && f
->prot() != PROTprivate
)
336 error("cannot override final function %s", f
->toPrettyChars());
342 cd
->vtblFinal
.push(this);
346 // Append to end of vtbl[]
347 //printf("\tintroducing function\n");
356 case -2: // can't determine because of fwd refs
357 cd
->sizeok
= 2; // can't finish due to forward reference
361 { FuncDeclaration
*fdv
= (FuncDeclaration
*)cd
->vtbl
.data
[vi
];
362 // This function is covariant with fdv
364 error("cannot override final function %s", fdv
->toPrettyChars());
366 if (!isOverride() && (global
.params
.warnings
|| sc
->module
->isDltFile
))
367 error("overrides base class function %s, but is not marked with 'override'", fdv
->toPrettyChars());
369 if (fdv
->toParent() == parent
)
371 // If both are mixins, then error.
372 // If either is not, the one that is not overrides
374 if (fdv
->parent
->isClassDeclaration())
376 if (!this->parent
->isClassDeclaration()
378 && !isDtorDeclaration()
380 && !isPostBlitDeclaration()
382 error("multiple overrides of same function");
384 cd
->vtbl
.data
[vi
] = (void *)this;
387 /* This works by whenever this function is called,
388 * it actually returns tintro, which gets dynamically
389 * cast to type. But we know that tintro is a base
390 * of type, so we could optimize it by not doing a
391 * dynamic cast, but just subtracting the isBaseOf()
392 * offset if the value is != null.
396 tintro
= fdv
->tintro
;
397 else if (!type
->equals(fdv
->type
))
399 /* Only need to have a tintro if the vptr
402 target_ptrdiff_t offset
;
403 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
412 /* Go through all the interface bases.
413 * If this function is covariant with any members of those interface
414 * functions, set the tintro.
416 for (int i
= 0; i
< cd
->interfaces_dim
; i
++)
418 BaseClass
*b
= cd
->interfaces
[i
];
419 vi
= findVtblIndex(&b
->base
->vtbl
, b
->base
->vtbl
.dim
);
426 cd
->sizeok
= 2; // can't finish due to forward reference
430 { FuncDeclaration
*fdv
= (FuncDeclaration
*)b
->base
->vtbl
.data
[vi
];
435 else if (!type
->equals(fdv
->type
))
437 /* Only need to have a tintro if the vptr
440 target_ptrdiff_t offset
;
441 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
447 else if (type
->nextOf()->ty
== Tclass
)
448 { ClassDeclaration
*cdn
= ((TypeClass
*)type
->nextOf())->sym
;
449 if (cdn
&& cdn
->sizeok
!= 1)
457 if (tintro
&& !tintro
->equals(ti
))
459 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
468 if (introducing
&& isOverride())
470 error("does not override any function");
475 else if (isOverride() && !parent
->isTemplateInstance())
476 error("override only applies to class member functions");
478 /* Do not allow template instances to add virtual functions
483 TemplateInstance
*ti
= parent
->isTemplateInstance();
486 // Take care of nested templates
489 TemplateInstance
*ti2
= ti
->tempdecl
->parent
->isTemplateInstance();
495 // If it's a member template
496 ClassDeclaration
*cd
= ti
->tempdecl
->isClassMember();
499 error("cannot use template to add virtual function to class '%s'", cd
->toChars());
506 // Check parameters to see if they are either () or (char[][] args)
514 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
515 if (arg0
->type
->ty
!= Tarray
||
516 arg0
->type
->nextOf()->ty
!= Tarray
||
517 arg0
->type
->nextOf()->nextOf()->ty
!= Tchar
||
518 arg0
->storageClass
& (STCout
| STCref
| STClazy
))
527 if (f
->nextOf()->ty
!= Tint32
&& f
->nextOf()->ty
!= Tvoid
)
528 error("must return int or void, not %s", f
->nextOf()->toChars());
532 error("parameters must be main() or main(char[][] args)");
536 if (ident
== Id::assign
&& (sd
|| cd
))
537 { // Disallow identity assignment operator.
541 { if (f
->varargs
== 1)
546 Argument
*arg0
= Argument::getNth(f
->parameters
, 0);
547 Type
*t0
= arg0
->type
->toBasetype();
548 Type
*tb
= sd
? sd
->type
: cd
->type
;
549 if (arg0
->type
->implicitConvTo(tb
) ||
550 (sd
&& t0
->ty
== Tpointer
&& t0
->nextOf()->implicitConvTo(tb
))
555 Argument
*arg1
= Argument::getNth(f
->parameters
, 1);
556 if (arg1
->defaultArg
)
563 /* Save scope for possible later use (if we need the
564 * function internals)
566 scope
= new Scope(*sc
);
573 sd
->hasIdentityAssign
= 1; // don't need to generate it
576 error("identity assignment operator overload is illegal");
579 void FuncDeclaration::semantic2(Scope
*sc
)
583 // Do the semantic analysis on the internals of the function.
585 void FuncDeclaration::semantic3(Scope
*sc
)
587 AggregateDeclaration
*ad
;
588 VarDeclaration
*argptr
= NULL
;
589 VarDeclaration
*_arguments
= NULL
;
595 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
598 //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
600 //{ static int x; if (++x == 2) *(char*)0=0; }
601 //printf("\tlinkage = %d\n", sc->linkage);
603 //printf(" sc->incontract = %d\n", sc->incontract);
608 if (!type
|| type
->ty
!= Tfunction
)
610 f
= (TypeFunction
*)(type
);
612 // Check the 'throws' clause
616 for (i
= 0; i
< fthrows
->dim
; i
++)
618 Type
*t
= (Type
*)fthrows
->data
[i
];
620 t
= t
->semantic(loc
, sc
);
621 if (!t
->isClassHandle())
622 error("can only throw classes, not %s", t
->toChars());
626 if (fbody
|| frequire
)
628 /* Symbol table into which we place parameters and nested functions,
629 * solely to diagnose name collisions.
631 localsymtab
= new DsymbolTable();
633 // Establish function scope
634 ScopeDsymbol
*ss
= new ScopeDsymbol();
635 ss
->parent
= sc
->scopesym
;
636 Scope
*sc2
= sc
->push(ss
);
641 sc2
->scontinue
= NULL
;
644 sc2
->linkage
= LINKd
;
645 sc2
->stc
&= ~(STCauto
| STCscope
| STCstatic
| STCabstract
| STCdeprecated
| STCconst
| STCfinal
| STCinvariant
| STCtls
);
646 sc2
->attributes
= NULL
;
647 sc2
->protection
= PROTpublic
;
648 sc2
->explicitProtection
= 0;
649 sc2
->structalign
= 8;
659 if (isFuncLiteralDeclaration() && isNested())
661 error("literals cannot be class members");
666 assert(!isNested()); // can't be both member and nested
668 Type
*thandle
= ad
->handle
;
669 if (storage_class
& STCconst
|| type
->isConst())
671 if (thandle
->ty
== Tclass
)
672 thandle
= thandle
->constOf();
674 { assert(thandle
->ty
== Tpointer
);
675 thandle
= thandle
->nextOf()->constOf()->pointerTo();
678 else if (storage_class
& STCinvariant
|| type
->isInvariant())
680 if (thandle
->ty
== Tclass
)
681 thandle
= thandle
->invariantOf();
683 { assert(thandle
->ty
== Tpointer
);
684 thandle
= thandle
->nextOf()->invariantOf()->pointerTo();
687 v
= new ThisDeclaration(thandle
);
688 v
->storage_class
|= STCparameter
;
698 /* The 'this' for a nested function is the link to the
699 * enclosing function's stack frame.
700 * Note that nested functions and member functions are disjoint.
702 VarDeclaration
*v
= new ThisDeclaration(Type::tvoid
->pointerTo());
703 v
->storage_class
|= STCparameter
;
711 // Declare hidden variable _arguments[] and _argptr
715 if (f
->linkage
== LINKd
)
716 { // Declare _arguments[]
718 v_arguments
= new VarDeclaration(0, Type::typeinfotypelist
->type
, Id::_arguments_typeinfo
, NULL
);
719 v_arguments
->storage_class
= STCparameter
;
720 v_arguments
->semantic(sc2
);
721 sc2
->insert(v_arguments
);
722 v_arguments
->parent
= this;
724 //t = Type::typeinfo->type->constOf()->arrayOf();
725 t
= Type::typeinfo
->type
->arrayOf();
726 _arguments
= new VarDeclaration(0, t
, Id::_arguments
, NULL
);
727 _arguments
->skipnullcheck
= TRUE
;
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
->skipnullcheck
= TRUE
;
749 argptr
->semantic(sc2
);
751 argptr
->parent
= this;
755 // Propagate storage class from tuple parameters to their element-parameters.
758 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
759 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
761 if (arg
->type
->ty
== Ttuple
)
762 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
763 size_t dim
= Argument::dim(t
->arguments
);
764 for (size_t j
= 0; j
< dim
; j
++)
765 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
766 narg
->storageClass
= arg
->storageClass
;
772 /* Declare all the function parameters as variables
773 * and install them in parameters[]
775 size_t nparams
= Argument::dim(f
->parameters
);
777 { /* parameters[] has all the tuples removed, as the back end
778 * doesn't know about tuples
780 parameters
= new Dsymbols();
781 parameters
->reserve(nparams
);
782 for (size_t i
= 0; i
< nparams
; i
++)
784 Argument
*arg
= Argument::getNth(f
->parameters
, i
);
785 Identifier
*id
= arg
->ident
;
788 /* Generate identifier for un-named parameter,
789 * because we need it later on.
792 buf
.printf("_param_%"PRIuSIZE
, i
);
793 char *name
= (char *)buf
.extractData();
794 id
= new Identifier(name
, TOKidentifier
);
797 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, id
, NULL
);
798 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
799 v
->storage_class
|= STCparameter
;
800 if (f
->varargs
== 2 && i
+ 1 == nparams
)
801 v
->storage_class
|= STCvariadic
;
802 v
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STClazy
| STCfinal
| STCconst
| STCinvariant
| STCnodtor
);
805 error("parameter %s.%s is already defined", toChars(), v
->toChars());
808 localsymtab
->insert(v
);
813 // Declare the tuple symbols and put them in the symbol table,
814 // but not in parameters[].
817 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
818 { Argument
*arg
= (Argument
*)f
->parameters
->data
[i
];
821 continue; // never used, so ignore
822 if (arg
->type
->ty
== Ttuple
)
823 { TypeTuple
*t
= (TypeTuple
*)arg
->type
;
824 size_t dim
= Argument::dim(t
->arguments
);
825 Objects
*exps
= new Objects();
827 for (size_t j
= 0; j
< dim
; j
++)
828 { Argument
*narg
= Argument::getNth(t
->arguments
, j
);
830 VarDeclaration
*v
= sc2
->search(0, narg
->ident
, NULL
)->isVarDeclaration();
832 Expression
*e
= new VarExp(v
->loc
, v
);
833 exps
->data
[j
] = (void *)e
;
836 TupleDeclaration
*v
= new TupleDeclaration(loc
, arg
->ident
, exps
);
837 //printf("declaring tuple %s\n", v->toChars());
840 error("parameter %s.%s is already defined", toChars(), v
->toChars());
841 localsymtab
->insert(v
);
847 /* Do the semantic analysis on the [in] preconditions and
848 * [out] postconditions.
853 { /* frequire is composed of the [in] contracts
855 // BUG: need to error if accessing out parameters
856 // BUG: need to treat parameters as const
857 // BUG: need to disallow returns and throws
858 // BUG: verify that all in and ref parameters are read
859 frequire
= frequire
->semantic(sc2
);
860 labtab
= NULL
; // so body can't refer to labels
863 if (fensure
|| addPostInvariant())
864 { /* fensure is composed of the [out] contracts
866 ScopeDsymbol
*sym
= new ScopeDsymbol();
867 sym
->parent
= sc2
->scopesym
;
868 sc2
= sc2
->push(sym
);
870 assert(type
->nextOf());
871 if (type
->nextOf()->ty
== Tvoid
)
874 error("void functions have no result");
879 outId
= Id::result
; // provide a default
883 { // Declare result variable
890 v
= new VarDeclaration(loc
, type
->nextOf(), outId
, NULL
);
892 v
->skipnullcheck
= 1;
897 error("out result %s is already defined", v
->toChars());
901 // vresult gets initialized with the function return value
902 // in ReturnStatement::semantic()
905 // BUG: need to treat parameters as const
906 // BUG: need to disallow returns and throws
908 { fensure
= fensure
->semantic(sc2
);
909 labtab
= NULL
; // so body can't refer to labels
912 if (!global
.params
.useOut
)
913 { fensure
= NULL
; // discard
917 // Postcondition invariant
918 if (addPostInvariant())
920 Expression
*e
= NULL
;
921 if (isCtorDeclaration())
923 // Call invariant directly only if it exists
924 InvariantDeclaration
*inv
= ad
->inv
;
925 ClassDeclaration
*cd
= ad
->isClassDeclaration();
936 e
= new DsymbolExp(0, inv
);
937 e
= new CallExp(0, e
);
938 e
= e
->semantic(sc2
);
942 { // Call invariant virtually
943 ThisExp
*v
= new ThisExp(0);
944 v
->type
= vthis
->type
;
945 e
= new AssertExp(0, v
);
949 ExpStatement
*s
= new ExpStatement(0, e
);
951 fensure
= new CompoundStatement(0, s
, fensure
);
958 { returnLabel
= new LabelDsymbol(Id::returnLabel
);
959 LabelStatement
*ls
= new LabelStatement(0, Id::returnLabel
, fensure
);
960 ls
->isReturnLabel
= 1;
961 returnLabel
->statement
= ls
;
969 { ClassDeclaration
*cd
= isClassMember();
971 /* If this is a class constructor
973 if (isCtorDeclaration() && cd
)
975 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
976 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
982 if (inferRetType
|| f
->retStyle() != RETstack
)
985 fbody
= fbody
->semantic(sc2
);
988 { // If no return type inferred yet, then infer a void
991 ((TypeFunction
*)type
)->next
= Type::tvoid
;
992 type
= type
->semantic(loc
, sc
);
994 f
= (TypeFunction
*)type
;
997 if (isStaticCtorDeclaration())
998 { /* It's a static constructor. Ensure that all
999 * ctor consts were initialized.
1002 Dsymbol
*p
= toParent();
1003 ScopeDsymbol
*ad
= p
->isScopeDsymbol();
1006 error("static constructor can only be member of struct/class/module, not %s %s", p
->kind(), p
->toChars());
1010 for (int i
= 0; i
< ad
->members
->dim
; i
++)
1011 { Dsymbol
*s
= (Dsymbol
*)ad
->members
->data
[i
];
1013 s
->checkCtorConstInit();
1018 if (isCtorDeclaration() && cd
)
1020 //printf("callSuper = x%x\n", sc2->callSuper);
1022 // Verify that all the ctorinit fields got initialized
1023 // Also check that non-null members got set
1024 if (!(sc2
->callSuper
& CSXthis_ctor
))
1026 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
1027 { VarDeclaration
*v
= (VarDeclaration
*)cd
->fields
.data
[i
];
1029 if (v
->ctorinit
== 0)
1031 if (v
->isCtorinit())
1032 error("missing initializer for final field %s", v
->toChars());
1033 else if (!v
->skipnullcheck
&&
1034 (v
->type
->ty
== Tclass
|| v
->type
->ty
== Tpointer
))
1035 error("missing initializer for non-null field %s", v
->toChars());
1040 if (!(sc2
->callSuper
& CSXany_ctor
) &&
1041 cd
->baseClass
&& cd
->baseClass
->ctor
)
1045 // Insert implicit super() at start of fbody
1046 Expression
*e1
= new SuperExp(0);
1047 Expression
*e
= new CallExp(0, e1
);
1049 unsigned errors
= global
.errors
;
1051 e
= e
->semantic(sc2
);
1053 if (errors
!= global
.errors
)
1054 error("no match for implicit super() call in constructor");
1056 Statement
*s
= new ExpStatement(0, e
);
1057 fbody
= new CompoundStatement(0, s
, fbody
);
1061 { // For foreach(){} body, append a return 0;
1062 Expression
*e
= new IntegerExp(0);
1063 Statement
*s
= new ReturnStatement(0, e
);
1064 fbody
= new CompoundStatement(0, fbody
, s
);
1065 assert(!returnLabel
);
1067 else if (!hasReturnExp
&& type
->nextOf()->ty
!= Tvoid
)
1068 error("expected to return a value of type %s", type
->nextOf()->toChars());
1069 else if (!inlineAsm
)
1071 int offend
= fbody
? fbody
->blockExit() & BEfallthru
: TRUE
;
1072 //int offend = fbody ? fbody->fallOffEnd() : TRUE;
1074 if (type
->nextOf()->ty
== Tvoid
)
1076 if (offend
&& isMain())
1077 { // Add a return 0; statement
1078 Statement
*s
= new ReturnStatement(0, new IntegerExp(0));
1079 fbody
= new CompoundStatement(0, fbody
, s
);
1087 if (global
.params
.warnings
)
1088 { fprintf(stdmsg
, "warning - ");
1089 error("no return at end of function");
1092 if (global
.params
.useAssert
&&
1093 !global
.params
.useInline
)
1094 { /* Add an assert(0, msg); where the missing return
1100 new StringExp(loc
, "missing return expression")
1104 e
= new HaltExp(endloc
);
1105 e
= new CommaExp(0, e
, type
->nextOf()->defaultInit());
1106 e
= e
->semantic(sc2
);
1107 Statement
*s
= new ExpStatement(0, e
);
1108 fbody
= new CompoundStatement(0, fbody
, s
);
1115 Statements
*a
= new Statements();
1117 // Merge in initialization of 'out' parameters
1119 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1121 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1122 if (v
->storage_class
& STCout
)
1125 ExpInitializer
*ie
= v
->init
->isExpInitializer();
1127 a
->push(new ExpStatement(0, ie
->exp
));
1133 { // Initialize _argptr to point past non-variadic arg
1135 // Handled in FuncDeclaration::toObjFile
1137 v_argptr
->init
= new VoidInitializer(loc
);
1141 Type
*t
= argptr
->type
;
1145 e1
= new VarExp(0, argptr
);
1146 if (parameters
&& parameters
->dim
)
1147 p
= (VarDeclaration
*)parameters
->data
[parameters
->dim
- 1];
1149 p
= v_arguments
; // last parameter is _arguments[]
1150 offset
= p
->type
->size();
1151 offset
= (offset
+ 3) & ~3; // assume stack aligns on 4
1152 e
= new SymOffExp(0, p
, offset
);
1153 e
= new AssignExp(0, e1
, e
);
1155 a
->push(new ExpStatement(0, e
));
1162 v_arguments_var
= _arguments
;
1163 v_arguments_var
->init
= new VoidInitializer(loc
);
1165 /* Advance to elements[] member of TypeInfo_Tuple with:
1166 * _arguments = v_arguments.elements;
1168 Expression
*e
= new VarExp(0, v_arguments
);
1169 e
= new DotIdExp(0, e
, Id::elements
);
1170 Expression
*e1
= new VarExp(0, _arguments
);
1171 e
= new AssignExp(0, e1
, e
);
1172 e
->op
= TOKconstruct
;
1173 e
= e
->semantic(sc
);
1174 a
->push(new ExpStatement(0, e
));
1177 // Merge contracts together with body into one compound statement
1180 if (frequire
&& global
.params
.useIn
)
1181 { frequire
->incontract
= 1;
1185 if (frequire
&& global
.params
.useIn
)
1189 // Precondition invariant
1190 if (addPreInvariant())
1192 Expression
*e
= NULL
;
1193 if (isDtorDeclaration())
1195 // Call invariant directly only if it exists
1196 InvariantDeclaration
*inv
= ad
->inv
;
1197 ClassDeclaration
*cd
= ad
->isClassDeclaration();
1208 e
= new DsymbolExp(0, inv
);
1209 e
= new CallExp(0, e
);
1210 e
= e
->semantic(sc2
);
1214 { // Call invariant virtually
1215 ThisExp
*v
= new ThisExp(0);
1216 v
->type
= vthis
->type
;
1217 Expression
*se
= new StringExp(0, "null this");
1218 se
= se
->semantic(sc
);
1219 se
->type
= Type::tchar
->arrayOf();
1220 e
= new AssertExp(loc
, v
, se
);
1224 ExpStatement
*s
= new ExpStatement(0, e
);
1234 a
->push(returnLabel
->statement
);
1236 if (type
->nextOf()->ty
!= Tvoid
)
1238 // Create: return vresult;
1240 Expression
*e
= new VarExp(0, vresult
);
1242 { e
= e
->implicitCastTo(sc
, tintro
->nextOf());
1243 e
= e
->semantic(sc
);
1245 ReturnStatement
*s
= new ReturnStatement(0, e
);
1250 fbody
= new CompoundStatement(0, a
);
1252 /* Append destructor calls for parameters as finally blocks.
1255 { for (size_t i
= 0; i
< parameters
->dim
; i
++)
1257 VarDeclaration
*v
= (VarDeclaration
*)parameters
->data
[i
];
1259 if (v
->storage_class
& (STCref
| STCout
))
1262 /* Don't do this for static arrays, since static
1263 * arrays are called by reference. Remove this
1264 * when we change them to call by value.
1266 if (v
->type
->toBasetype()->ty
== Tsarray
)
1269 Expression
*e
= v
->callAutoDtor(sc
);
1271 { Statement
*s
= new ExpStatement(0, e
);
1272 s
= s
->semantic(sc
);
1273 if (fbody
->blockExit() == BEfallthru
)
1274 fbody
= new CompoundStatement(0, fbody
, s
);
1276 fbody
= new TryFinallyStatement(0, fbody
, s
);
1288 void FuncDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1290 //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars());
1292 type
->toCBuffer(buf
, ident
, hgs
);
1293 bodyToCBuffer(buf
, hgs
);
1297 void FuncDeclaration::bodyToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1300 (!hgs
->hdrgen
|| hgs
->tpltMember
|| canInline(1,1))
1306 { buf
->writestring("in");
1308 frequire
->toCBuffer(buf
, hgs
);
1313 { buf
->writestring("out");
1315 { buf
->writebyte('(');
1316 buf
->writestring(outId
->toChars());
1317 buf
->writebyte(')');
1320 fensure
->toCBuffer(buf
, hgs
);
1323 if (frequire
|| fensure
)
1324 { buf
->writestring("body");
1328 buf
->writebyte('{');
1330 fbody
->toCBuffer(buf
, hgs
);
1331 buf
->writebyte('}');
1335 { buf
->writeByte(';');
1340 /****************************************************
1341 * Determine if 'this' overrides fd.
1342 * Return !=0 if it does.
1345 int FuncDeclaration::overrides(FuncDeclaration
*fd
)
1348 if (fd
->ident
== ident
)
1350 int cov
= type
->covariant(fd
->type
);
1352 { ClassDeclaration
*cd1
= toParent()->isClassDeclaration();
1353 ClassDeclaration
*cd2
= fd
->toParent()->isClassDeclaration();
1355 if (cd1
&& cd2
&& cd2
->isBaseOf(cd1
, NULL
))
1362 /*************************************************
1363 * Find index of function in vtbl[0..dim] that
1364 * this function overrides.
1366 * -1 didn't find one
1367 * -2 can't determine because of forward references
1370 int FuncDeclaration::findVtblIndex(Array
*vtbl
, int dim
)
1372 for (int vi
= 0; vi
< dim
; vi
++)
1374 FuncDeclaration
*fdv
= ((Dsymbol
*)vtbl
->data
[vi
])->isFuncDeclaration();
1375 if (fdv
&& fdv
->ident
== ident
)
1377 int cov
= type
->covariant(fdv
->type
);
1378 //printf("\tbaseclass cov = %d\n", cov);
1381 case 0: // types are distinct
1389 //fdv->type->print();
1390 //printf("%s %s\n", type->deco, fdv->type->deco);
1391 error("of type %s overrides but is not covariant with %s of type %s",
1392 type
->toChars(), fdv
->toPrettyChars(), fdv
->type
->toChars());
1396 return -2; // forward references
1406 /****************************************************
1407 * Overload this FuncDeclaration with the new one f.
1408 * Return !=0 if successful; i.e. no conflict.
1411 int FuncDeclaration::overloadInsert(Dsymbol
*s
)
1414 AliasDeclaration
*a
;
1416 //printf("FuncDeclaration::overloadInsert(%s)\n", s->toChars());
1417 a
= s
->isAliasDeclaration();
1421 return overnext
->overloadInsert(a
);
1422 if (!a
->aliassym
&& a
->type
->ty
!= Tident
&& a
->type
->ty
!= Tinstance
)
1424 //printf("\ta = '%s'\n", a->type->toChars());
1428 //printf("\ttrue: no conflict\n");
1431 f
= s
->isFuncDeclaration();
1436 /* Disable this check because:
1438 * semantic() isn't run yet on foo(), so the const hasn't been
1442 { printf("type = %s\n", type
->toChars());
1443 printf("f->type = %s\n", f
->type
->toChars());
1445 if (type
&& f
->type
&& // can be NULL for overloaded constructors
1446 f
->type
->covariant(type
) &&
1447 f
->type
->mod
== type
->mod
&&
1448 !isFuncAliasDeclaration())
1450 //printf("\tfalse: conflict %s\n", kind());
1456 return overnext
->overloadInsert(f
);
1458 //printf("\ttrue: no conflict\n");
1462 /***************************************************
1463 * Visit each overloaded function in turn, and call
1464 * (*fp)(param, f) on it.
1465 * Exit when no more, or (*fp)(param, f) returns 1.
1471 int overloadApply(FuncDeclaration
*fstart
,
1472 int (*fp
)(void *, FuncDeclaration
*),
1479 for (d
= fstart
; d
; d
= next
)
1480 { FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration();
1484 if (overloadApply(fa
->funcalias
, fp
, param
))
1486 next
= fa
->overnext
;
1490 AliasDeclaration
*a
= d
->isAliasDeclaration();
1494 Dsymbol
*s
= a
->toAlias();
1495 next
= s
->isDeclaration();
1503 f
= d
->isFuncDeclaration();
1505 { d
->error("is aliased to a function");
1506 break; // BUG: should print error message?
1508 if ((*fp
)(param
, f
))
1518 /********************************************
1519 * If there are no overloads of function f, return that function,
1520 * otherwise return NULL.
1523 static int fpunique(void *param
, FuncDeclaration
*f
)
1524 { FuncDeclaration
**pf
= (FuncDeclaration
**)param
;
1528 return 1; // ambiguous, done
1536 FuncDeclaration
*FuncDeclaration::isUnique()
1537 { FuncDeclaration
*result
= NULL
;
1539 overloadApply(this, &fpunique
, &result
);
1543 /********************************************
1544 * Find function in overload list that exactly matches t.
1549 Type
*t
; // type to match
1550 FuncDeclaration
*f
; // return value
1553 int fp1(void *param
, FuncDeclaration
*f
)
1554 { Param1
*p
= (Param1
*)param
;
1557 if (t
->equals(f
->type
))
1563 /* Allow covariant matches, if it's just a const conversion
1564 * of the return type
1566 if (t
->ty
== Tfunction
)
1567 { TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1568 if (tf
->covariant(t
) == 1 &&
1569 tf
->nextOf()->implicitConvTo(t
->nextOf()) >= MATCHconst
)
1579 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
1584 overloadApply(this, &fp1
, &p
);
1589 /********************************************
1590 * Decide which function matches the arguments best.
1597 Expressions
*arguments
;
1600 int fp2(void *param
, FuncDeclaration
*f
)
1601 { Param2
*p
= (Param2
*)param
;
1603 Expressions
*arguments
= p
->arguments
;
1606 if (f
!= m
->lastf
) // skip duplicates
1609 TypeFunction
*tf
= (TypeFunction
*)f
->type
;
1610 match
= (MATCH
) tf
->callMatch(f
->needThis() ? p
->ethis
: NULL
, arguments
);
1611 //printf("match = %d\n", match);
1612 if (match
!= MATCHnomatch
)
1614 if (match
> m
->last
)
1617 if (match
< m
->last
)
1620 /* See if one of the matches overrides the other.
1622 if (m
->lastf
->overrides(f
))
1624 else if (f
->overrides(m
->lastf
))
1627 /* Try to disambiguate using template-style partial ordering rules.
1628 * In essence, if f() and g() are ambiguous, if f() can call g(),
1629 * but g() cannot call f(), then pick f().
1630 * This is because f() is "more specialized."
1633 MATCH c1
= f
->leastAsSpecialized(m
->lastf
);
1634 MATCH c2
= m
->lastf
->leastAsSpecialized(f
);
1659 void overloadResolveX(Match
*m
, FuncDeclaration
*fstart
,
1660 Expression
*ethis
, Expressions
*arguments
)
1665 p
.arguments
= arguments
;
1666 overloadApply(fstart
, &fp2
, &p
);
1670 FuncDeclaration
*FuncDeclaration::overloadResolve(Loc loc
, Expression
*ethis
, Expressions
*arguments
, int flags
)
1676 printf("FuncDeclaration::overloadResolve('%s')\n", toChars());
1680 for (i
= 0; i
< arguments
->dim
; i
++)
1683 arg
= (Expression
*)arguments
->data
[i
];
1685 printf("\t%s: ", arg
->toChars());
1691 memset(&m
, 0, sizeof(m
));
1692 m
.last
= MATCHnomatch
;
1693 overloadResolveX(&m
, this, ethis
, arguments
);
1695 if (m
.count
== 1) // exactly one match
1707 argExpTypesToCBuffer(&buf
, arguments
, &hgs
);
1710 if (m
.last
== MATCHnomatch
)
1712 if (flags
& 1) // if do not print error messages
1713 return NULL
; // no match
1715 tf
= (TypeFunction
*)type
;
1717 //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
1718 error(loc
, "%s does not match parameter types (%s)",
1719 Argument::argsTypesToChars(tf
->parameters
, tf
->varargs
),
1721 return m
.anyf
; // as long as it's not a FuncAliasDeclaration
1726 TypeFunction
*t1
= (TypeFunction
*)m
.lastf
->type
;
1727 TypeFunction
*t2
= (TypeFunction
*)m
.nextf
->type
;
1729 error(loc
, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
1731 m
.lastf
->toPrettyChars(), Argument::argsTypesToChars(t1
->parameters
, t1
->varargs
),
1732 m
.nextf
->toPrettyChars(), Argument::argsTypesToChars(t2
->parameters
, t2
->varargs
));
1734 error(loc
, "overloads %s and %s both match argument list for %s",
1735 m
.lastf
->type
->toChars(),
1736 m
.nextf
->type
->toChars(),
1737 m
.lastf
->toChars());
1744 /*************************************
1745 * Determine partial specialization order of 'this' vs g.
1746 * This is very similar to TemplateDeclaration::leastAsSpecialized().
1748 * match 'this' is at least as specialized as g
1749 * 0 g is more specialized than 'this'
1752 MATCH
FuncDeclaration::leastAsSpecialized(FuncDeclaration
*g
)
1754 #define LOG_LEASTAS 0
1757 printf("%s.leastAsSpecialized(%s)\n", toChars(), g
->toChars());
1760 /* This works by calling g() with f()'s parameters, and
1761 * if that is possible, then f() is at least as specialized
1765 TypeFunction
*tf
= (TypeFunction
*)type
;
1766 TypeFunction
*tg
= (TypeFunction
*)g
->type
;
1767 size_t nfparams
= Argument::dim(tf
->parameters
);
1768 size_t ngparams
= Argument::dim(tg
->parameters
);
1769 MATCH match
= MATCHexact
;
1771 /* If both functions have a 'this' pointer, and the mods are not
1772 * the same and g's is not const, then this is less specialized.
1774 if (needThis() && g
->needThis())
1776 if (tf
->mod
!= tg
->mod
)
1778 if (tg
->mod
== MODconst
)
1781 return MATCHnomatch
;
1785 /* Create a dummy array of arguments out of the parameters to f()
1788 args
.setDim(nfparams
);
1789 for (int u
= 0; u
< nfparams
; u
++)
1791 Argument
*p
= Argument::getNth(tf
->parameters
, u
);
1792 Expression
*e
= p
->type
->defaultInit();
1796 MATCH m
= (MATCH
) tg
->callMatch(NULL
, &args
);
1799 /* A variadic template is less specialized than a
1802 if (tf
->varargs
&& !tg
->varargs
)
1803 goto L1
; // less specialized
1806 printf(" matches %d, so is least as specialized\n", m
);
1812 printf(" doesn't match, so is not as specialized\n");
1814 return MATCHnomatch
;
1817 /********************************
1818 * Labels are in a separate scope, one per function.
1821 LabelDsymbol
*FuncDeclaration::searchLabel(Identifier
*ident
)
1825 labtab
= new DsymbolTable(); // guess we need one
1827 s
= labtab
->lookup(ident
);
1830 s
= new LabelDsymbol(ident
);
1833 return (LabelDsymbol
*)s
;
1836 /****************************************
1837 * If non-static member function that has a 'this' pointer,
1838 * return the aggregate it is a member of.
1839 * Otherwise, return NULL.
1842 AggregateDeclaration
*FuncDeclaration::isThis()
1843 { AggregateDeclaration
*ad
;
1845 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
1847 if ((storage_class
& STCstatic
) == 0)
1851 //printf("-FuncDeclaration::isThis() %p\n", ad);
1855 AggregateDeclaration
*FuncDeclaration::isMember2()
1856 { AggregateDeclaration
*ad
;
1858 //printf("+FuncDeclaration::isMember2() '%s'\n", toChars());
1860 for (Dsymbol
*s
= this; s
; s
= s
->parent
)
1862 //printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
1865 { //printf("test4\n");
1869 (!s
->parent
->isTemplateInstance()))
1870 { //printf("test5\n");
1874 //printf("-FuncDeclaration::isMember2() %p\n", ad);
1878 /*****************************************
1879 * Determine lexical level difference from 'this' to nested function 'fd'.
1880 * Error if this cannot call fd.
1883 * -1 increase nesting by 1 (fd is nested within 'this')
1884 * >0 decrease nesting by number
1887 int FuncDeclaration::getLevel(Loc loc
, FuncDeclaration
*fd
)
1892 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
1893 fdparent
= fd
->toParent2();
1894 if (fdparent
== this)
1898 while (fd
!= s
&& fdparent
!= s
->toParent2())
1900 //printf("\ts = '%s'\n", s->toChars());
1901 FuncDeclaration
*thisfd
= s
->isFuncDeclaration();
1903 { if (!thisfd
->isNested() && !thisfd
->vthis
)
1908 ClassDeclaration
*thiscd
= s
->isClassDeclaration();
1910 { if (!thiscd
->isNested())
1924 error(loc
, "cannot access frame of function %s", fd
->toChars());
1928 void FuncDeclaration::appendExp(Expression
*e
)
1931 s
= new ExpStatement(0, e
);
1935 void FuncDeclaration::appendState(Statement
*s
)
1936 { CompoundStatement
*cs
;
1941 a
= new Statements();
1942 fbody
= new CompoundStatement(0, a
);
1944 cs
= fbody
->isCompoundStatement();
1945 cs
->statements
->push(s
);
1949 int FuncDeclaration::isMain()
1951 return ident
== Id::main
&&
1952 linkage
!= LINKc
&& !isMember() && !isNested();
1955 int FuncDeclaration::isWinMain()
1957 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
1959 int x
= ident
== Id::WinMain
&&
1960 linkage
!= LINKc
&& !isMember();
1961 printf("%s\n", x
? "yes" : "no");
1964 return ident
== Id::WinMain
&&
1965 linkage
!= LINKc
&& !isMember();
1969 int FuncDeclaration::isDllMain()
1971 return ident
== Id::DllMain
&&
1972 linkage
!= LINKc
&& !isMember();
1975 int FuncDeclaration::isExport()
1977 return protection
== PROTexport
;
1980 int FuncDeclaration::isImportedSymbol()
1982 //printf("isImportedSymbol()\n");
1983 //printf("protection = %d\n", protection);
1984 return (protection
== PROTexport
) && !fbody
;
1987 // Determine if function goes into virtual function pointer table
1989 int FuncDeclaration::isVirtual()
1992 printf("FuncDeclaration::isVirtual(%s)\n", toChars());
1993 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
1994 printf("result is %d\n",
1996 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
1997 toParent()->isClassDeclaration());
1999 return isMember() &&
2000 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
2001 toParent()->isClassDeclaration();
2004 int FuncDeclaration::isFinal()
2007 printf("FuncDeclaration::isFinal(%s)\n", toChars());
2008 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection
== PROTprivate
, isCtorDeclaration(), linkage
!= LINKd
);
2009 printf("result is %d\n",
2011 !(isStatic() || protection
== PROTprivate
|| protection
== PROTpackage
) &&
2012 toParent()->isClassDeclaration());
2014 ClassDeclaration
*cd
;
2015 return isMember() &&
2016 (Declaration::isFinal() ||
2017 ((cd
= toParent()->isClassDeclaration()) != NULL
&& cd
->storage_class
& STCfinal
));
2020 int FuncDeclaration::isAbstract()
2022 return storage_class
& STCabstract
;
2025 int FuncDeclaration::isCodeseg()
2027 return TRUE
; // functions are always in the code segment
2030 int FuncDeclaration::isOverloadable()
2032 return 1; // functions can be overloaded
2035 // Determine if function needs
2036 // a static frame pointer to its lexically enclosing function
2038 int FuncDeclaration::isNested()
2041 //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
2042 //printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
2043 return ((storage_class
& STCstatic
) == 0) &&
2044 (toParent2()->isFuncDeclaration() != NULL
);
2047 int FuncDeclaration::needThis()
2049 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
2050 int i
= isThis() != NULL
;
2051 //printf("\t%d\n", i);
2052 if (!i
&& isFuncAliasDeclaration())
2053 i
= ((FuncAliasDeclaration
*)this)->funcalias
->needThis();
2057 int FuncDeclaration::addPreInvariant()
2059 AggregateDeclaration
*ad
= isThis();
2061 //ad->isClassDeclaration() &&
2062 global
.params
.useInvariants
&&
2063 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2065 ident
!= Id::cpctor
);
2068 int FuncDeclaration::addPostInvariant()
2070 AggregateDeclaration
*ad
= isThis();
2073 //ad->isClassDeclaration() &&
2074 global
.params
.useInvariants
&&
2075 (protection
== PROTpublic
|| protection
== PROTexport
) &&
2077 ident
!= Id::cpctor
);
2080 /**********************************
2081 * Generate a FuncDeclaration for a runtime library function.
2084 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, char *name
,
2085 Type
*t1
, Type
*t2
, Type
*t3
)
2087 return genCfunc(treturn
, Lexer::idPool(name
), t1
, t2
, t3
);
2090 FuncDeclaration
*FuncDeclaration::genCfunc(Type
*treturn
, Identifier
*id
,
2091 Type
*t1
, Type
*t2
, Type
*t3
)
2093 FuncDeclaration
*fd
;
2096 static DsymbolTable
*st
= NULL
;
2098 //printf("genCfunc(name = '%s')\n", id->toChars());
2099 //printf("treturn\n\t"); treturn->print();
2101 // See if already in table
2103 st
= new DsymbolTable();
2107 fd
= s
->isFuncDeclaration();
2109 assert(fd
->type
->nextOf()->equals(treturn
));
2113 Arguments
* args
= 0;
2115 args
= new Arguments
;
2116 args
->push(new Argument(STCin
,t1
,0,0));
2119 args
->push(new Argument(STCin
,t2
,0,0));
2121 args
->push(new Argument(STCin
,t3
,0,0));
2125 tf
= new TypeFunction(args
, treturn
, 0, LINKc
);
2126 fd
= new FuncDeclaration(0, 0, id
, STCstatic
, tf
);
2127 fd
->protection
= PROTpublic
;
2128 fd
->linkage
= LINKc
;
2135 char *FuncDeclaration::kind()
2140 /*******************************
2141 * Look at all the variables in this function that are referenced
2142 * by nested functions, and determine if a closure needs to be
2147 int FuncDeclaration::needsClosure()
2149 /* Need a closure for all the closureVars[] if any of the
2150 * closureVars[] are accessed by a
2151 * function that escapes the scope of this function.
2152 * We take the conservative approach and decide that any function that:
2153 * 1) is a virtual function
2154 * 2) has its address taken
2155 * 3) has a parent that escapes
2157 * Note that since a non-virtual function can be called by
2158 * a virtual one, if that non-virtual function accesses a closure
2159 * var, the closure still has to be taken. Hence, we check for isThis()
2160 * instead of isVirtual(). (thanks to David Friedman)
2163 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
2164 for (int i
= 0; i
< closureVars
.dim
; i
++)
2165 { VarDeclaration
*v
= (VarDeclaration
*)closureVars
.data
[i
];
2166 assert(v
->isVarDeclaration());
2167 //printf("\tv = %s\n", v->toChars());
2169 for (int j
= 0; j
< v
->nestedrefs
.dim
; j
++)
2170 { FuncDeclaration
*f
= (FuncDeclaration
*)v
->nestedrefs
.data
[j
];
2173 //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
2174 if (f
->isThis() || f
->tookAddressOf
)
2175 goto Lyes
; // assume f escapes this function's scope
2177 // Look to see if any parents of f that are below this escape
2178 for (Dsymbol
*s
= f
->parent
; s
!= this; s
= s
->parent
)
2180 f
= s
->isFuncDeclaration();
2181 if (f
&& (f
->isThis() || f
->tookAddressOf
))
2189 //printf("\tneeds closure\n");
2194 /****************************** FuncAliasDeclaration ************************/
2196 // Used as a way to import a set of functions from another scope into this one.
2198 FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration
*funcalias
)
2199 : FuncDeclaration(funcalias
->loc
, funcalias
->endloc
, funcalias
->ident
,
2200 (enum STC
)funcalias
->storage_class
, funcalias
->type
)
2202 assert(funcalias
!= this);
2203 this->funcalias
= funcalias
;
2206 char *FuncAliasDeclaration::kind()
2208 return "function alias";
2212 /****************************** FuncLiteralDeclaration ************************/
2214 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc
, Loc endloc
, Type
*type
,
2215 enum TOK tok
, ForeachStatement
*fes
)
2216 : FuncDeclaration(loc
, endloc
, NULL
, STCundefined
, type
)
2221 id
= "__foreachbody";
2222 else if (tok
== TOKdelegate
)
2225 id
= "__funcliteral";
2226 this->ident
= Identifier::generateId(id
);
2229 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
2232 Dsymbol
*FuncLiteralDeclaration::syntaxCopy(Dsymbol
*s
)
2234 FuncLiteralDeclaration
*f
;
2236 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
2238 f
= (FuncLiteralDeclaration
*)s
;
2240 f
= new FuncLiteralDeclaration(loc
, endloc
, type
->syntaxCopy(), tok
, fes
);
2241 FuncDeclaration::syntaxCopy(f
);
2245 int FuncLiteralDeclaration::isNested()
2247 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
2248 return (tok
== TOKdelegate
);
2251 char *FuncLiteralDeclaration::kind()
2253 // GCC requires the (char*) casts
2254 return (tok
== TOKdelegate
) ? (char*)"delegate" : (char*)"function";
2257 void FuncLiteralDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2259 static Identifier
*idfunc
;
2260 static Identifier
*iddel
;
2263 idfunc
= new Identifier("function", 0);
2265 iddel
= new Identifier("delegate", 0);
2267 type
->toCBuffer(buf
, ((tok
== TOKdelegate
) ? iddel
: idfunc
), hgs
);
2268 bodyToCBuffer(buf
, hgs
);
2272 /********************************* CtorDeclaration ****************************/
2274 CtorDeclaration::CtorDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2275 : FuncDeclaration(loc
, endloc
, Id::ctor
, STCundefined
, NULL
)
2277 this->arguments
= arguments
;
2278 this->varargs
= varargs
;
2279 //printf("CtorDeclaration() %s\n", toChars());
2282 Dsymbol
*CtorDeclaration::syntaxCopy(Dsymbol
*s
)
2286 f
= new CtorDeclaration(loc
, endloc
, NULL
, varargs
);
2289 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
2290 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
2291 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
2292 assert(!fthrows
); // deprecated
2294 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2299 void CtorDeclaration::semantic(Scope
*sc
)
2301 ClassDeclaration
*cd
;
2304 //printf("CtorDeclaration::semantic()\n");
2309 sc
->stc
&= ~STCstatic
; // not a static constructor
2311 parent
= sc
->parent
;
2312 Dsymbol
*parent
= toParent();
2313 cd
= parent
->isClassDeclaration();
2316 error("constructors are only for class definitions");
2321 tret
= cd
->type
; //->referenceTo();
2323 for (int i
= 0; i
< cd
->fields
.dim
; i
++)
2325 VarDeclaration
*vd
= (VarDeclaration
*) cd
->fields
.data
[i
];
2329 arguments
= new Arguments();
2330 Argument
*a
= new Argument(vd
->storage_class
, vd
->type
, vd
->ident
, 0);
2331 // BUG: We don't really want these arguments in scope...
2334 Statement
*assign
= new ExpStatement(loc
, new AssignExp(loc
,
2335 new DotIdExp(loc
, new ThisExp(loc
), a
->ident
),
2336 new IdentifierExp(loc
, a
->ident
)));
2338 fbody
= new CompoundStatement(loc
, assign
, fbody
);
2345 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2347 sc
->flags
|= SCOPEctor
;
2348 type
= type
->semantic(loc
, sc
);
2349 sc
->flags
&= ~SCOPEctor
;
2353 // to the function body
2359 s
= new ReturnStatement(0, e
);
2360 fbody
= new CompoundStatement(0, fbody
, s
);
2363 FuncDeclaration::semantic(sc
);
2367 // See if it's the default constructor
2368 if (cd
&& varargs
== 0 && Argument::dim(arguments
) == 0)
2369 cd
->defaultCtor
= this;
2372 char *CtorDeclaration::kind()
2374 return "constructor";
2377 char *CtorDeclaration::toChars()
2382 int CtorDeclaration::isVirtual()
2387 int CtorDeclaration::addPreInvariant()
2392 int CtorDeclaration::addPostInvariant()
2394 return (vthis
&& global
.params
.useInvariants
);
2398 void CtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2400 buf
->writestring("this");
2401 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2402 bodyToCBuffer(buf
, hgs
);
2405 /********************************* PostBlitDeclaration ****************************/
2407 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
)
2408 : FuncDeclaration(loc
, endloc
, Id::_postblit
, STCundefined
, NULL
)
2412 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2413 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2417 Dsymbol
*PostBlitDeclaration::syntaxCopy(Dsymbol
*s
)
2420 PostBlitDeclaration
*dd
= new PostBlitDeclaration(loc
, endloc
, ident
);
2421 return FuncDeclaration::syntaxCopy(dd
);
2425 void PostBlitDeclaration::semantic(Scope
*sc
)
2427 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
2428 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2429 parent
= sc
->parent
;
2430 Dsymbol
*parent
= toParent();
2431 StructDeclaration
*ad
= parent
->isStructDeclaration();
2434 error("post blits are only for struct/union definitions, not %s %s", parent
->kind(), parent
->toChars());
2436 else if (ident
== Id::_postblit
)
2437 ad
->postblits
.push(this);
2438 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2441 sc
->stc
&= ~STCstatic
; // not static
2442 sc
->linkage
= LINKd
;
2444 FuncDeclaration::semantic(sc
);
2449 int PostBlitDeclaration::overloadInsert(Dsymbol
*s
)
2451 return FALSE
; // cannot overload postblits
2454 int PostBlitDeclaration::addPreInvariant()
2459 int PostBlitDeclaration::addPostInvariant()
2461 return (vthis
&& global
.params
.useInvariants
);
2464 int PostBlitDeclaration::isVirtual()
2469 void PostBlitDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2473 buf
->writestring("=this()");
2474 bodyToCBuffer(buf
, hgs
);
2477 /********************************* DtorDeclaration ****************************/
2479 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
)
2480 : FuncDeclaration(loc
, endloc
, Id::dtor
, STCundefined
, NULL
)
2484 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
, Identifier
*id
)
2485 : FuncDeclaration(loc
, endloc
, id
, STCundefined
, NULL
)
2489 Dsymbol
*DtorDeclaration::syntaxCopy(Dsymbol
*s
)
2492 DtorDeclaration
*dd
= new DtorDeclaration(loc
, endloc
, ident
);
2493 return FuncDeclaration::syntaxCopy(dd
);
2497 void DtorDeclaration::semantic(Scope
*sc
)
2499 //printf("DtorDeclaration::semantic() %s\n", toChars());
2500 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
2501 parent
= sc
->parent
;
2502 Dsymbol
*parent
= toParent();
2503 AggregateDeclaration
*ad
= parent
->isAggregateDeclaration();
2506 error("destructors are only for class/struct/union definitions, not %s %s", parent
->kind(), parent
->toChars());
2508 else if (ident
== Id::dtor
)
2509 ad
->dtors
.push(this);
2510 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2513 sc
->stc
&= ~STCstatic
; // not a static destructor
2514 sc
->linkage
= LINKd
;
2516 FuncDeclaration::semantic(sc
);
2521 int DtorDeclaration::overloadInsert(Dsymbol
*s
)
2523 return FALSE
; // cannot overload destructors
2526 int DtorDeclaration::addPreInvariant()
2528 return (vthis
&& global
.params
.useInvariants
);
2531 int DtorDeclaration::addPostInvariant()
2536 int DtorDeclaration::isVirtual()
2538 /* This should be FALSE so that dtor's don't get put into the vtbl[],
2539 * but doing so will require recompiling everything.
2544 return FuncDeclaration::isVirtual();
2548 void DtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2552 buf
->writestring("~this()");
2553 bodyToCBuffer(buf
, hgs
);
2556 /********************************* StaticCtorDeclaration ****************************/
2558 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
)
2559 : FuncDeclaration(loc
, endloc
,
2560 Identifier::generateId("_staticCtor"), STCstatic
, NULL
)
2564 Dsymbol
*StaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
2566 StaticCtorDeclaration
*scd
;
2569 scd
= new StaticCtorDeclaration(loc
, endloc
);
2570 return FuncDeclaration::syntaxCopy(scd
);
2574 void StaticCtorDeclaration::semantic(Scope
*sc
)
2576 //printf("StaticCtorDeclaration::semantic()\n");
2578 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2580 FuncDeclaration::semantic(sc
);
2582 // We're going to need ModuleInfo
2583 Module
*m
= getModule();
2587 { m
->needmoduleinfo
= 1;
2589 m
->strictlyneedmoduleinfo
= 1;
2594 AggregateDeclaration
*StaticCtorDeclaration::isThis()
2599 int StaticCtorDeclaration::isStaticConstructor()
2604 int StaticCtorDeclaration::isVirtual()
2609 int StaticCtorDeclaration::addPreInvariant()
2614 int StaticCtorDeclaration::addPostInvariant()
2619 void StaticCtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2622 { buf
->writestring("static this();\n");
2625 buf
->writestring("static this()");
2626 bodyToCBuffer(buf
, hgs
);
2629 /********************************* StaticDtorDeclaration ****************************/
2631 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
)
2632 : FuncDeclaration(loc
, endloc
,
2633 Identifier::generateId("_staticDtor"), STCstatic
, NULL
)
2637 Dsymbol
*StaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
2639 StaticDtorDeclaration
*sdd
;
2642 sdd
= new StaticDtorDeclaration(loc
, endloc
);
2643 return FuncDeclaration::syntaxCopy(sdd
);
2647 void StaticDtorDeclaration::semantic(Scope
*sc
)
2649 ClassDeclaration
*cd
;
2652 cd
= sc
->scopesym
->isClassDeclaration();
2656 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2658 FuncDeclaration::semantic(sc
);
2660 // We're going to need ModuleInfo
2661 Module
*m
= getModule();
2665 { m
->needmoduleinfo
= 1;
2667 m
->strictlyneedmoduleinfo
= 1;
2672 AggregateDeclaration
*StaticDtorDeclaration::isThis()
2677 int StaticDtorDeclaration::isStaticDestructor()
2682 int StaticDtorDeclaration::isVirtual()
2687 int StaticDtorDeclaration::addPreInvariant()
2692 int StaticDtorDeclaration::addPostInvariant()
2697 void StaticDtorDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2701 buf
->writestring("static ~this()");
2702 bodyToCBuffer(buf
, hgs
);
2705 /********************************* InvariantDeclaration ****************************/
2707 InvariantDeclaration::InvariantDeclaration(Loc loc
, Loc endloc
)
2708 : FuncDeclaration(loc
, endloc
, Id::classInvariant
, STCundefined
, NULL
)
2712 Dsymbol
*InvariantDeclaration::syntaxCopy(Dsymbol
*s
)
2714 InvariantDeclaration
*id
;
2717 id
= new InvariantDeclaration(loc
, endloc
);
2718 FuncDeclaration::syntaxCopy(id
);
2723 void InvariantDeclaration::semantic(Scope
*sc
)
2725 AggregateDeclaration
*ad
;
2728 parent
= sc
->parent
;
2729 Dsymbol
*parent
= toParent();
2730 ad
= parent
->isAggregateDeclaration();
2733 error("invariants only are for struct/union/class definitions");
2736 else if (ad
->inv
&& ad
->inv
!= this)
2738 error("more than one invariant for %s", ad
->toChars());
2741 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2744 sc
->stc
&= ~STCstatic
; // not a static invariant
2746 sc
->linkage
= LINKd
;
2748 FuncDeclaration::semantic(sc
);
2753 int InvariantDeclaration::isVirtual()
2758 int InvariantDeclaration::addPreInvariant()
2763 int InvariantDeclaration::addPostInvariant()
2768 void InvariantDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2772 buf
->writestring("invariant");
2773 bodyToCBuffer(buf
, hgs
);
2777 /********************************* UnitTestDeclaration ****************************/
2779 /*******************************
2780 * Generate unique unittest function Id so we can have multiple
2781 * instances per module.
2784 static Identifier
*unitTestId()
2786 return Lexer::uniqueId("__unittest");
2789 UnitTestDeclaration::UnitTestDeclaration(Loc loc
, Loc endloc
)
2790 : FuncDeclaration(loc
, endloc
, unitTestId(), STCundefined
, NULL
)
2794 Dsymbol
*UnitTestDeclaration::syntaxCopy(Dsymbol
*s
)
2796 UnitTestDeclaration
*utd
;
2799 utd
= new UnitTestDeclaration(loc
, endloc
);
2800 return FuncDeclaration::syntaxCopy(utd
);
2804 void UnitTestDeclaration::semantic(Scope
*sc
)
2806 if (global
.params
.useUnitTests
)
2810 type
= new TypeFunction(NULL
, Type::tvoid
, FALSE
, LINKd
);
2811 FuncDeclaration::semantic(sc
);
2814 // We're going to need ModuleInfo even if the unit tests are not
2815 // compiled in, because other modules may import this module and refer
2816 // to this ModuleInfo.
2817 Module
*m
= getModule();
2821 m
->needmoduleinfo
= 1;
2824 AggregateDeclaration
*UnitTestDeclaration::isThis()
2829 int UnitTestDeclaration::isVirtual()
2834 int UnitTestDeclaration::addPreInvariant()
2839 int UnitTestDeclaration::addPostInvariant()
2844 void UnitTestDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2848 buf
->writestring("unittest");
2849 bodyToCBuffer(buf
, hgs
);
2852 /********************************* NewDeclaration ****************************/
2854 NewDeclaration::NewDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
, int varargs
)
2855 : FuncDeclaration(loc
, endloc
, Id::classNew
, STCstatic
, NULL
)
2857 this->arguments
= arguments
;
2858 this->varargs
= varargs
;
2861 Dsymbol
*NewDeclaration::syntaxCopy(Dsymbol
*s
)
2865 f
= new NewDeclaration(loc
, endloc
, NULL
, varargs
);
2867 FuncDeclaration::syntaxCopy(f
);
2869 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2875 void NewDeclaration::semantic(Scope
*sc
)
2877 ClassDeclaration
*cd
;
2880 //printf("NewDeclaration::semantic()\n");
2882 parent
= sc
->parent
;
2883 Dsymbol
*parent
= toParent();
2884 cd
= parent
->isClassDeclaration();
2885 if (!cd
&& !parent
->isStructDeclaration())
2887 error("new allocators only are for class or struct definitions");
2889 tret
= Type::tvoid
->pointerTo();
2890 type
= new TypeFunction(arguments
, tret
, varargs
, LINKd
);
2892 type
= type
->semantic(loc
, sc
);
2893 assert(type
->ty
== Tfunction
);
2895 // Check that there is at least one argument of type uint
2896 TypeFunction
*tf
= (TypeFunction
*)type
;
2897 if (Argument::dim(tf
->parameters
) < 1)
2899 error("at least one argument of type uint expected");
2903 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2904 if (!a
->type
->equals(Type::tuns32
) &&
2905 (! global
.params
.isX86_64
|| !a
->type
->equals(Type::tuns64
)))
2906 error("first argument must be type uint, not %s", a
->type
->toChars());
2909 FuncDeclaration::semantic(sc
);
2912 char *NewDeclaration::kind()
2917 int NewDeclaration::isVirtual()
2922 int NewDeclaration::addPreInvariant()
2927 int NewDeclaration::addPostInvariant()
2932 void NewDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2934 buf
->writestring("new");
2935 Argument::argsToCBuffer(buf
, hgs
, arguments
, varargs
);
2936 bodyToCBuffer(buf
, hgs
);
2940 /********************************* DeleteDeclaration ****************************/
2942 DeleteDeclaration::DeleteDeclaration(Loc loc
, Loc endloc
, Arguments
*arguments
)
2943 : FuncDeclaration(loc
, endloc
, Id::classDelete
, STCstatic
, NULL
)
2945 this->arguments
= arguments
;
2948 Dsymbol
*DeleteDeclaration::syntaxCopy(Dsymbol
*s
)
2950 DeleteDeclaration
*f
;
2952 f
= new DeleteDeclaration(loc
, endloc
, NULL
);
2954 FuncDeclaration::syntaxCopy(f
);
2956 f
->arguments
= Argument::arraySyntaxCopy(arguments
);
2962 void DeleteDeclaration::semantic(Scope
*sc
)
2964 ClassDeclaration
*cd
;
2966 //printf("DeleteDeclaration::semantic()\n");
2968 parent
= sc
->parent
;
2969 Dsymbol
*parent
= toParent();
2970 cd
= parent
->isClassDeclaration();
2971 if (!cd
&& !parent
->isStructDeclaration())
2973 error("new allocators only are for class or struct definitions");
2975 type
= new TypeFunction(arguments
, Type::tvoid
, 0, LINKd
);
2977 type
= type
->semantic(loc
, sc
);
2978 assert(type
->ty
== Tfunction
);
2980 // Check that there is only one argument of type void*
2981 TypeFunction
*tf
= (TypeFunction
*)type
;
2982 if (Argument::dim(tf
->parameters
) != 1)
2984 error("one argument of type void* expected");
2988 Argument
*a
= Argument::getNth(tf
->parameters
, 0);
2989 if (!a
->type
->equals(Type::tvoid
->pointerTo()))
2990 error("one argument of type void* expected, not %s", a
->type
->toChars());
2993 FuncDeclaration::semantic(sc
);
2996 char *DeleteDeclaration::kind()
2998 return "deallocator";
3001 int DeleteDeclaration::isDelete()
3006 int DeleteDeclaration::isVirtual()
3011 int DeleteDeclaration::addPreInvariant()
3016 int DeleteDeclaration::addPostInvariant()
3021 void DeleteDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3023 buf
->writestring("delete");
3024 Argument::argsToCBuffer(buf
, hgs
, arguments
, 0);
3025 bodyToCBuffer(buf
, hgs
);