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
17 // Handle template implementation
24 long __cdecl
__ehfilter(LPEXCEPTION_POINTERS ep
);
29 #include "stringtable.h"
34 #include "expression.h"
37 #include "aggregate.h"
38 #include "declaration.h"
42 #include "identifier.h"
47 /********************************************
48 * These functions substitute for dynamic_cast. dynamic_cast does not work
49 * on earlier versions of gcc.
52 Expression
*isExpression(Object
*o
)
54 //return dynamic_cast<Expression *>(o);
55 if (!o
|| o
->dyncast() != DYNCAST_EXPRESSION
)
57 return (Expression
*)o
;
60 Dsymbol
*isDsymbol(Object
*o
)
62 //return dynamic_cast<Dsymbol *>(o);
63 if (!o
|| o
->dyncast() != DYNCAST_DSYMBOL
)
68 Type
*isType(Object
*o
)
70 //return dynamic_cast<Type *>(o);
71 if (!o
|| o
->dyncast() != DYNCAST_TYPE
)
76 Tuple
*isTuple(Object
*o
)
78 //return dynamic_cast<Tuple *>(o);
79 if (!o
|| o
->dyncast() != DYNCAST_TUPLE
)
85 /***********************
86 * Try to get arg as a type.
89 Type
*getType(Object
*o
)
93 { Expression
*e
= isExpression(o
);
100 Dsymbol
*getDsymbol(Object
*oarg
)
103 Expression
*ea
= isExpression(oarg
);
105 { // Try to convert Expression to symbol
106 if (ea
->op
== TOKvar
)
107 sa
= ((VarExp
*)ea
)->var
;
108 else if (ea
->op
== TOKfunction
)
109 sa
= ((FuncExp
*)ea
)->fd
;
114 { // Try to convert Type to symbol
115 Type
*ta
= isType(oarg
);
117 sa
= ta
->toDsymbol(NULL
);
119 sa
= isDsymbol(oarg
); // if already a symbol
124 /******************************
125 * If o1 matches o2, return 1.
129 int match(Object
*o1
, Object
*o2
, TemplateDeclaration
*tempdecl
, Scope
*sc
)
131 Type
*t1
= isType(o1
);
132 Type
*t2
= isType(o2
);
133 Expression
*e1
= isExpression(o1
);
134 Expression
*e2
= isExpression(o2
);
135 Dsymbol
*s1
= isDsymbol(o1
);
136 Dsymbol
*s2
= isDsymbol(o2
);
137 Tuple
*v1
= isTuple(o1
);
138 Tuple
*v2
= isTuple(o2
);
140 //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
142 /* A proper implementation of the various equals() overrides
143 * should make it possible to just do o1->equals(o2), but
144 * we'll do that another day.
149 /* if t1 is an instance of ti, then give error
150 * about recursive expansions.
152 Dsymbol
*s
= t1
->toDsymbol(sc
);
154 { TemplateInstance
*ti1
= s
->parent
->isTemplateInstance();
155 if (ti1
&& ti1
->tempdecl
== tempdecl
)
157 for (Scope
*sc1
= sc
; sc1
; sc1
= sc1
->enclosing
)
159 if (sc1
->scopesym
== ti1
)
161 error("recursive template expansion for template argument %s", t1
->toChars());
162 return 1; // fake a match
168 if (!t2
|| !t1
->equals(t2
))
176 printf("match %d\n", e1
->equals(e2
));
190 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
191 if (!s2
|| !s1
->equals(s2
) || s1
->parent
!= s2
->parent
)
200 if (v1
->objects
.dim
!= v2
->objects
.dim
)
202 for (size_t i
= 0; i
< v1
->objects
.dim
; i
++)
204 if (!match((Object
*)v1
->objects
.data
[i
],
205 (Object
*)v2
->objects
.data
[i
],
212 return 0; // nomatch;
215 /****************************************
218 void ObjectToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
, Object
*oarg
)
220 //printf("ObjectToCBuffer()\n");
221 Type
*t
= isType(oarg
);
222 Expression
*e
= isExpression(oarg
);
223 Dsymbol
*s
= isDsymbol(oarg
);
224 Tuple
*v
= isTuple(oarg
);
226 { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
227 t
->toCBuffer(buf
, NULL
, hgs
);
230 e
->toCBuffer(buf
, hgs
);
233 char *p
= s
->ident
? s
->ident
->toChars() : s
->toChars();
238 Objects
*args
= &v
->objects
;
239 for (size_t i
= 0; i
< args
->dim
; i
++)
243 Object
*o
= (Object
*)args
->data
[i
];
244 ObjectToCBuffer(buf
, hgs
, o
);
249 buf
->writestring("NULL");
254 printf("bad Object = %p\n", oarg
);
262 /* ======================== TemplateDeclaration ============================= */
264 TemplateDeclaration::TemplateDeclaration(Loc loc
, Identifier
*id
, TemplateParameters
*parameters
, Array
*decldefs
)
268 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id
->toChars());
272 for (int i
= 0; i
< parameters
->dim
; i
++)
273 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
274 //printf("\tparameter[%d] = %p\n", i, tp);
275 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
279 printf("\tparameter[%d] = %s : %s\n", i
, tp
->ident
->toChars(), ttp
->specType
? ttp
->specType
->toChars() : "");
284 this->parameters
= parameters
;
285 this->origParameters
= parameters
;
286 this->members
= decldefs
;
287 this->overnext
= NULL
;
288 this->overroot
= NULL
;
290 this->onemember
= NULL
;
293 Dsymbol
*TemplateDeclaration::syntaxCopy(Dsymbol
*)
295 //printf("TemplateDeclaration::syntaxCopy()\n");
296 TemplateDeclaration
*td
;
297 TemplateParameters
*p
;
303 p
= new TemplateParameters();
304 p
->setDim(parameters
->dim
);
305 for (int i
= 0; i
< p
->dim
; i
++)
306 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
307 p
->data
[i
] = (void *)tp
->syntaxCopy();
310 d
= Dsymbol::arraySyntaxCopy(members
);
311 td
= new TemplateDeclaration(loc
, ident
, p
, d
);
315 void TemplateDeclaration::semantic(Scope
*sc
)
318 printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident
->toChars());
321 return; // semantic() already run
325 error("cannot declare template at function scope %s", sc
->func
->toChars());
328 if (/*global.params.useArrayBounds &&*/ sc
->module
)
330 // Generate this function as it may be used
331 // when template is instantiated in other modules
332 sc
->module
->toModuleArray();
335 if (/*global.params.useAssert &&*/ sc
->module
)
337 // Generate this function as it may be used
338 // when template is instantiated in other modules
339 sc
->module
->toModuleAssert();
342 /* Remember Scope for later instantiations, but make
343 * a copy since attributes can change.
345 this->scope
= new Scope(*sc
);
346 this->scope
->setNoFree();
348 // Set up scope for parameters
349 ScopeDsymbol
*paramsym
= new ScopeDsymbol();
350 paramsym
->parent
= sc
->parent
;
351 Scope
*paramscope
= sc
->push(paramsym
);
352 paramscope
->parameterSpecialization
= 1;
354 if (global
.params
.doDocComments
)
356 origParameters
= new TemplateParameters();
357 origParameters
->setDim(parameters
->dim
);
358 for (int i
= 0; i
< parameters
->dim
; i
++)
360 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
361 origParameters
->data
[i
] = (void *)tp
->syntaxCopy();
365 for (int i
= 0; i
< parameters
->dim
; i
++)
367 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
369 tp
->declareParameter(paramscope
);
372 for (int i
= 0; i
< parameters
->dim
; i
++)
374 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
376 tp
->semantic(paramscope
);
377 if (i
+ 1 != parameters
->dim
&& tp
->isTemplateTupleParameter())
378 error("template tuple parameter must be last one");
386 if (Dsymbol::oneMembers(members
, &s
))
388 if (s
&& s
->ident
&& s
->ident
->equals(ident
))
396 /* BUG: should check:
397 * o no virtual functions or non-static data members of classes
401 char *TemplateDeclaration::kind()
403 return (onemember
&& onemember
->isAggregateDeclaration())
405 : (char *)"template";
408 /**********************************
409 * Overload existing TemplateDeclaration 'this' with the new one 's'.
410 * Return !=0 if successful; i.e. no conflict.
413 int TemplateDeclaration::overloadInsert(Dsymbol
*s
)
415 TemplateDeclaration
**pf
;
416 TemplateDeclaration
*f
;
419 printf("TemplateDeclaration::overloadInsert('%s')\n", s
->toChars());
421 f
= s
->isTemplateDeclaration();
424 TemplateDeclaration
*pthis
= this;
425 for (pf
= &pthis
; *pf
; pf
= &(*pf
)->overnext
)
428 // Conflict if TemplateParameter's match
429 // Will get caught anyway later with TemplateInstance, but
430 // should check it now.
431 TemplateDeclaration
*f2
= *pf
;
433 if (f
->parameters
->dim
!= f2
->parameters
->dim
)
436 for (int i
= 0; i
< f
->parameters
->dim
; i
++)
437 { TemplateParameter
*p1
= (TemplateParameter
*)f
->parameters
->data
[i
];
438 TemplateParameter
*p2
= (TemplateParameter
*)f2
->parameters
->data
[i
];
440 if (!p1
->overloadMatch(p2
))
445 printf("\tfalse: conflict\n");
457 printf("\ttrue: no conflict\n");
462 /***************************************
463 * Given that ti is an instance of this TemplateDeclaration,
464 * deduce the types of the parameters to this, and store
465 * those deduced types in dedtypes[].
467 * flag 1: don't do semantic() because of dummy types
468 * 2: don't change types in matchArg()
470 * dedtypes deduced arguments
471 * Return match level.
474 MATCH
TemplateDeclaration::matchWithInstance(TemplateInstance
*ti
,
475 Objects
*dedtypes
, int flag
)
477 int dedtypes_dim
= dedtypes
->dim
;
481 printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti
->toChars(), flag
);
485 printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim
, parameters
->dim
);
487 printf("ti->tiargs->dim = %d, [0] = %p\n",
489 ti
->tiargs
->data
[0]);
493 int parameters_dim
= parameters
->dim
;
494 int variadic
= isVariadic() != NULL
;
496 // If more arguments than parameters, no match
497 if (ti
->tiargs
->dim
> parameters_dim
&& !variadic
)
500 printf(" no match: more arguments than parameters\n");
505 assert(dedtypes_dim
== parameters_dim
);
506 assert(dedtypes_dim
>= ti
->tiargs
->dim
|| variadic
);
508 // Set up scope for parameters
509 assert((size_t)scope
> 0x10000);
510 ScopeDsymbol
*paramsym
= new ScopeDsymbol();
511 paramsym
->parent
= scope
->parent
;
512 Scope
*paramscope
= scope
->push(paramsym
);
514 // Attempt type deduction
516 for (int i
= 0; i
< dedtypes_dim
; i
++)
518 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
521 //printf("\targument [%d]\n", i);
523 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
524 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
526 printf("\tparameter[%d] is %s : %s\n", i
, tp
->ident
->toChars(), ttp
->specType
? ttp
->specType
->toChars() : "");
530 m2
= tp
->matchArg(paramscope
, ti
->tiargs
, i
, parameters
, dedtypes
, &sparam
);
532 m2
= tp
->matchArg(paramscope
, ti
->tiargs
, i
, parameters
, dedtypes
, &sparam
, (flag
& 2) ? 1 : 0);
535 //printf("\tm2 = %d\n", m2);
537 if (m2
== MATCHnomatch
)
540 printf("\tmatchArg() for parameter %i failed\n", i
);
549 sparam
->semantic(paramscope
);
550 if (!paramscope
->insert(sparam
))
556 // Any parameter left without a type gets the type of its corresponding arg
557 for (int i
= 0; i
< dedtypes_dim
; i
++)
559 if (!dedtypes
->data
[i
])
560 { assert(i
< ti
->tiargs
->dim
);
561 dedtypes
->data
[i
] = ti
->tiargs
->data
[i
];
567 // Print out the results
568 printf("--------------------------\n");
569 printf("template %s\n", toChars());
570 printf("instance %s\n", ti
->toChars());
573 for (int i
= 0; i
< dedtypes_dim
; i
++)
575 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
580 if (i
< ti
->tiargs
->dim
)
581 oarg
= (Object
*)ti
->tiargs
->data
[i
];
584 tp
->print(oarg
, (Object
*)dedtypes
->data
[i
]);
592 printf(" match = %d\n", m
);
598 printf(" no match\n");
605 printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti
, m
);
610 /********************************************
611 * Determine partial specialization order of 'this' vs td2.
613 * 1 this is at least as specialized as td2
614 * 0 td2 is more specialized than this
617 int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration
*td2
)
619 /* This works by taking the template parameters to this template
620 * declaration and feeding them to td2 as if it were a template
622 * If it works, then this template is at least as specialized
626 TemplateInstance
ti(0, ident
); // create dummy template instance
629 #define LOG_LEASTAS 0
632 printf("%s.leastAsSpecialized(%s)\n", toChars(), td2
->toChars());
635 // Set type arguments to dummy template instance to be types
636 // generated from the parameters to this template declaration
637 ti
.tiargs
= new Objects();
638 ti
.tiargs
->setDim(parameters
->dim
);
639 for (int i
= 0; i
< ti
.tiargs
->dim
; i
++)
641 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
643 void *p
= tp
->dummyArg();
645 ti
.tiargs
->data
[i
] = p
;
647 ti
.tiargs
->setDim(i
);
650 // Temporary Array to hold deduced types
651 //dedtypes.setDim(parameters->dim);
652 dedtypes
.setDim(td2
->parameters
->dim
);
654 // Attempt a type deduction
655 if (td2
->matchWithInstance(&ti
, &dedtypes
, 1))
657 /* A non-variadic template is more specialized than a
660 if (isVariadic() && !td2
->isVariadic())
664 printf(" matches, so is least as specialized\n");
670 printf(" doesn't match, so is not as specialized\n");
676 /*************************************************
677 * Match function arguments against a specific template function.
679 * targsi Expression/Type initial list of template arguments
680 * fargs arguments to function
682 * dedargs Expression/Type deduced template arguments
687 MATCH
TemplateDeclaration::deduceFunctionTemplateMatch(Objects
*targsi
, Expressions
*fargs
,
693 size_t nargsi
; // array size of targsi
696 MATCH match
= MATCHexact
;
697 FuncDeclaration
*fd
= onemember
->toAlias()->isFuncDeclaration();
698 TypeFunction
*fdtype
; // type of fd
699 TemplateTupleParameter
*tp
;
700 Objects dedtypes
; // for T:T*, the dedargs is the T*, dedtypes is the T
703 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
704 for (i
= 0; i
< fargs
->dim
; i
++)
705 { Expression
*e
= (Expression
*)fargs
->data
[i
];
706 printf("\tfarg[%d] is %s, type is %s\n", i
, e
->toChars(), e
->type
->toChars());
710 assert((size_t)scope
> 0x10000);
712 dedargs
->setDim(parameters
->dim
);
715 dedtypes
.setDim(parameters
->dim
);
718 // Set up scope for parameters
719 ScopeDsymbol
*paramsym
= new ScopeDsymbol();
720 paramsym
->parent
= scope
->parent
;
721 Scope
*paramscope
= scope
->push(paramsym
);
727 { // Set initial template arguments
729 nargsi
= targsi
->dim
;
730 if (nargsi
> parameters
->dim
)
733 dedargs
->setDim(nargsi
);
737 memcpy(dedargs
->data
, targsi
->data
, nargsi
* sizeof(*dedargs
->data
));
739 for (i
= 0; i
< nargsi
; i
++)
740 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
744 m
= tp
->matchArg(paramscope
, dedargs
, i
, parameters
, &dedtypes
, &sparam
);
745 //printf("\tdeduceType m = %d\n", m);
746 if (m
== MATCHnomatch
)
751 sparam
->semantic(paramscope
);
752 if (!paramscope
->insert(sparam
))
757 assert(fd
->type
->ty
== Tfunction
);
758 fdtype
= (TypeFunction
*)fd
->type
;
760 nfparams
= Argument::dim(fdtype
->parameters
); // number of function parameters
761 nfargs
= fargs
->dim
; // number of function arguments
763 /* Check for match of function arguments with variadic template
764 * parameter, such as:
766 * template Foo(T, A...) { void Foo(T t, A a); }
767 * void main() { Foo(1,2,3); }
770 if (tp
) // if variadic
772 if (nfparams
== 0) // if no function parameters
774 Tuple
*t
= new Tuple();
775 //printf("t = %p\n", t);
776 dedargs
->data
[parameters
->dim
- 1] = (void *)t
;
779 else if (nfargs
< nfparams
- 1)
783 /* Figure out which of the function parameters matches
784 * the tuple template parameter. Do this by matching
786 * Set the index of this function parameter to fptupindex.
788 for (fptupindex
= 0; fptupindex
< nfparams
; fptupindex
++)
790 Argument
*fparam
= (Argument
*)fdtype
->parameters
->data
[fptupindex
];
791 if (fparam
->type
->ty
!= Tident
)
793 TypeIdentifier
*tid
= (TypeIdentifier
*)fparam
->type
;
794 if (!tp
->ident
->equals(tid
->ident
) || tid
->idents
.dim
)
797 if (fdtype
->varargs
) // variadic function doesn't
798 goto Lnomatch
; // go with variadic template
800 /* The types of the function arguments
801 * now form the tuple argument.
803 Tuple
*t
= new Tuple();
804 dedargs
->data
[parameters
->dim
- 1] = (void *)t
;
806 tuple_dim
= nfargs
- (nfparams
- 1);
807 t
->objects
.setDim(tuple_dim
);
808 for (i
= 0; i
< tuple_dim
; i
++)
809 { Expression
*farg
= (Expression
*)fargs
->data
[fptupindex
+ i
];
810 t
->objects
.data
[i
] = (void *)farg
->type
;
819 if (nfparams
== nfargs
)
821 else if (nfargs
> nfparams
)
823 if (fdtype
->varargs
== 0)
824 goto Lnomatch
; // too many args, no match
825 match
= MATCHconvert
; // match ... with a conversion
829 // Loop through the function parameters
830 for (i
= 0; i
< nfparams
; i
++)
832 /* Skip over function parameters which wound up
833 * as part of a template tuple parameter.
836 { if (fptupindex
== nfparams
- 1)
842 Argument
*fparam
= Argument::getNth(fdtype
->parameters
, i
);
844 if (i
>= nfargs
) // if not enough arguments
846 if (fparam
->defaultArg
)
847 { /* Default arguments do not participate in template argument
854 { Expression
*farg
= (Expression
*)fargs
->data
[i
];
856 printf("\tfarg->type = %s\n", farg
->type
->toChars());
857 printf("\tfparam->type = %s\n", fparam
->type
->toChars());
861 m
= farg
->type
->deduceType(scope
, fparam
->type
, parameters
, &dedtypes
);
862 //printf("\tdeduceType m = %d\n", m);
864 /* If no match, see if there's a conversion to a delegate
866 if (!m
&& fparam
->type
->toBasetype()->ty
== Tdelegate
)
868 TypeDelegate
*td
= (TypeDelegate
*)fparam
->type
->toBasetype();
869 TypeFunction
*tf
= (TypeFunction
*)td
->next
;
871 if (!tf
->varargs
&& Argument::dim(tf
->parameters
) == 0)
873 m
= farg
->type
->deduceType(scope
, tf
->next
, parameters
, &dedtypes
);
874 if (!m
&& tf
->next
->toBasetype()->ty
== Tvoid
)
877 //printf("\tm2 = %d\n", m);
882 match
= m
; // pick worst match
886 if (!(fdtype
->varargs
== 2 && i
+ 1 == nfparams
))
889 /* Check for match with function parameter T...
891 Type
*t
= fparam
->type
;
894 // Perhaps we can do better with this, see TypeFunction::callMatch()
908 /* Fill in any missing arguments with their defaults.
910 for (i
= nargsi
; i
< dedargs
->dim
; i
++)
912 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
913 //printf("tp[%d] = %s\n", i, tp->ident->toChars());
914 /* For T:T*, the dedargs is the T*, dedtypes is the T
915 * But for function templates, we really need them to match
917 Object
*oarg
= (Object
*)dedargs
->data
[i
];
918 Object
*oded
= (Object
*)dedtypes
.data
[i
];
919 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
924 if (tp
->specialization())
925 { /* The specialization can work as long as afterwards
929 dedargs
->data
[i
] = (void *)oded
;
930 MATCH m2
= tp
->matchArg(paramscope
, dedargs
, i
, parameters
, &dedtypes
, &sparam
);
931 //printf("m2 = %d\n", m2);
935 match
= m2
; // pick worst match
936 if (dedtypes
.data
[i
] != oded
)
937 error("specialization not allowed for deduced parameter %s", tp
->ident
->toChars());
941 { oded
= tp
->defaultArg(paramscope
);
945 declareParameter(paramscope
, tp
, oded
);
946 dedargs
->data
[i
] = (void *)oded
;
951 for (i
= 0; i
< dedargs
->dim
; i
++)
952 { Type
*t
= (Type
*)dedargs
->data
[i
];
953 printf("\tdedargs[%d] = %d, %s\n", i
, t
->dyncast(), t
->toChars());
958 //printf("\tmatch %d\n", match);
963 //printf("\tnomatch\n");
967 /**************************************************
968 * Declare template parameter tp with value o.
971 void TemplateDeclaration::declareParameter(Scope
*sc
, TemplateParameter
*tp
, Object
*o
)
973 //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);
975 Type
*targ
= isType(o
);
976 Expression
*ea
= isExpression(o
);
977 Dsymbol
*sa
= isDsymbol(o
);
978 Tuple
*va
= isTuple(o
);
984 //printf("type %s\n", targ->toChars());
985 s
= new AliasDeclaration(0, tp
->ident
, targ
);
989 //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
990 s
= new AliasDeclaration(0, tp
->ident
, sa
);
994 // tdtypes.data[i] always matches ea here
995 Initializer
*init
= new ExpInitializer(loc
, ea
);
996 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
999 VarDeclaration
*v
= new VarDeclaration(loc
, tvp
->valType
, tp
->ident
, init
);
1000 v
->storage_class
= STCconst
;
1005 //printf("\ttuple\n");
1006 s
= new TupleDeclaration(loc
, tp
->ident
, &va
->objects
);
1016 error("declaration %s is already defined", tp
->ident
->toChars());
1020 /**************************************
1021 * Determine if TemplateDeclaration is variadic.
1024 TemplateTupleParameter
*isVariadic(TemplateParameters
*parameters
)
1025 { size_t dim
= parameters
->dim
;
1026 TemplateTupleParameter
*tp
= NULL
;
1029 tp
= ((TemplateParameter
*)parameters
->data
[dim
- 1])->isTemplateTupleParameter();
1033 TemplateTupleParameter
*TemplateDeclaration::isVariadic()
1035 return ::isVariadic(parameters
);
1038 /***********************************
1039 * We can overload templates.
1042 int TemplateDeclaration::isOverloadable()
1047 /*************************************************
1048 * Given function arguments, figure out which template function
1049 * to expand, and return that function.
1050 * If no match, give error message and return NULL.
1052 * sc instantiation scope
1053 * loc instantiation location
1054 * targsi initial list of template arguments
1055 * fargs arguments to function
1058 FuncDeclaration
*TemplateDeclaration::deduceFunctionTemplate(Scope
*sc
, Loc loc
,
1059 Objects
*targsi
, Expressions
*fargs
)
1061 MATCH m_best
= MATCHnomatch
;
1062 TemplateDeclaration
*td_ambig
= NULL
;
1063 TemplateDeclaration
*td_best
= NULL
;
1064 Objects
*tdargs
= new Objects();
1065 TemplateInstance
*ti
;
1066 FuncDeclaration
*fd
;
1069 printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
1070 printf(" targsi:\n");
1072 { for (int i
= 0; i
< targsi
->dim
; i
++)
1073 { Object
*arg
= (Object
*)targsi
->data
[i
];
1074 printf("\t%s\n", arg
->toChars());
1077 printf(" fargs:\n");
1078 for (int i
= 0; i
< fargs
->dim
; i
++)
1079 { Expression
*arg
= (Expression
*)fargs
->data
[i
];
1080 printf("\t%s %s\n", arg
->type
->toChars(), arg
->toChars());
1081 //printf("\tty = %d\n", arg->type->ty);
1085 for (TemplateDeclaration
*td
= this; td
; td
= td
->overnext
)
1089 error("forward reference to template %s", td
->toChars());
1092 if (!td
->onemember
|| !td
->onemember
->toAlias()->isFuncDeclaration())
1094 error("is not a function template");
1101 m
= td
->deduceFunctionTemplateMatch(targsi
, fargs
, &dedargs
);
1102 //printf("deduceFunctionTemplateMatch = %d\n", m);
1103 if (!m
) // if no match
1112 // Disambiguate by picking the most specialized TemplateDeclaration
1113 int c1
= td
->leastAsSpecialized(td_best
);
1114 int c2
= td_best
->leastAsSpecialized(td
);
1115 //printf("c1 = %d, c2 = %d\n", c1, c2);
1125 Lambig
: // td_best and td are ambiguous
1129 Ltd_best
: // td_best is the best match so far
1133 Ltd
: // td is the new best match
1135 assert((size_t)td
->scope
> 0x10000);
1138 tdargs
->setDim(dedargs
.dim
);
1139 memcpy(tdargs
->data
, dedargs
.data
, tdargs
->dim
* sizeof(void *));
1144 error(loc
, "does not match any template declaration");
1149 error(loc
, "%s matches more than one function template declaration, %s and %s",
1150 toChars(), td_best
->toChars(), td_ambig
->toChars());
1153 /* The best match is td_best with arguments tdargs.
1154 * Now instantiate the template.
1156 assert((size_t)td_best
->scope
> 0x10000);
1157 ti
= new TemplateInstance(loc
, td_best
, tdargs
);
1159 fd
= ti
->toAlias()->isFuncDeclaration();
1169 argExpTypesToCBuffer(&buf
, fargs
, &hgs
);
1170 error(loc
, "cannot deduce template function from argument types (%s)",
1176 void TemplateDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1178 #if 0 // Should handle template functions
1179 if (onemember
&& onemember
->isFuncDeclaration())
1180 buf
->writestring("foo ");
1182 buf
->writestring(kind());
1183 buf
->writeByte(' ');
1184 buf
->writestring(ident
->toChars());
1185 buf
->writeByte('(');
1186 for (int i
= 0; i
< parameters
->dim
; i
++)
1188 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1190 tp
= (TemplateParameter
*)origParameters
->data
[i
];
1192 buf
->writeByte(',');
1193 tp
->toCBuffer(buf
, hgs
);
1195 buf
->writeByte(')');
1201 buf
->writebyte('{');
1203 for (int i
= 0; i
< members
->dim
; i
++)
1205 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1206 s
->toCBuffer(buf
, hgs
);
1208 buf
->writebyte('}');
1215 char *TemplateDeclaration::toChars()
1219 memset(&hgs
, 0, sizeof(hgs
));
1220 buf
.writestring(ident
->toChars());
1222 for (int i
= 0; i
< parameters
->dim
; i
++)
1224 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1227 tp
->toCBuffer(&buf
, &hgs
);
1231 return (char *)buf
.extractData();
1234 /* ======================== Type ============================================ */
1237 * Given an identifier, figure out which TemplateParameter it is.
1238 * Return -1 if not found.
1241 int templateIdentifierLookup(Identifier
*id
, TemplateParameters
*parameters
)
1243 for (size_t i
= 0; i
< parameters
->dim
; i
++)
1244 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1246 if (tp
->ident
->equals(id
))
1252 int templateParameterLookup(Type
*tparam
, TemplateParameters
*parameters
)
1254 assert(tparam
->ty
== Tident
);
1255 TypeIdentifier
*tident
= (TypeIdentifier
*)tparam
;
1256 //printf("\ttident = '%s'\n", tident->toChars());
1257 if (tident
->idents
.dim
== 0)
1259 return templateIdentifierLookup(tident
->ident
, parameters
);
1264 /* These form the heart of template argument deduction.
1265 * Given 'this' being the type argument to the template instance,
1266 * it is matched against the template declaration parameter specialization
1267 * 'tparam' to determine the type to be used for the parameter.
1269 * template Foo(T:T*) // template declaration
1270 * Foo!(int*) // template instantiation
1274 * parameters = [ T:T* ] // Array of TemplateParameter's
1276 * dedtypes = [ int ] // Array of Expression/Type's
1279 MATCH
Type::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
,
1282 //printf("Type::deduceType()\n");
1283 //printf("\tthis = %d, ", ty); print();
1284 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1291 if (tparam
->ty
== Tident
)
1293 // Determine which parameter tparam is
1294 int i
= templateParameterLookup(tparam
, parameters
);
1299 /* BUG: what if tparam is a template instance, that
1300 * has as an argument another Tident?
1302 tparam
= tparam
->semantic(0, sc
);
1303 assert(tparam
->ty
!= Tident
);
1304 return deduceType(sc
, tparam
, parameters
, dedtypes
);
1307 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1309 // Found the corresponding parameter tp
1310 if (!tp
->isTemplateTypeParameter())
1312 Type
*at
= (Type
*)dedtypes
->data
[i
];
1315 dedtypes
->data
[i
] = (void *)this;
1320 else if (ty
== Tclass
&& at
->ty
== Tclass
)
1322 return (MATCH
) implicitConvTo(at
);
1324 else if (ty
== Tsarray
&& at
->ty
== Tarray
&&
1325 nextOf()->equals(at
->nextOf()))
1333 if (ty
!= tparam
->ty
)
1337 return nextOf()->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1343 return MATCHnomatch
;
1346 MATCH
TypeSArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
,
1350 printf("TypeSArray::deduceType()\n");
1351 printf("\tthis = %d, ", ty
); print();
1352 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1355 // Extra check that array dimensions must match
1358 if (tparam
->ty
== Tsarray
)
1360 TypeSArray
*tp
= (TypeSArray
*)tparam
;
1362 if (tp
->dim
->op
== TOKvar
&&
1363 ((VarExp
*)tp
->dim
)->var
->storage_class
& STCtemplateparameter
)
1364 { int i
= templateIdentifierLookup(((VarExp
*)tp
->dim
)->var
->ident
, parameters
);
1365 // This code matches code in TypeInstance::deduceType()
1368 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1369 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1372 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
1375 if (!dim
->equals(e
))
1379 { Type
*vt
= tvp
->valType
->semantic(0, sc
);
1380 MATCH m
= (MATCH
)dim
->implicitConvTo(vt
);
1383 dedtypes
->data
[i
] = dim
;
1386 else if (dim
->toInteger() != tp
->dim
->toInteger())
1387 return MATCHnomatch
;
1389 else if (tparam
->ty
== Taarray
)
1391 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1392 if (tp
->index
->ty
== Tident
)
1393 { TypeIdentifier
*tident
= (TypeIdentifier
*)tp
->index
;
1395 if (tident
->idents
.dim
== 0)
1396 { Identifier
*id
= tident
->ident
;
1398 for (size_t i
= 0; i
< parameters
->dim
; i
++)
1400 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1402 if (tp
->ident
->equals(id
))
1403 { // Found the corresponding template parameter
1404 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1405 if (!tvp
|| !tvp
->valType
->isintegral())
1408 if (dedtypes
->data
[i
])
1410 if (!dim
->equals((Object
*)dedtypes
->data
[i
]))
1414 { dedtypes
->data
[i
] = (void *)dim
;
1416 return next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1422 else if (tparam
->ty
== Tarray
)
1425 m
= next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1426 if (m
== MATCHexact
)
1431 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1434 return MATCHnomatch
;
1437 MATCH
TypeAArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1440 printf("TypeAArray::deduceType()\n");
1441 printf("\tthis = %d, ", ty
); print();
1442 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1445 // Extra check that index type must match
1446 if (tparam
&& tparam
->ty
== Taarray
)
1448 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1449 if (!index
->deduceType(sc
, tp
->index
, parameters
, dedtypes
))
1451 return MATCHnomatch
;
1454 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1457 MATCH
TypeFunction::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1459 //printf("TypeFunction::deduceType()\n");
1460 //printf("\tthis = %d, ", ty); print();
1461 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1463 // Extra check that function characteristics must match
1464 if (tparam
&& tparam
->ty
== Tfunction
)
1466 TypeFunction
*tp
= (TypeFunction
*)tparam
;
1467 if (varargs
!= tp
->varargs
||
1468 linkage
!= tp
->linkage
)
1469 return MATCHnomatch
;
1471 size_t nfargs
= Argument::dim(this->parameters
);
1472 size_t nfparams
= Argument::dim(tp
->parameters
);
1474 /* See if tuple match
1476 if (nfparams
> 0 && nfargs
>= nfparams
- 1)
1478 /* See if 'A' of the template parameter matches 'A'
1479 * of the type of the last function parameter.
1481 Argument
*fparam
= (Argument
*)tp
->parameters
->data
[nfparams
- 1];
1482 if (fparam
->type
->ty
!= Tident
)
1484 TypeIdentifier
*tid
= (TypeIdentifier
*)fparam
->type
;
1485 if (tid
->idents
.dim
)
1488 /* Look through parameters to find tuple matching tid->ident
1492 { if (tupi
== parameters
->dim
)
1494 TemplateParameter
*t
= (TemplateParameter
*)parameters
->data
[tupi
];
1495 TemplateTupleParameter
*tup
= t
->isTemplateTupleParameter();
1496 if (tup
&& tup
->ident
->equals(tid
->ident
))
1500 /* The types of the function arguments [nfparams - 1 .. nfargs]
1501 * now form the tuple argument.
1503 int tuple_dim
= nfargs
- (nfparams
- 1);
1505 /* See if existing tuple, and whether it matches or not
1507 Object
*o
= (Object
*)dedtypes
->data
[tupi
];
1509 { // Existing deduced argument must be a tuple, and must match
1510 Tuple
*t
= isTuple(o
);
1511 if (!t
|| t
->objects
.dim
!= tuple_dim
)
1512 return MATCHnomatch
;
1513 for (size_t i
= 0; i
< tuple_dim
; i
++)
1514 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1515 if (!arg
->type
->equals((Object
*)t
->objects
.data
[i
]))
1516 return MATCHnomatch
;
1520 { // Create new tuple
1521 Tuple
*t
= new Tuple();
1522 t
->objects
.setDim(tuple_dim
);
1523 for (size_t i
= 0; i
< tuple_dim
; i
++)
1524 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1525 t
->objects
.data
[i
] = (void *)arg
->type
;
1527 dedtypes
->data
[tupi
] = (void *)t
;
1529 nfparams
--; // don't consider the last parameter for type deduction
1534 if (nfargs
!= nfparams
)
1535 return MATCHnomatch
;
1537 for (size_t i
= 0; i
< nfparams
; i
++)
1539 Argument
*a
= Argument::getNth(this->parameters
, i
);
1540 Argument
*ap
= Argument::getNth(tp
->parameters
, i
);
1541 if (a
->storageClass
!= ap
->storageClass
||
1542 !a
->type
->deduceType(sc
, ap
->type
, parameters
, dedtypes
))
1543 return MATCHnomatch
;
1546 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1549 MATCH
TypeIdentifier::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1552 if (tparam
&& tparam
->ty
== Tident
)
1554 TypeIdentifier
*tp
= (TypeIdentifier
*)tparam
;
1556 for (int i
= 0; i
< idents
.dim
; i
++)
1558 Identifier
*id1
= (Identifier
*)idents
.data
[i
];
1559 Identifier
*id2
= (Identifier
*)tp
->idents
.data
[i
];
1561 if (!id1
->equals(id2
))
1562 return MATCHnomatch
;
1565 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1568 MATCH
TypeInstance::deduceType(Scope
*sc
,
1569 Type
*tparam
, TemplateParameters
*parameters
,
1572 //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
1573 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1576 if (tparam
&& tparam
->ty
== Tinstance
)
1578 TypeInstance
*tp
= (TypeInstance
*)tparam
;
1580 //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
1581 //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
1582 if (!tp
->tempinst
->tempdecl
)
1583 { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
1584 if (!tp
->tempinst
->name
->equals(tempinst
->name
))
1587 * template Foo(T : sa!(T), alias sa)
1589 int i
= templateIdentifierLookup(tp
->tempinst
->name
, parameters
);
1591 { /* Didn't find it as a parameter identifier. Try looking
1592 * it up and seeing if is an alias. See Bugzilla 1454
1594 Dsymbol
*s
= tempinst
->tempdecl
->scope
->search(0, tp
->tempinst
->name
, NULL
);
1598 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
1599 if (td
&& td
== tempinst
->tempdecl
)
1604 TemplateParameter
*tpx
= (TemplateParameter
*)parameters
->data
[i
];
1605 // This logic duplicates tpx->matchArg()
1606 TemplateAliasParameter
*ta
= tpx
->isTemplateAliasParameter();
1609 Dsymbol
*sa
= tempinst
->tempdecl
;
1612 if (ta
->specAlias
&& sa
!= ta
->specAlias
)
1614 if (dedtypes
->data
[i
])
1615 { // Must match already deduced symbol
1616 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
1621 dedtypes
->data
[i
] = sa
;
1624 else if (tempinst
->tempdecl
!= tp
->tempinst
->tempdecl
)
1628 if (tempinst
->tiargs
->dim
!= tp
->tempinst
->tiargs
->dim
)
1631 for (int i
= 0; i
< tempinst
->tiargs
->dim
; i
++)
1633 //printf("\ttest: tempinst->tiargs[%d]\n", i);
1635 Object
*o1
= (Object
*)tempinst
->tiargs
->data
[i
];
1636 Object
*o2
= (Object
*)tp
->tempinst
->tiargs
->data
[i
];
1638 Type
*t1
= isType(o1
);
1639 Type
*t2
= isType(o2
);
1641 Expression
*e1
= isExpression(o1
);
1642 Expression
*e2
= isExpression(o2
);
1645 if (t1
) printf("t1 = %s\n", t1
->toChars());
1646 if (t2
) printf("t2 = %s\n", t2
->toChars());
1647 if (e1
) printf("e1 = %s\n", e1
->toChars());
1648 if (e2
) printf("e2 = %s\n", e2
->toChars());
1653 if (!t1
->deduceType(sc
, t2
, parameters
, dedtypes
))
1658 if (!e1
->equals(e2
))
1659 { if (e2
->op
== TOKvar
)
1662 * (T:Number!(e2), int e2)
1664 j
= templateIdentifierLookup(((VarExp
*)e2
)->var
->ident
, parameters
);
1670 else if (e1
&& t2
&& t2
->ty
== Tident
)
1672 j
= templateParameterLookup(t2
, parameters
);
1676 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[j
];
1677 // BUG: use tp->matchArg() instead of the following
1678 TemplateValueParameter
*tv
= tp
->isTemplateValueParameter();
1681 Expression
*e
= (Expression
*)dedtypes
->data
[j
];
1688 { Type
*vt
= tv
->valType
->semantic(0, sc
);
1689 MATCH m
= (MATCH
)e1
->implicitConvTo(vt
);
1692 dedtypes
->data
[j
] = e1
;
1695 // BUG: Need to handle alias and tuple parameters
1700 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1703 return MATCHnomatch
;
1706 MATCH
TypeStruct::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1708 //printf("TypeStruct::deduceType()\n");
1709 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
1710 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1712 /* If this struct is a template struct, and we're matching
1713 * it against a template instance, convert the struct type
1714 * to a template instance, too, and try again.
1716 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1718 if (tparam
&& tparam
->ty
== Tinstance
)
1720 if (ti
&& ti
->toAlias() == sym
)
1722 TypeInstance
*t
= new TypeInstance(0, ti
);
1723 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1726 /* Match things like:
1729 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1730 if (tpi
->idents
.dim
)
1731 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1732 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1734 Type
*tparent
= sym
->parent
->getType();
1737 /* Slice off the .foo in S!(T).foo
1740 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1749 if (tparam
&& tparam
->ty
== Tstruct
)
1751 TypeStruct
*tp
= (TypeStruct
*)tparam
;
1754 return MATCHnomatch
;
1756 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1759 MATCH
TypeEnum::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1762 if (tparam
&& tparam
->ty
== Tenum
)
1764 TypeEnum
*tp
= (TypeEnum
*)tparam
;
1767 return MATCHnomatch
;
1769 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1772 MATCH
TypeTypedef::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1775 if (tparam
&& tparam
->ty
== Ttypedef
)
1777 TypeTypedef
*tp
= (TypeTypedef
*)tparam
;
1780 return MATCHnomatch
;
1782 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1785 MATCH
TypeClass::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1787 //printf("TypeClass::deduceType(this = %s)\n", toChars());
1789 /* If this class is a template class, and we're matching
1790 * it against a template instance, convert the class type
1791 * to a template instance, too, and try again.
1793 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1795 if (tparam
&& tparam
->ty
== Tinstance
)
1797 if (ti
&& ti
->toAlias() == sym
)
1799 TypeInstance
*t
= new TypeInstance(0, ti
);
1800 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1803 /* Match things like:
1806 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1807 if (tpi
->idents
.dim
)
1808 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1809 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1811 Type
*tparent
= sym
->parent
->getType();
1814 /* Slice off the .foo in S!(T).foo
1817 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1826 if (tparam
&& tparam
->ty
== Tclass
)
1828 TypeClass
*tp
= (TypeClass
*)tparam
;
1830 //printf("\t%d\n", (MATCH) implicitConvTo(tp));
1831 return (MATCH
) implicitConvTo(tp
);
1833 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1836 /* ======================== TemplateParameter =============================== */
1838 TemplateParameter::TemplateParameter(Loc loc
, Identifier
*ident
)
1841 this->ident
= ident
;
1842 this->sparam
= NULL
;
1845 TemplateTypeParameter
*TemplateParameter::isTemplateTypeParameter()
1850 TemplateValueParameter
*TemplateParameter::isTemplateValueParameter()
1855 TemplateAliasParameter
*TemplateParameter::isTemplateAliasParameter()
1860 TemplateTupleParameter
*TemplateParameter::isTemplateTupleParameter()
1866 TemplateThisParameter
*TemplateParameter::isTemplateThisParameter()
1872 /* ======================== TemplateTypeParameter =========================== */
1876 TemplateTypeParameter::TemplateTypeParameter(Loc loc
, Identifier
*ident
, Type
*specType
,
1878 : TemplateParameter(loc
, ident
)
1880 this->ident
= ident
;
1881 this->specType
= specType
;
1882 this->defaultType
= defaultType
;
1885 TemplateTypeParameter
*TemplateTypeParameter::isTemplateTypeParameter()
1890 TemplateParameter
*TemplateTypeParameter::syntaxCopy()
1892 TemplateTypeParameter
*tp
= new TemplateTypeParameter(loc
, ident
, specType
, defaultType
);
1894 tp
->specType
= specType
->syntaxCopy();
1896 tp
->defaultType
= defaultType
->syntaxCopy();
1900 void TemplateTypeParameter::declareParameter(Scope
*sc
)
1902 //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
1903 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
1904 sparam
= new AliasDeclaration(loc
, ident
, ti
);
1905 if (!sc
->insert(sparam
))
1906 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
1909 void TemplateTypeParameter::semantic(Scope
*sc
)
1911 //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
1914 specType
= specType
->semantic(loc
, sc
);
1916 #if 0 // Don't do semantic() until instantiation
1919 defaultType
= defaultType
->semantic(loc
, sc
);
1924 /****************************************
1925 * Determine if two TemplateParameters are the same
1926 * as far as TemplateDeclaration overloading goes.
1932 int TemplateTypeParameter::overloadMatch(TemplateParameter
*tp
)
1934 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
1938 if (specType
!= ttp
->specType
)
1941 if (specType
&& !specType
->equals(ttp
->specType
))
1951 /*******************************************
1952 * Match to a particular TemplateParameter.
1955 * tiargs[] actual arguments to template instance
1956 * parameters[] template parameters
1957 * dedtypes[] deduced arguments to template instance
1958 * *psparam set to symbol declared and initialized to dedtypes[i]
1961 MATCH
TemplateTypeParameter::matchArg(Scope
*sc
, Objects
*tiargs
,
1962 int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
1963 Declaration
**psparam
)
1965 //printf("TemplateTypeParameter::matchArg()\n");
1968 MATCH m
= MATCHexact
;
1971 if (i
< tiargs
->dim
)
1972 oarg
= (Object
*)tiargs
->data
[i
];
1974 { // Get default argument instead
1975 oarg
= defaultArg(sc
);
1977 { assert(i
< dedtypes
->dim
);
1978 // It might have already been deduced
1979 oarg
= (Object
*)dedtypes
->data
[i
];
1988 //printf("ta is %s\n", ta->toChars());
1990 t
= (Type
*)dedtypes
->data
[i
];
1994 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
1995 MATCH m2
= ta
->deduceType(sc
, specType
, parameters
, dedtypes
);
1996 if (m2
== MATCHnomatch
)
1997 { //printf("\tfailed deduceType\n");
2003 t
= (Type
*)dedtypes
->data
[i
];
2007 // So that matches with specializations are better
2010 { // Must match already deduced type
2014 { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
2022 dedtypes
->data
[i
] = ta
;
2025 *psparam
= new AliasDeclaration(loc
, ident
, t
);
2026 //printf("\tm = %d\n", m);
2031 //printf("\tm = %d\n", MATCHnomatch);
2032 return MATCHnomatch
;
2036 void TemplateTypeParameter::print(Object
*oarg
, Object
*oded
)
2038 fprintf(stderr
, " %s\n", ident
->toChars());
2040 Type
*t
= isType(oarg
);
2041 Type
*ta
= isType(oded
);
2046 fprintf(stderr
, "\tSpecialization: %s\n", specType
->toChars());
2048 fprintf(stderr
, "\tDefault: %s\n", defaultType
->toChars());
2049 fprintf(stderr
, "\tArgument: %s\n", t
? t
->toChars() : "NULL");
2050 fprintf(stderr
, "\tDeduced Type: %s\n", ta
->toChars());
2054 void TemplateTypeParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2056 buf
->writestring(ident
->toChars());
2059 buf
->writestring(" : ");
2060 specType
->toCBuffer(buf
, NULL
, hgs
);
2064 buf
->writestring(" = ");
2065 defaultType
->toCBuffer(buf
, NULL
, hgs
);
2070 void *TemplateTypeParameter::dummyArg()
2076 { // Use this for alias-parameter's too (?)
2077 t
= new TypeIdentifier(loc
, ident
);
2083 Object
*TemplateTypeParameter::specialization()
2089 Object
*TemplateTypeParameter::defaultArg(Scope
*sc
)
2096 t
= t
->syntaxCopy();
2097 t
= t
->semantic(loc
, sc
);
2102 /* ======================== TemplateThisParameter =========================== */
2107 TemplateThisParameter::TemplateThisParameter(Loc loc
, Identifier
*ident
,
2110 : TemplateTypeParameter(loc
, ident
, specType
, defaultType
)
2114 TemplateThisParameter
*TemplateThisParameter::isTemplateThisParameter()
2119 TemplateParameter
*TemplateThisParameter::syntaxCopy()
2121 TemplateThisParameter
*tp
= new TemplateThisParameter(loc
, ident
, specType
, defaultType
);
2123 tp
->specType
= specType
->syntaxCopy();
2125 tp
->defaultType
= defaultType
->syntaxCopy();
2129 void TemplateThisParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2131 buf
->writestring("this ");
2132 TemplateTypeParameter::toCBuffer(buf
, hgs
);
2136 /* ======================== TemplateAliasParameter ========================== */
2140 Dsymbol
*TemplateAliasParameter::sdummy
= NULL
;
2142 TemplateAliasParameter::TemplateAliasParameter(Loc loc
, Identifier
*ident
, Type
*specAliasT
, Type
*defaultAlias
)
2143 : TemplateParameter(loc
, ident
)
2145 this->ident
= ident
;
2146 this->specAliasT
= specAliasT
;
2147 this->defaultAlias
= defaultAlias
;
2149 this->specAlias
= NULL
;
2152 TemplateAliasParameter
*TemplateAliasParameter::isTemplateAliasParameter()
2157 TemplateParameter
*TemplateAliasParameter::syntaxCopy()
2159 TemplateAliasParameter
*tp
= new TemplateAliasParameter(loc
, ident
, specAliasT
, defaultAlias
);
2161 tp
->specAliasT
= specAliasT
->syntaxCopy();
2163 tp
->defaultAlias
= defaultAlias
->syntaxCopy();
2167 void TemplateAliasParameter::declareParameter(Scope
*sc
)
2169 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2170 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2171 if (!sc
->insert(sparam
))
2172 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2175 void TemplateAliasParameter::semantic(Scope
*sc
)
2179 specAlias
= specAliasT
->toDsymbol(sc
);
2181 error("%s is not a symbol", specAliasT
->toChars());
2183 #if 0 // Don't do semantic() until instantiation
2185 defaultAlias
= defaultAlias
->semantic(loc
, sc
);
2189 int TemplateAliasParameter::overloadMatch(TemplateParameter
*tp
)
2191 TemplateAliasParameter
*tap
= tp
->isTemplateAliasParameter();
2195 if (specAlias
!= tap
->specAlias
)
2205 MATCH
TemplateAliasParameter::matchArg(Scope
*sc
,
2206 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2207 Declaration
**psparam
)
2213 //printf("TemplateAliasParameter::matchArg()\n");
2215 if (i
< tiargs
->dim
)
2216 oarg
= (Object
*)tiargs
->data
[i
];
2218 { // Get default argument instead
2219 oarg
= defaultArg(sc
);
2221 { assert(i
< dedtypes
->dim
);
2222 // It might have already been deduced
2223 oarg
= (Object
*)dedtypes
->data
[i
];
2229 sa
= getDsymbol(oarg
);
2235 if (!sa
|| sa
== sdummy
)
2237 if (sa
!= specAlias
)
2240 else if (dedtypes
->data
[i
])
2241 { // Must match already deduced symbol
2242 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
2247 dedtypes
->data
[i
] = sa
;
2249 *psparam
= new AliasDeclaration(loc
, ident
, sa
);
2254 return MATCHnomatch
;
2258 void TemplateAliasParameter::print(Object
*oarg
, Object
*oded
)
2260 fprintf(stderr
, " %s\n", ident
->toChars());
2262 Dsymbol
*sa
= isDsymbol(oded
);
2265 fprintf(stderr
, "\tArgument alias: %s\n", sa
->toChars());
2268 void TemplateAliasParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2270 buf
->writestring("alias ");
2271 buf
->writestring(ident
->toChars());
2274 buf
->writestring(" : ");
2275 specAliasT
->toCBuffer(buf
, NULL
, hgs
);
2279 buf
->writestring(" = ");
2280 defaultAlias
->toCBuffer(buf
, NULL
, hgs
);
2285 void *TemplateAliasParameter::dummyArg()
2292 sdummy
= new Dsymbol();
2299 Object
*TemplateAliasParameter::specialization()
2305 Object
*TemplateAliasParameter::defaultArg(Scope
*sc
)
2311 s
= defaultAlias
->toDsymbol(sc
);
2313 error("%s is not a symbol", defaultAlias
->toChars());
2318 /* ======================== TemplateValueParameter ========================== */
2322 Expression
*TemplateValueParameter::edummy
= NULL
;
2324 TemplateValueParameter::TemplateValueParameter(Loc loc
, Identifier
*ident
, Type
*valType
,
2325 Expression
*specValue
, Expression
*defaultValue
)
2326 : TemplateParameter(loc
, ident
)
2328 this->ident
= ident
;
2329 this->valType
= valType
;
2330 this->specValue
= specValue
;
2331 this->defaultValue
= defaultValue
;
2334 TemplateValueParameter
*TemplateValueParameter::isTemplateValueParameter()
2339 TemplateParameter
*TemplateValueParameter::syntaxCopy()
2341 TemplateValueParameter
*tp
=
2342 new TemplateValueParameter(loc
, ident
, valType
, specValue
, defaultValue
);
2343 tp
->valType
= valType
->syntaxCopy();
2345 tp
->specValue
= specValue
->syntaxCopy();
2347 tp
->defaultValue
= defaultValue
->syntaxCopy();
2351 void TemplateValueParameter::declareParameter(Scope
*sc
)
2353 VarDeclaration
*v
= new VarDeclaration(loc
, valType
, ident
, NULL
);
2354 v
->storage_class
= STCtemplateparameter
;
2356 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2360 void TemplateValueParameter::semantic(Scope
*sc
)
2362 sparam
->semantic(sc
);
2363 valType
= valType
->semantic(loc
, sc
);
2364 if (!(valType
->isintegral() || valType
->isfloating() || valType
->isString()) &&
2365 valType
->ty
!= Tident
)
2366 error(loc
, "arithmetic/string type expected for value-parameter, not %s", valType
->toChars());
2369 { Expression
*e
= specValue
;
2371 e
= e
->semantic(sc
);
2372 e
= e
->implicitCastTo(sc
, valType
);
2373 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2374 if (e
->op
== TOKint64
|| e
->op
== TOKfloat64
||
2375 e
->op
== TOKcomplex80
|| e
->op
== TOKnull
|| e
->op
== TOKstring
)
2380 #if 0 // defer semantic analysis to arg match
2382 { Expression
*e
= defaultValue
;
2384 e
= e
->semantic(sc
);
2385 e
= e
->implicitCastTo(sc
, valType
);
2386 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2387 if (e
->op
== TOKint64
)
2394 int TemplateValueParameter::overloadMatch(TemplateParameter
*tp
)
2396 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
2400 if (valType
!= tvp
->valType
)
2403 if (valType
&& !valType
->equals(tvp
->valType
))
2406 if (specValue
!= tvp
->specValue
)
2417 MATCH
TemplateValueParameter::matchArg(Scope
*sc
,
2418 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2419 Declaration
**psparam
)
2421 //printf("TemplateValueParameter::matchArg()\n");
2424 Declaration
*sparam
;
2425 MATCH m
= MATCHexact
;
2429 if (i
< tiargs
->dim
)
2430 oarg
= (Object
*)tiargs
->data
[i
];
2432 { // Get default argument instead
2433 oarg
= defaultArg(sc
);
2435 { assert(i
< dedtypes
->dim
);
2436 // It might have already been deduced
2437 oarg
= (Object
*)dedtypes
->data
[i
];
2443 ei
= isExpression(oarg
);
2451 if (!ei
|| ei
== edummy
)
2454 Expression
*e
= specValue
;
2456 e
= e
->semantic(sc
);
2457 e
= e
->implicitCastTo(sc
, valType
);
2458 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2460 ei
= ei
->syntaxCopy();
2461 ei
= ei
->semantic(sc
);
2462 ei
= ei
->optimize(WANTvalue
| WANTinterpret
);
2463 //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars());
2464 //printf("e : %s, %s\n", e->toChars(), e->type->toChars());
2468 else if (dedtypes
->data
[i
])
2469 { // Must match already deduced value
2470 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
2472 if (!ei
|| !ei
->equals(e
))
2476 //printf("valType: %s, ty = %d\n", valType->toChars(), valType->ty);
2477 vt
= valType
->semantic(0, sc
);
2478 //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars());
2481 m
= (MATCH
)ei
->implicitConvTo(vt
);
2482 //printf("m: %d\n", m);
2486 dedtypes
->data
[i
] = ei
;
2488 init
= new ExpInitializer(loc
, ei
);
2489 sparam
= new VarDeclaration(loc
, vt
, ident
, init
);
2490 sparam
->storage_class
= STCconst
;
2495 //printf("\tno match\n");
2497 return MATCHnomatch
;
2501 void TemplateValueParameter::print(Object
*oarg
, Object
*oded
)
2503 fprintf(stderr
, " %s\n", ident
->toChars());
2505 Expression
*ea
= isExpression(oded
);
2508 fprintf(stderr
, "\tSpecialization: %s\n", specValue
->toChars());
2509 fprintf(stderr
, "\tArgument Value: %s\n", ea
? ea
->toChars() : "NULL");
2513 void TemplateValueParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2515 valType
->toCBuffer(buf
, ident
, hgs
);
2518 buf
->writestring(" : ");
2519 specValue
->toCBuffer(buf
, hgs
);
2523 buf
->writestring(" = ");
2524 defaultValue
->toCBuffer(buf
, hgs
);
2529 void *TemplateValueParameter::dummyArg()
2535 // Create a dummy value
2537 edummy
= valType
->defaultInit();
2544 Object
*TemplateValueParameter::specialization()
2550 Object
*TemplateValueParameter::defaultArg(Scope
*sc
)
2552 Expression
*e
= defaultValue
;
2555 e
= e
->syntaxCopy();
2556 e
= e
->semantic(sc
);
2558 if (e
->op
== TOKdefault
)
2559 { DefaultInitExp
*de
= (DefaultInitExp
*)e
;
2560 e
= de
->resolve(loc
, sc
);
2567 /* ======================== TemplateTupleParameter ========================== */
2569 // variadic-parameter
2571 TemplateTupleParameter::TemplateTupleParameter(Loc loc
, Identifier
*ident
)
2572 : TemplateParameter(loc
, ident
)
2574 this->ident
= ident
;
2577 TemplateTupleParameter
*TemplateTupleParameter::isTemplateTupleParameter()
2582 TemplateParameter
*TemplateTupleParameter::syntaxCopy()
2584 TemplateTupleParameter
*tp
= new TemplateTupleParameter(loc
, ident
);
2588 void TemplateTupleParameter::declareParameter(Scope
*sc
)
2590 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2591 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2592 if (!sc
->insert(sparam
))
2593 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2596 void TemplateTupleParameter::semantic(Scope
*sc
)
2600 int TemplateTupleParameter::overloadMatch(TemplateParameter
*tp
)
2602 TemplateTupleParameter
*tvp
= tp
->isTemplateTupleParameter();
2613 MATCH
TemplateTupleParameter::matchArg(Scope
*sc
,
2614 Objects
*tiargs
, int i
, TemplateParameters
*parameters
,
2616 Declaration
**psparam
)
2618 //printf("TemplateTupleParameter::matchArg()\n");
2620 /* The rest of the actual arguments (tiargs[]) form the match
2621 * for the variadic parameter.
2623 assert(i
+ 1 == dedtypes
->dim
); // must be the last one
2625 if (i
+ 1 == tiargs
->dim
&& isTuple((Object
*)tiargs
->data
[i
]))
2626 ovar
= isTuple((Object
*)tiargs
->data
[i
]);
2630 //printf("ovar = %p\n", ovar);
2631 if (i
< tiargs
->dim
)
2633 //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
2634 ovar
->objects
.setDim(tiargs
->dim
- i
);
2635 for (size_t j
= 0; j
< ovar
->objects
.dim
; j
++)
2636 ovar
->objects
.data
[j
] = tiargs
->data
[i
+ j
];
2639 *psparam
= new TupleDeclaration(loc
, ident
, &ovar
->objects
);
2640 dedtypes
->data
[i
] = (void *)ovar
;
2645 void TemplateTupleParameter::print(Object
*oarg
, Object
*oded
)
2647 printf(" %s... [", ident
->toChars());
2648 Tuple
*v
= isTuple(oded
);
2651 //printf("|%d| ", v->objects.dim);
2652 for (int i
= 0; i
< v
->objects
.dim
; i
++)
2657 Object
*o
= (Object
*)v
->objects
.data
[i
];
2659 Dsymbol
*sa
= isDsymbol(o
);
2661 printf("alias: %s", sa
->toChars());
2663 Type
*ta
= isType(o
);
2665 printf("type: %s", ta
->toChars());
2667 Expression
*ea
= isExpression(o
);
2669 printf("exp: %s", ea
->toChars());
2671 assert(!isTuple(o
)); // no nested Tuple arguments
2677 void TemplateTupleParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2679 buf
->writestring(ident
->toChars());
2680 buf
->writestring("...");
2684 void *TemplateTupleParameter::dummyArg()
2690 Object
*TemplateTupleParameter::specialization()
2696 Object
*TemplateTupleParameter::defaultArg(Scope
*sc
)
2701 /* ======================== TemplateInstance ================================ */
2703 TemplateInstance::TemplateInstance(Loc loc
, Identifier
*ident
)
2704 : ScopeDsymbol(NULL
)
2707 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident
? ident
->toChars() : "null");
2711 this->tiargs
= NULL
;
2712 this->tempdecl
= NULL
;
2714 this->argsym
= NULL
;
2715 this->aliasdecl
= NULL
;
2716 this->semanticdone
= 0;
2717 this->withsym
= NULL
;
2720 this->objFileModule
= NULL
;
2722 this->havetempdecl
= 0;
2723 this->isnested
= NULL
;
2728 TemplateInstance::TemplateInstance(Loc loc
, TemplateDeclaration
*td
, Objects
*tiargs
)
2729 : ScopeDsymbol(NULL
)
2732 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td
->toChars());
2735 this->name
= td
->ident
;
2736 this->tiargs
= tiargs
;
2737 this->tempdecl
= td
;
2739 this->argsym
= NULL
;
2740 this->aliasdecl
= NULL
;
2741 this->semanticdone
= 0;
2742 this->withsym
= NULL
;
2745 this->objFileModule
= NULL
;
2747 this->havetempdecl
= 1;
2748 this->isnested
= NULL
;
2751 assert((size_t)tempdecl
->scope
> 0x10000);
2755 Objects
*TemplateInstance::arraySyntaxCopy(Objects
*objs
)
2759 { a
= new Objects();
2760 a
->setDim(objs
->dim
);
2761 for (size_t i
= 0; i
< objs
->dim
; i
++)
2763 Type
*ta
= isType((Object
*)objs
->data
[i
]);
2765 a
->data
[i
] = ta
->syntaxCopy();
2768 Expression
*ea
= isExpression((Object
*)objs
->data
[i
]);
2770 a
->data
[i
] = ea
->syntaxCopy();
2777 Dsymbol
*TemplateInstance::syntaxCopy(Dsymbol
*s
)
2779 TemplateInstance
*ti
;
2783 ti
= (TemplateInstance
*)s
;
2785 ti
= new TemplateInstance(loc
, name
);
2787 ti
->tiargs
= arraySyntaxCopy(tiargs
);
2789 ScopeDsymbol::syntaxCopy(ti
);
2795 #include "d-dmd-gcc.h"
2798 void TemplateInstance::semantic(Scope
*sc
)
2804 /* Trying to soldier on rarely generates useful messages
2812 printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
2816 fprintf(stderr, "ti '%s' (%p), belongs in '%s'\n", toChars(), this,
2817 sc->module->toPrettyChars());
2819 fprintf(stderr, " -- really '%s' (%p)\n", inst->toChars(), inst);
2821 fprintf(stderr, " -- doing semantic\n");
2825 if (inst
) // if semantic() was already run
2828 printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst
->toChars(), inst
);
2833 if (semanticdone
!= 0)
2835 error(loc
, "recursive template expansion");
2842 printf("\tdo semantic\n");
2846 assert((size_t)tempdecl
->scope
> 0x10000);
2848 tdtypes
.setDim(tempdecl
->parameters
->dim
);
2849 if (!tempdecl
->matchWithInstance(this, &tdtypes
, 0))
2851 error("incompatible arguments for template instantiation");
2858 // Run semantic on each argument, place results in tiargs[]
2861 tempdecl
= findTemplateDeclaration(sc
);
2863 tempdecl
= findBestMatch(sc
);
2864 if (!tempdecl
|| global
.errors
)
2866 //printf("error return %p, %d\n", tempdecl, global.errors);
2867 return; // error recovery
2873 /* See if there is an existing TemplateInstantiation that already
2874 * implements the typeargs. If so, just refer to that one instead.
2877 for (size_t i
= 0; i
< tempdecl
->instances
.dim
; i
++)
2879 TemplateInstance
*ti
= (TemplateInstance
*)tempdecl
->instances
.data
[i
];
2881 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i
, ti
, ti
->toChars());
2883 assert(tdtypes
.dim
== ti
->tdtypes
.dim
);
2885 // Nesting must match
2886 if (isnested
!= ti
->isnested
)
2889 if (isnested
&& sc
->parent
!= ti
->parent
)
2892 for (size_t j
= 0; j
< tdtypes
.dim
; j
++)
2893 { Object
*o1
= (Object
*)tdtypes
.data
[j
];
2894 Object
*o2
= (Object
*)ti
->tdtypes
.data
[j
];
2895 if (!match(o1
, o2
, tempdecl
, sc
))
2901 parent
= ti
->parent
;
2903 printf("\tit's a match with instance %p\n", inst
);
2911 /* So, we need to implement 'this' instance.
2914 printf("\timplement template instance '%s'\n", toChars());
2916 unsigned errorsave
= global
.errors
;
2918 int tempdecl_instance_idx
= tempdecl
->instances
.dim
;
2919 tempdecl
->instances
.push(this);
2920 parent
= tempdecl
->parent
;
2921 //printf("parent = '%s'\n", parent->kind());
2923 ident
= genIdent(); // need an identifier for name mangling purposes.
2929 //printf("parent = '%s'\n", parent->kind());
2931 // Add 'this' to the enclosing scope's members[] so the semantic routines
2932 // will get called on the instance members
2934 int dosemantic3
= 0;
2938 /* For "all" and "private" template modes, templates are always
2939 emitted. Problem: This picks up templates that aren't even
2940 needed in the current module. */
2942 if (d_gcc_force_templates())
2944 //fprintf(stderr, "\t0: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
2945 objFileModule
= d_gcc_get_output_module();
2946 a
= objFileModule
->members
;
2951 if (sc
->scopesym
&& sc
->scopesym
->members
&& !sc
->scopesym
->isTemplateMixin())
2953 //printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
2954 a
= sc
->scopesym
->members
;
2957 Dsymbol
* p
= sc
->scopesym
;
2959 TemplateInstance
* i
;
2962 if ( (i
= p
->isTemplateInstance()) ) {
2963 if (i
->objFileModule
) {
2964 objFileModule
= i
->objFileModule
;
2967 } else if ( (m
= p
->isModule()) ) {
2968 objFileModule
= m
; // %% importedFrom ?
2973 // fprintf(stderr, "\t1: adding %s to module %s via %s %s\n", tempdecl->toChars(), objFileModule?objFileModule->toChars():"", sc->scopesym->kind(), sc->scopesym->toChars());
2978 { Module
*m
= sc
->module
->importedFrom
;
2979 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
2981 if (m
->semanticdone
>= 3)
2987 for (int i
= 0; 1; i
++)
2994 if (this == (Dsymbol
*)a
->data
[i
]) // if already in Array
3000 // Copy the syntax trees from the TemplateDeclaration
3001 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
3003 // Create our own scope for the template parameters
3004 Scope
*scope
= tempdecl
->scope
;
3007 error("forward reference to template declaration %s\n", tempdecl
->toChars());
3012 printf("\tcreate scope for template parameters '%s'\n", toChars());
3014 argsym
= new ScopeDsymbol();
3015 argsym
->parent
= scope
->parent
;
3016 scope
= scope
->push(argsym
);
3018 // Declare each template parameter as an alias for the argument type
3019 declareParameters(scope
);
3021 // Add members of template instance to template instance symbol table
3022 // parent = scope->scopesym;
3023 symtab
= new DsymbolTable();
3025 for (int i
= 0; i
< members
->dim
; i
++)
3027 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3029 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i
, s
->toChars(), s
, s
->kind(), this->toChars(), memnum
);
3031 memnum
|= s
->addMember(scope
, this, memnum
);
3034 printf("adding members done\n");
3037 /* See if there is only one member of template instance, and that
3038 * member has the same name as the template instance.
3039 * If so, this template instance becomes an alias for that member.
3041 //printf("members->dim = %d\n", members->dim);
3045 if (Dsymbol::oneMembers(members
, &s
) && s
)
3047 //printf("s->kind = '%s'\n", s->kind());
3049 //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
3050 if (s
->ident
&& s
->ident
->equals(tempdecl
->ident
))
3052 //printf("setting aliasdecl\n");
3053 aliasdecl
= new AliasDeclaration(loc
, s
->ident
, s
);
3058 // Do semantic() analysis on template instance members
3060 printf("\tdo semantic() on template instance members '%s'\n", toChars());
3063 sc2
= scope
->push(this);
3064 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
3065 sc2
->parent
= /*isnested ? sc->parent :*/ this;
3073 for (int i
= 0; i
< members
->dim
; i
++)
3075 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3076 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
3077 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
3079 // s->parent = sc->parent;
3080 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3082 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3083 sc2
->module
->runDeferredSemantic();
3088 __except (__ehfilter(GetExceptionInformation()))
3090 global
.gag
= 0; // ensure error message gets printed
3091 error("recursive expansion");
3097 /* If any of the instantiation members didn't get semantic() run
3098 * on them due to forward references, we cannot run semantic2()
3099 * or semantic3() yet.
3101 for (size_t i
= 0; i
< Module::deferred
.dim
; i
++)
3102 { Dsymbol
*sd
= (Dsymbol
*)Module::deferred
.data
[i
];
3104 if (sd
->parent
== this)
3105 goto Laftersemantic
;
3108 /* The problem is when to parse the initializer for a variable.
3109 * Perhaps VarDeclaration::semantic() should do it like it does
3110 * for initializers inside a function.
3112 // if (sc->parent->isFuncDeclaration())
3114 /* BUG 782: this has problems if the classes this depends on
3115 * are forward referenced. Find a way to defer semantic()
3120 if (sc
->func
|| dosemantic3
)
3130 // Give additional context info if error occurred during instantiation
3131 if (global
.errors
!= errorsave
)
3133 error("error instantiating");
3136 tempdecl
->instances
.remove(tempdecl_instance_idx
);
3140 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3145 void TemplateInstance::semanticTiargs(Scope
*sc
)
3147 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3148 semanticTiargs(loc
, sc
, tiargs
);
3151 void TemplateInstance::semanticTiargs(Loc loc
, Scope
*sc
, Objects
*tiargs
)
3153 // Run semantic on each argument, place results in tiargs[]
3154 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3157 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3159 Object
*o
= (Object
*)tiargs
->data
[j
];
3160 Type
*ta
= isType(o
);
3161 Expression
*ea
= isExpression(o
);
3162 Dsymbol
*sa
= isDsymbol(o
);
3164 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
3167 //printf("type %s\n", ta->toChars());
3168 // It might really be an Expression or an Alias
3169 ta
->resolve(loc
, sc
, &ea
, &ta
, &sa
);
3172 ea
= ea
->semantic(sc
);
3173 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3174 tiargs
->data
[j
] = ea
;
3177 { tiargs
->data
[j
] = sa
;
3178 TupleDeclaration
*d
= sa
->toAlias()->isTupleDeclaration();
3181 size_t dim
= d
->objects
->dim
;
3183 tiargs
->insert(j
, d
->objects
);
3189 if (ta
->ty
== Ttuple
)
3191 TypeTuple
*tt
= (TypeTuple
*)ta
;
3192 size_t dim
= tt
->arguments
->dim
;
3195 { tiargs
->reserve(dim
);
3196 for (size_t i
= 0; i
< dim
; i
++)
3197 { Argument
*arg
= (Argument
*)tt
->arguments
->data
[i
];
3198 tiargs
->insert(j
+ i
, arg
->type
);
3204 tiargs
->data
[j
] = ta
;
3208 assert(global
.errors
);
3209 tiargs
->data
[j
] = Type::terror
;
3215 { assert(global
.errors
);
3216 ea
= new IntegerExp(0);
3219 ea
= ea
->semantic(sc
);
3220 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3221 tiargs
->data
[j
] = ea
;
3222 if (ea
->op
== TOKtype
)
3223 tiargs
->data
[j
] = ea
->type
;
3232 //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
3235 printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
3236 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3238 Object
*o
= (Object
*)tiargs
->data
[j
];
3239 Type
*ta
= isType(o
);
3240 Expression
*ea
= isExpression(o
);
3241 Dsymbol
*sa
= isDsymbol(o
);
3242 Tuple
*va
= isTuple(o
);
3244 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j
, ta
, ea
, sa
, va
);
3249 /**********************************************
3250 * Find template declaration corresponding to template instance.
3253 TemplateDeclaration
*TemplateInstance::findTemplateDeclaration(Scope
*sc
)
3255 //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
3260 * figure out which TemplateDeclaration foo refers to.
3268 s
= sc
->search(loc
, id
, &scopesym
);
3270 { error("identifier '%s' is not defined", id
->toChars());
3274 printf("It's an instance of '%s' kind '%s'\n", s
->toChars(), s
->kind());
3276 printf("s->parent = '%s'\n", s
->parent
->toChars());
3278 withsym
= scopesym
->isWithScopeSymbol();
3280 /* We might have found an alias within a template when
3281 * we really want the template.
3283 TemplateInstance
*ti
;
3285 (ti
= s
->parent
->isTemplateInstance()) != NULL
)
3289 ti
->toAlias()->ident
== id
)
3293 /* This is so that one can refer to the enclosing
3294 * template, even if it has the same name as a member
3295 * of the template, if it has a !(arguments)
3297 tempdecl
= ti
->tempdecl
;
3298 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3299 tempdecl
= tempdecl
->overroot
; // then get the start
3306 /* It should be a TemplateDeclaration, not some other symbol
3308 tempdecl
= s
->isTemplateDeclaration();
3311 if (!s
->parent
&& global
.errors
)
3313 if (!s
->parent
&& s
->getType())
3314 { Dsymbol
*s2
= s
->getType()->toDsymbol(sc
);
3317 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3323 //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
3325 //assert(s->parent);
3326 TemplateInstance
*ti
= s
->parent
? s
->parent
->isTemplateInstance() : NULL
;
3329 ti
->toAlias()->ident
== id
)
3333 /* This is so that one can refer to the enclosing
3334 * template, even if it has the same name as a member
3335 * of the template, if it has a !(arguments)
3337 tempdecl
= ti
->tempdecl
;
3338 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3339 tempdecl
= tempdecl
->overroot
; // then get the start
3343 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3349 assert(tempdecl
->isTemplateDeclaration());
3353 TemplateDeclaration
*TemplateInstance::findBestMatch(Scope
*sc
)
3355 /* Since there can be multiple TemplateDeclaration's with the same
3356 * name, look for the best match.
3358 TemplateDeclaration
*td_ambig
= NULL
;
3359 TemplateDeclaration
*td_best
= NULL
;
3360 MATCH m_best
= MATCHnomatch
;
3364 printf("TemplateInstance::findBestMatch()\n");
3366 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
3370 //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
3372 // If more arguments than parameters,
3373 // then this is no match.
3374 if (td
->parameters
->dim
< tiargs
->dim
)
3376 if (!td
->isVariadic())
3380 dedtypes
.setDim(td
->parameters
->dim
);
3384 error("forward reference to template declaration %s", td
->toChars());
3387 m
= td
->matchWithInstance(this, &dedtypes
, 0);
3388 //printf("m = %d\n", m);
3389 if (!m
) // no match at all
3402 // Disambiguate by picking the most specialized TemplateDeclaration
3403 int c1
= td
->leastAsSpecialized(td_best
);
3404 int c2
= td_best
->leastAsSpecialized(td
);
3405 //printf("c1 = %d, c2 = %d\n", c1, c2);
3415 Lambig
: // td_best and td are ambiguous
3419 Ltd_best
: // td_best is the best match so far
3423 Ltd
: // td is the new best match
3427 tdtypes
.setDim(dedtypes
.dim
);
3428 memcpy(tdtypes
.data
, dedtypes
.data
, tdtypes
.dim
* sizeof(void *));
3434 error("%s does not match any template declaration", toChars());
3439 error("%s matches more than one template declaration, %s and %s",
3440 toChars(), td_best
->toChars(), td_ambig
->toChars());
3443 /* The best match is td_best
3448 /* Cast any value arguments to be same type as value parameter
3450 for (size_t i
= 0; i
< tiargs
->dim
; i
++)
3451 { Object
*o
= (Object
*)tiargs
->data
[i
];
3452 Expression
*ea
= isExpression(o
); // value argument
3453 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3455 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3459 ea
= ea
->castTo(tvp
->valType
);
3460 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3461 tiargs
->data
[i
] = (Object
*)ea
;
3467 printf("\tIt's a match with template declaration '%s'\n", tempdecl
->toChars());
3473 /*****************************************
3474 * Determines if a TemplateInstance will need a nested
3475 * generation of the TemplateDeclaration.
3478 int TemplateInstance::isNested(Objects
*args
)
3480 //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars());
3482 /* A nested instance happens when an argument references a local
3483 * symbol that is on the stack.
3485 for (size_t i
= 0; i
< args
->dim
; i
++)
3486 { Object
*o
= (Object
*)args
->data
[i
];
3487 Expression
*ea
= isExpression(o
);
3488 Dsymbol
*sa
= isDsymbol(o
);
3489 Tuple
*va
= isTuple(o
);
3492 if (ea
->op
== TOKvar
)
3494 sa
= ((VarExp
*)ea
)->var
;
3497 if (ea
->op
== TOKfunction
)
3499 sa
= ((FuncExp
*)ea
)->fd
;
3506 Declaration
*d
= sa
->isDeclaration();
3507 if (d
&& !d
->isDataseg() &&
3509 !(d
->storage_class
& STCmanifest
) &&
3511 (!d
->isFuncDeclaration() || d
->isFuncDeclaration()->isNested()) &&
3514 // if module level template
3515 if (tempdecl
->toParent()->isModule())
3516 { Dsymbol
*dparent
= d
->toParent();
3519 else if (isnested
!= dparent
)
3521 /* Select the more deeply nested of the two.
3522 * Error if one is not nested inside the other.
3524 for (Dsymbol
*p
= isnested
; p
; p
= p
->parent
)
3527 goto L1
; // isnested is most nested
3529 for (Dsymbol
*p
= dparent
; 1; p
= p
->parent
)
3532 { isnested
= dparent
;
3533 goto L1
; // dparent is most nested
3536 error("is nested in both %s and %s", isnested
->toChars(), dparent
->toChars());
3539 //printf("\tnested inside %s\n", isnested->toChars());
3543 error("cannot use local '%s' as template parameter", d
->toChars());
3548 nested
|= isNested(&va
->objects
);
3554 /****************************************
3555 * This instance needs an identifier for name mangling purposes.
3556 * Create one by taking the template declaration name and adding
3557 * the type signature for it.
3560 Identifier
*TemplateInstance::genIdent()
3565 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
3566 id
= tempdecl
->ident
->toChars();
3567 buf
.printf("__T%"PRIuSIZE
"%s", strlen(id
), id
);
3569 for (int i
= 0; i
< args
->dim
; i
++)
3570 { Object
*o
= (Object
*)args
->data
[i
];
3571 Type
*ta
= isType(o
);
3572 Expression
*ea
= isExpression(o
);
3573 Dsymbol
*sa
= isDsymbol(o
);
3574 Tuple
*va
= isTuple(o
);
3575 //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
3580 buf
.writestring(ta
->deco
);
3584 printf("ta = %d, %s\n", ta
->ty
, ta
->toChars());
3586 assert(global
.errors
);
3593 if (ea
->op
== TOKvar
)
3595 sa
= ((VarExp
*)ea
)->var
;
3599 if (ea
->op
== TOKfunction
)
3601 sa
= ((FuncExp
*)ea
)->fd
;
3606 if (ea
->op
== TOKtuple
)
3607 { ea
->error("tuple is not a valid template value argument");
3611 /* Use deco that matches what it would be for a function parameter
3613 buf
.writestring(ea
->type
->deco
);
3615 // Use type of parameter, not type of argument
3616 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3618 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3620 buf
.writestring(tvp
->valType
->deco
);
3622 ea
->toMangleBuffer(&buf
);
3628 Declaration
*d
= sa
->isDeclaration();
3629 if (d
&& !d
->type
->deco
)
3630 error("forward reference of %s", d
->toChars());
3633 char *p
= sa
->mangle();
3634 buf
.printf("%"PRIuSIZE
"%s", strlen(p
), p
);
3639 assert(i
+ 1 == args
->dim
); // must be last one
3640 args
= &va
->objects
;
3649 return new Identifier(id
, TOKidentifier
);
3653 /****************************************************
3654 * Declare parameters of template instance, initialize them with the
3655 * template instance arguments.
3658 void TemplateInstance::declareParameters(Scope
*scope
)
3660 //printf("TemplateInstance::declareParameters()\n");
3661 for (int i
= 0; i
< tdtypes
.dim
; i
++)
3663 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3664 //Object *o = (Object *)tiargs->data[i];
3665 Object
*o
= (Object
*)tdtypes
.data
[i
];
3667 //printf("\ttdtypes[%d] = %p\n", i, o);
3668 tempdecl
->declareParameter(scope
, tp
, o
);
3673 void TemplateInstance::semantic2(Scope
*sc
)
3676 if (semanticdone
>= 2)
3680 printf("+TemplateInstance::semantic2('%s')\n", toChars());
3682 if (!errors
&& members
)
3684 sc
= tempdecl
->scope
;
3686 sc
= sc
->push(argsym
);
3687 sc
= sc
->push(this);
3688 for (i
= 0; i
< members
->dim
; i
++)
3690 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3692 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
3700 printf("-TemplateInstance::semantic2('%s')\n", toChars());
3704 void TemplateInstance::semantic3(Scope
*sc
)
3707 printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone
);
3709 //if (toChars()[0] == 'D') *(char*)0=0;
3710 if (semanticdone
>= 3)
3713 if (!errors
&& members
)
3715 sc
= tempdecl
->scope
;
3716 sc
= sc
->push(argsym
);
3717 sc
= sc
->push(this);
3718 for (int i
= 0; i
< members
->dim
; i
++)
3720 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3728 void TemplateInstance::toObjFile(int multiobj
)
3731 printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
3733 if (!errors
&& members
)
3736 // Append to list of object files to be written later
3740 for (int i
= 0; i
< members
->dim
; i
++)
3742 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3743 s
->toObjFile(multiobj
);
3749 void TemplateInstance::inlineScan()
3752 printf("TemplateInstance::inlineScan('%s')\n", toChars());
3754 if (!errors
&& members
)
3756 for (int i
= 0; i
< members
->dim
; i
++)
3758 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3764 void TemplateInstance::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3768 Identifier
*id
= name
;
3769 buf
->writestring(id
->toChars());
3770 buf
->writestring("!(");
3772 buf
->writestring("...");
3776 Objects
*args
= tiargs
;
3777 for (i
= 0; i
< args
->dim
; i
++)
3780 buf
->writeByte(',');
3781 Object
*oarg
= (Object
*)args
->data
[i
];
3782 ObjectToCBuffer(buf
, hgs
, oarg
);
3786 buf
->writeByte(')');
3790 Dsymbol
*TemplateInstance::toAlias()
3793 printf("TemplateInstance::toAlias()\n");
3796 { error("cannot resolve forward reference");
3801 return inst
->toAlias();
3804 return aliasdecl
->toAlias();
3809 AliasDeclaration
*TemplateInstance::isAliasDeclaration()
3814 char *TemplateInstance::kind()
3816 return "template instance";
3819 int TemplateInstance::oneMember(Dsymbol
**ps
)
3825 char *TemplateInstance::toChars()
3831 toCBuffer(&buf
, &hgs
);
3837 /* ======================== TemplateMixin ================================ */
3839 TemplateMixin::TemplateMixin(Loc loc
, Identifier
*ident
, Type
*tqual
,
3840 Array
*idents
, Objects
*tiargs
)
3841 : TemplateInstance(loc
, (Identifier
*)idents
->data
[idents
->dim
- 1])
3843 //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
3844 this->ident
= ident
;
3845 this->tqual
= tqual
;
3846 this->idents
= idents
;
3847 this->tiargs
= tiargs
? tiargs
: new Objects();
3851 Dsymbol
*TemplateMixin::syntaxCopy(Dsymbol
*s
)
3852 { TemplateMixin
*tm
;
3854 Array
*ids
= new Array();
3855 ids
->setDim(idents
->dim
);
3856 for (int i
= 0; i
< idents
->dim
; i
++)
3857 { // Matches TypeQualified::syntaxCopyHelper()
3858 Identifier
*id
= (Identifier
*)idents
->data
[i
];
3859 if (id
->dyncast() == DYNCAST_DSYMBOL
)
3861 TemplateInstance
*ti
= (TemplateInstance
*)id
;
3863 ti
= (TemplateInstance
*)ti
->syntaxCopy(NULL
);
3864 id
= (Identifier
*)ti
;
3869 tm
= new TemplateMixin(loc
, ident
,
3870 (Type
*)(tqual
? tqual
->syntaxCopy() : NULL
),
3872 TemplateInstance::syntaxCopy(tm
);
3876 void TemplateMixin::semantic(Scope
*sc
)
3879 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
3883 // This for when a class/struct contains mixin members, and
3884 // is done over because of forward references
3885 (!parent
|| !toParent()->isAggregateDeclaration()))
3888 printf("\tsemantic done\n");
3895 printf("\tdo semantic\n");
3901 scx
= scope
; // save so we don't make redundant copies
3905 // Follow qualifications to find the TemplateDeclaration
3912 { s
= tqual
->toDsymbol(sc
);
3918 id
= (Identifier
*)idents
->data
[0];
3919 switch (id
->dyncast())
3921 case DYNCAST_IDENTIFIER
:
3922 s
= sc
->search(loc
, id
, NULL
);
3925 case DYNCAST_DSYMBOL
:
3927 TemplateInstance
*ti
= (TemplateInstance
*)id
;
3937 for (; i
< idents
->dim
; i
++)
3941 id
= (Identifier
*)idents
->data
[i
];
3942 s
= s
->searchX(loc
, sc
, id
);
3946 error("is not defined");
3950 tempdecl
= s
->toAlias()->isTemplateDeclaration();
3953 error("%s isn't a template", s
->toChars());
3959 // Look for forward reference
3961 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
3965 /* Cannot handle forward references if mixin is a struct member,
3966 * because addField must happen during struct's semantic, not
3967 * during the mixin semantic.
3968 * runDeferred will re-run mixin's semantic outside of the struct's
3972 AggregateDeclaration
*ad
= toParent()->isAggregateDeclaration();
3977 // Forward reference
3978 //printf("forward reference - deferring\n");
3979 scope
= scx
? scx
: new Scope(*sc
);
3981 scope
->module
->addDeferredSemantic(this);
3987 // Run semantic on each argument, place results in tiargs[]
3990 tempdecl
= findBestMatch(sc
);
3993 return; // error recovery
4000 parent
= sc
->parent
;
4002 /* Detect recursive mixin instantiations.
4004 for (Dsymbol
*s
= parent
; s
; s
= s
->parent
)
4006 //printf("\ts = '%s'\n", s->toChars());
4007 TemplateMixin
*tm
= s
->isTemplateMixin();
4008 if (!tm
|| tempdecl
!= tm
->tempdecl
)
4011 for (int i
= 0; i
< tiargs
->dim
; i
++)
4012 { Object
*o
= (Object
*)tiargs
->data
[i
];
4013 Type
*ta
= isType(o
);
4014 Expression
*ea
= isExpression(o
);
4015 Dsymbol
*sa
= isDsymbol(o
);
4016 Object
*tmo
= (Object
*)tm
->tiargs
->data
[i
];
4019 Type
*tmta
= isType(tmo
);
4022 if (!ta
->equals(tmta
))
4026 { Expression
*tme
= isExpression(tmo
);
4027 if (!tme
|| !ea
->equals(tme
))
4032 Dsymbol
*tmsa
= isDsymbol(tmo
);
4039 error("recursive mixin instantiation");
4046 // Copy the syntax trees from the TemplateDeclaration
4047 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
4051 symtab
= new DsymbolTable();
4053 for (Scope
*sce
= sc
; 1; sce
= sce
->enclosing
)
4055 ScopeDsymbol
*sds
= (ScopeDsymbol
*)sce
->scopesym
;
4058 sds
->importScope(this, PROTpublic
);
4064 printf("\tcreate scope for template parameters '%s'\n", toChars());
4067 scy
= sc
->push(this);
4070 argsym
= new ScopeDsymbol();
4071 argsym
->parent
= scy
->parent
;
4072 Scope
*scope
= scy
->push(argsym
);
4074 unsigned errorsave
= global
.errors
;
4076 // Declare each template parameter as an alias for the argument type
4077 declareParameters(scope
);
4079 // Add members to enclosing scope, as well as this scope
4080 for (unsigned i
= 0; i
< members
->dim
; i
++)
4083 s
= (Dsymbol
*)members
->data
[i
];
4084 s
->addMember(scope
, this, i
);
4086 //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
4087 //printf("s->parent = %s\n", s->parent->toChars());
4090 // Do semantic() analysis on template instance members
4092 printf("\tdo semantic() on template instance members '%s'\n", toChars());
4095 sc2
= scope
->push(this);
4096 sc2
->offset
= sc
->offset
;
4097 for (int i
= 0; i
< members
->dim
; i
++)
4099 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4102 sc
->offset
= sc2
->offset
;
4104 /* The problem is when to parse the initializer for a variable.
4105 * Perhaps VarDeclaration::semantic() should do it like it does
4106 * for initializers inside a function.
4108 // if (sc->parent->isFuncDeclaration())
4117 // Give additional context info if error occurred during instantiation
4118 if (global
.errors
!= errorsave
)
4120 error("error instantiating");
4127 // if (!isAnonymous())
4132 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
4136 void TemplateMixin::semantic2(Scope
*sc
)
4139 if (semanticdone
>= 2)
4143 printf("+TemplateMixin::semantic2('%s')\n", toChars());
4148 sc
= sc
->push(argsym
);
4149 sc
= sc
->push(this);
4150 for (i
= 0; i
< members
->dim
; i
++)
4152 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4154 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
4162 printf("-TemplateMixin::semantic2('%s')\n", toChars());
4166 void TemplateMixin::semantic3(Scope
*sc
)
4169 if (semanticdone
>= 3)
4173 printf("TemplateMixin::semantic3('%s')\n", toChars());
4177 sc
= sc
->push(argsym
);
4178 sc
= sc
->push(this);
4179 for (i
= 0; i
< members
->dim
; i
++)
4181 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4189 void TemplateMixin::inlineScan()
4191 TemplateInstance::inlineScan();
4194 char *TemplateMixin::kind()
4199 int TemplateMixin::oneMember(Dsymbol
**ps
)
4201 return Dsymbol::oneMember(ps
);
4204 int TemplateMixin::hasPointers()
4206 //printf("TemplateMixin::hasPointers() %s\n", toChars());
4207 for (size_t i
= 0; i
< members
->dim
; i
++)
4209 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4210 //printf(" s = %s %s\n", s->kind(), s->toChars());
4211 if (s
->hasPointers())
4219 char *TemplateMixin::toChars()
4225 TemplateInstance::toCBuffer(&buf
, &hgs
);
4231 void TemplateMixin::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4233 buf
->writestring("mixin ");
4235 for (i
= 0; i
< idents
->dim
; i
++)
4236 { Identifier
*id
= (Identifier
*)idents
->data
[i
];
4239 buf
->writeByte('.');
4240 buf
->writestring(id
->toChars());
4242 buf
->writestring("!(");
4245 for (i
= 0; i
< tiargs
->dim
; i
++)
4247 buf
->writebyte(',');
4248 Object
*oarg
= (Object
*)tiargs
->data
[i
];
4249 Type
*t
= isType(oarg
);
4250 Expression
*e
= isExpression(oarg
);
4251 Dsymbol
*s
= isDsymbol(oarg
);
4253 t
->toCBuffer(buf
, NULL
, hgs
);
4255 e
->toCBuffer(buf
, hgs
);
4258 char *p
= s
->ident
? s
->ident
->toChars() : s
->toChars();
4259 buf
->writestring(p
);
4263 buf
->writestring("NULL");
4271 buf
->writebyte(')');
4272 buf
->writebyte(';');
4277 void TemplateMixin::toObjFile(int multiobj
)
4279 //printf("TemplateMixin::toObjFile('%s')\n", toChars());
4280 TemplateInstance::toObjFile(multiobj
);