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
, bool dltSource
)
265 : ScopeDsymbol(id
), dltSource(dltSource
)
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
, dltSource
);
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();
1288 if (tparam
->ty
== Tmaybe
)
1289 tparam
= tparam
->next
;
1290 if (this->ty
== Tmaybe
)
1291 return next
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1296 if (tparam
->ty
== Tident
)
1298 // Determine which parameter tparam is
1299 int i
= templateParameterLookup(tparam
, parameters
);
1304 /* BUG: what if tparam is a template instance, that
1305 * has as an argument another Tident?
1307 tparam
= tparam
->semantic(0, sc
);
1308 assert(tparam
->ty
!= Tident
);
1309 return deduceType(sc
, tparam
, parameters
, dedtypes
);
1312 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1314 // Found the corresponding parameter tp
1315 if (!tp
->isTemplateTypeParameter())
1317 Type
*at
= (Type
*)dedtypes
->data
[i
];
1320 dedtypes
->data
[i
] = (void *)this;
1325 else if (ty
== Tclass
&& at
->ty
== Tclass
)
1327 return (MATCH
) implicitConvTo(at
);
1329 else if (ty
== Tsarray
&& at
->ty
== Tarray
&&
1330 nextOf()->equals(at
->nextOf()))
1338 if (ty
!= tparam
->ty
)
1342 return nextOf()->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1348 return MATCHnomatch
;
1351 MATCH
TypeSArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
,
1355 printf("TypeSArray::deduceType()\n");
1356 printf("\tthis = %d, ", ty
); print();
1357 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1360 // Extra check that array dimensions must match
1363 if (tparam
->ty
== Tsarray
)
1365 TypeSArray
*tp
= (TypeSArray
*)tparam
;
1367 if (tp
->dim
->op
== TOKvar
&&
1368 ((VarExp
*)tp
->dim
)->var
->storage_class
& STCtemplateparameter
)
1369 { int i
= templateIdentifierLookup(((VarExp
*)tp
->dim
)->var
->ident
, parameters
);
1370 // This code matches code in TypeInstance::deduceType()
1373 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1374 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1377 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
1380 if (!dim
->equals(e
))
1384 { Type
*vt
= tvp
->valType
->semantic(0, sc
);
1385 MATCH m
= (MATCH
)dim
->implicitConvTo(vt
);
1388 dedtypes
->data
[i
] = dim
;
1391 else if (dim
->toInteger() != tp
->dim
->toInteger())
1392 return MATCHnomatch
;
1394 else if (tparam
->ty
== Taarray
)
1396 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1397 if (tp
->index
->ty
== Tident
)
1398 { TypeIdentifier
*tident
= (TypeIdentifier
*)tp
->index
;
1400 if (tident
->idents
.dim
== 0)
1401 { Identifier
*id
= tident
->ident
;
1403 for (size_t i
= 0; i
< parameters
->dim
; i
++)
1405 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1407 if (tp
->ident
->equals(id
))
1408 { // Found the corresponding template parameter
1409 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1410 if (!tvp
|| !tvp
->valType
->isintegral())
1413 if (dedtypes
->data
[i
])
1415 if (!dim
->equals((Object
*)dedtypes
->data
[i
]))
1419 { dedtypes
->data
[i
] = (void *)dim
;
1421 return next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1427 else if (tparam
->ty
== Tarray
)
1430 m
= next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1431 if (m
== MATCHexact
)
1436 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1439 return MATCHnomatch
;
1442 MATCH
TypeAArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1445 printf("TypeAArray::deduceType()\n");
1446 printf("\tthis = %d, ", ty
); print();
1447 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1450 // Extra check that index type must match
1451 if (tparam
&& tparam
->ty
== Taarray
)
1453 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1454 if (!index
->deduceType(sc
, tp
->index
, parameters
, dedtypes
))
1456 return MATCHnomatch
;
1459 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1462 MATCH
TypeFunction::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1464 //printf("TypeFunction::deduceType()\n");
1465 //printf("\tthis = %d, ", ty); print();
1466 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1468 // Extra check that function characteristics must match
1469 if (tparam
&& tparam
->ty
== Tfunction
)
1471 TypeFunction
*tp
= (TypeFunction
*)tparam
;
1472 if (varargs
!= tp
->varargs
||
1473 linkage
!= tp
->linkage
)
1474 return MATCHnomatch
;
1476 size_t nfargs
= Argument::dim(this->parameters
);
1477 size_t nfparams
= Argument::dim(tp
->parameters
);
1479 /* See if tuple match
1481 if (nfparams
> 0 && nfargs
>= nfparams
- 1)
1483 /* See if 'A' of the template parameter matches 'A'
1484 * of the type of the last function parameter.
1486 Argument
*fparam
= (Argument
*)tp
->parameters
->data
[nfparams
- 1];
1487 if (fparam
->type
->ty
!= Tident
)
1489 TypeIdentifier
*tid
= (TypeIdentifier
*)fparam
->type
;
1490 if (tid
->idents
.dim
)
1493 /* Look through parameters to find tuple matching tid->ident
1497 { if (tupi
== parameters
->dim
)
1499 TemplateParameter
*t
= (TemplateParameter
*)parameters
->data
[tupi
];
1500 TemplateTupleParameter
*tup
= t
->isTemplateTupleParameter();
1501 if (tup
&& tup
->ident
->equals(tid
->ident
))
1505 /* The types of the function arguments [nfparams - 1 .. nfargs]
1506 * now form the tuple argument.
1508 int tuple_dim
= nfargs
- (nfparams
- 1);
1510 /* See if existing tuple, and whether it matches or not
1512 Object
*o
= (Object
*)dedtypes
->data
[tupi
];
1514 { // Existing deduced argument must be a tuple, and must match
1515 Tuple
*t
= isTuple(o
);
1516 if (!t
|| t
->objects
.dim
!= tuple_dim
)
1517 return MATCHnomatch
;
1518 for (size_t i
= 0; i
< tuple_dim
; i
++)
1519 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1520 if (!arg
->type
->equals((Object
*)t
->objects
.data
[i
]))
1521 return MATCHnomatch
;
1525 { // Create new tuple
1526 Tuple
*t
= new Tuple();
1527 t
->objects
.setDim(tuple_dim
);
1528 for (size_t i
= 0; i
< tuple_dim
; i
++)
1529 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1530 t
->objects
.data
[i
] = (void *)arg
->type
;
1532 dedtypes
->data
[tupi
] = (void *)t
;
1534 nfparams
--; // don't consider the last parameter for type deduction
1539 if (nfargs
!= nfparams
)
1540 return MATCHnomatch
;
1542 for (size_t i
= 0; i
< nfparams
; i
++)
1544 Argument
*a
= Argument::getNth(this->parameters
, i
);
1545 Argument
*ap
= Argument::getNth(tp
->parameters
, i
);
1546 if (a
->storageClass
!= ap
->storageClass
||
1547 !a
->type
->deduceType(sc
, ap
->type
, parameters
, dedtypes
))
1548 return MATCHnomatch
;
1551 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1554 MATCH
TypeIdentifier::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1557 if (tparam
&& tparam
->ty
== Tident
)
1559 TypeIdentifier
*tp
= (TypeIdentifier
*)tparam
;
1561 for (int i
= 0; i
< idents
.dim
; i
++)
1563 Identifier
*id1
= (Identifier
*)idents
.data
[i
];
1564 Identifier
*id2
= (Identifier
*)tp
->idents
.data
[i
];
1566 if (!id1
->equals(id2
))
1567 return MATCHnomatch
;
1570 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1573 MATCH
TypeInstance::deduceType(Scope
*sc
,
1574 Type
*tparam
, TemplateParameters
*parameters
,
1577 //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
1578 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1581 if (tparam
&& tparam
->ty
== Tinstance
)
1583 TypeInstance
*tp
= (TypeInstance
*)tparam
;
1585 //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
1586 //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
1587 if (!tp
->tempinst
->tempdecl
)
1588 { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
1589 if (!tp
->tempinst
->name
->equals(tempinst
->name
))
1592 * template Foo(T : sa!(T), alias sa)
1594 int i
= templateIdentifierLookup(tp
->tempinst
->name
, parameters
);
1596 { /* Didn't find it as a parameter identifier. Try looking
1597 * it up and seeing if is an alias. See Bugzilla 1454
1599 Dsymbol
*s
= tempinst
->tempdecl
->scope
->search(0, tp
->tempinst
->name
, NULL
);
1603 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
1604 if (td
&& td
== tempinst
->tempdecl
)
1609 TemplateParameter
*tpx
= (TemplateParameter
*)parameters
->data
[i
];
1610 // This logic duplicates tpx->matchArg()
1611 TemplateAliasParameter
*ta
= tpx
->isTemplateAliasParameter();
1614 Dsymbol
*sa
= tempinst
->tempdecl
;
1617 if (ta
->specAlias
&& sa
!= ta
->specAlias
)
1619 if (dedtypes
->data
[i
])
1620 { // Must match already deduced symbol
1621 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
1626 dedtypes
->data
[i
] = sa
;
1629 else if (tempinst
->tempdecl
!= tp
->tempinst
->tempdecl
)
1633 if (tempinst
->tiargs
->dim
!= tp
->tempinst
->tiargs
->dim
)
1636 for (int i
= 0; i
< tempinst
->tiargs
->dim
; i
++)
1638 //printf("\ttest: tempinst->tiargs[%d]\n", i);
1640 Object
*o1
= (Object
*)tempinst
->tiargs
->data
[i
];
1641 Object
*o2
= (Object
*)tp
->tempinst
->tiargs
->data
[i
];
1643 Type
*t1
= isType(o1
);
1644 Type
*t2
= isType(o2
);
1646 Expression
*e1
= isExpression(o1
);
1647 Expression
*e2
= isExpression(o2
);
1650 if (t1
) printf("t1 = %s\n", t1
->toChars());
1651 if (t2
) printf("t2 = %s\n", t2
->toChars());
1652 if (e1
) printf("e1 = %s\n", e1
->toChars());
1653 if (e2
) printf("e2 = %s\n", e2
->toChars());
1658 if (!t1
->deduceType(sc
, t2
, parameters
, dedtypes
))
1663 if (!e1
->equals(e2
))
1664 { if (e2
->op
== TOKvar
)
1667 * (T:Number!(e2), int e2)
1669 j
= templateIdentifierLookup(((VarExp
*)e2
)->var
->ident
, parameters
);
1675 else if (e1
&& t2
&& t2
->ty
== Tident
)
1677 j
= templateParameterLookup(t2
, parameters
);
1681 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[j
];
1682 // BUG: use tp->matchArg() instead of the following
1683 TemplateValueParameter
*tv
= tp
->isTemplateValueParameter();
1686 Expression
*e
= (Expression
*)dedtypes
->data
[j
];
1693 { Type
*vt
= tv
->valType
->semantic(0, sc
);
1694 MATCH m
= (MATCH
)e1
->implicitConvTo(vt
);
1697 dedtypes
->data
[j
] = e1
;
1700 // BUG: Need to handle alias and tuple parameters
1705 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1708 return MATCHnomatch
;
1711 MATCH
TypeStruct::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1713 //printf("TypeStruct::deduceType()\n");
1714 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
1715 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1717 /* If this struct is a template struct, and we're matching
1718 * it against a template instance, convert the struct type
1719 * to a template instance, too, and try again.
1721 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1723 if (tparam
&& tparam
->ty
== Tinstance
)
1725 if (ti
&& ti
->toAlias() == sym
)
1727 TypeInstance
*t
= new TypeInstance(0, ti
);
1728 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1731 /* Match things like:
1734 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1735 if (tpi
->idents
.dim
)
1736 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1737 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1739 Type
*tparent
= sym
->parent
->getType();
1742 /* Slice off the .foo in S!(T).foo
1745 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1754 if (tparam
&& tparam
->ty
== Tstruct
)
1756 TypeStruct
*tp
= (TypeStruct
*)tparam
;
1759 return MATCHnomatch
;
1761 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1764 MATCH
TypeEnum::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1767 if (tparam
&& tparam
->ty
== Tenum
)
1769 TypeEnum
*tp
= (TypeEnum
*)tparam
;
1772 return MATCHnomatch
;
1774 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1777 MATCH
TypeTypedef::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1780 if (tparam
&& tparam
->ty
== Ttypedef
)
1782 TypeTypedef
*tp
= (TypeTypedef
*)tparam
;
1785 return MATCHnomatch
;
1787 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1790 MATCH
TypeClass::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1792 //printf("TypeClass::deduceType(this = %s)\n", toChars());
1794 /* If this class is a template class, and we're matching
1795 * it against a template instance, convert the class type
1796 * to a template instance, too, and try again.
1798 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1800 if (tparam
&& tparam
->ty
== Tinstance
)
1802 if (ti
&& ti
->toAlias() == sym
)
1804 TypeInstance
*t
= new TypeInstance(0, ti
);
1805 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1808 /* Match things like:
1811 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1812 if (tpi
->idents
.dim
)
1813 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1814 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1816 Type
*tparent
= sym
->parent
->getType();
1819 /* Slice off the .foo in S!(T).foo
1822 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1831 if (tparam
&& tparam
->ty
== Tclass
)
1833 TypeClass
*tp
= (TypeClass
*)tparam
;
1835 //printf("\t%d\n", (MATCH) implicitConvTo(tp));
1836 return (MATCH
) implicitConvTo(tp
);
1838 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1841 /* ======================== TemplateParameter =============================== */
1843 TemplateParameter::TemplateParameter(Loc loc
, Identifier
*ident
)
1846 this->ident
= ident
;
1847 this->sparam
= NULL
;
1850 TemplateTypeParameter
*TemplateParameter::isTemplateTypeParameter()
1855 TemplateValueParameter
*TemplateParameter::isTemplateValueParameter()
1860 TemplateAliasParameter
*TemplateParameter::isTemplateAliasParameter()
1865 TemplateTupleParameter
*TemplateParameter::isTemplateTupleParameter()
1871 TemplateThisParameter
*TemplateParameter::isTemplateThisParameter()
1877 /* ======================== TemplateTypeParameter =========================== */
1881 TemplateTypeParameter::TemplateTypeParameter(Loc loc
, Identifier
*ident
, Type
*specType
,
1883 : TemplateParameter(loc
, ident
)
1885 this->ident
= ident
;
1886 this->specType
= specType
;
1887 this->defaultType
= defaultType
;
1890 TemplateTypeParameter
*TemplateTypeParameter::isTemplateTypeParameter()
1895 TemplateParameter
*TemplateTypeParameter::syntaxCopy()
1897 TemplateTypeParameter
*tp
= new TemplateTypeParameter(loc
, ident
, specType
, defaultType
);
1899 tp
->specType
= specType
->syntaxCopy();
1901 tp
->defaultType
= defaultType
->syntaxCopy();
1905 void TemplateTypeParameter::declareParameter(Scope
*sc
)
1907 //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
1908 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
1909 sparam
= new AliasDeclaration(loc
, ident
, ti
);
1910 if (!sc
->insert(sparam
))
1911 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
1914 void TemplateTypeParameter::semantic(Scope
*sc
)
1916 //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
1919 specType
= specType
->semantic(loc
, sc
);
1921 #if 0 // Don't do semantic() until instantiation
1924 defaultType
= defaultType
->semantic(loc
, sc
);
1929 /****************************************
1930 * Determine if two TemplateParameters are the same
1931 * as far as TemplateDeclaration overloading goes.
1937 int TemplateTypeParameter::overloadMatch(TemplateParameter
*tp
)
1939 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
1943 if (specType
!= ttp
->specType
)
1946 if (specType
&& !specType
->equals(ttp
->specType
))
1956 /*******************************************
1957 * Match to a particular TemplateParameter.
1960 * tiargs[] actual arguments to template instance
1961 * parameters[] template parameters
1962 * dedtypes[] deduced arguments to template instance
1963 * *psparam set to symbol declared and initialized to dedtypes[i]
1966 MATCH
TemplateTypeParameter::matchArg(Scope
*sc
, Objects
*tiargs
,
1967 int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
1968 Declaration
**psparam
)
1970 //printf("TemplateTypeParameter::matchArg()\n");
1973 MATCH m
= MATCHexact
;
1976 if (i
< tiargs
->dim
)
1977 oarg
= (Object
*)tiargs
->data
[i
];
1979 { // Get default argument instead
1980 oarg
= defaultArg(sc
);
1982 { assert(i
< dedtypes
->dim
);
1983 // It might have already been deduced
1984 oarg
= (Object
*)dedtypes
->data
[i
];
1993 //printf("ta is %s\n", ta->toChars());
1995 t
= (Type
*)dedtypes
->data
[i
];
1999 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
2000 MATCH m2
= ta
->deduceType(sc
, specType
, parameters
, dedtypes
);
2001 if (m2
== MATCHnomatch
)
2002 { //printf("\tfailed deduceType\n");
2008 t
= (Type
*)dedtypes
->data
[i
];
2012 // So that matches with specializations are better
2015 { // Must match already deduced type
2019 { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
2027 dedtypes
->data
[i
] = ta
;
2030 *psparam
= new AliasDeclaration(loc
, ident
, t
);
2031 //printf("\tm = %d\n", m);
2036 //printf("\tm = %d\n", MATCHnomatch);
2037 return MATCHnomatch
;
2041 void TemplateTypeParameter::print(Object
*oarg
, Object
*oded
)
2043 fprintf(stderr
, " %s\n", ident
->toChars());
2045 Type
*t
= isType(oarg
);
2046 Type
*ta
= isType(oded
);
2051 fprintf(stderr
, "\tSpecialization: %s\n", specType
->toChars());
2053 fprintf(stderr
, "\tDefault: %s\n", defaultType
->toChars());
2054 fprintf(stderr
, "\tArgument: %s\n", t
? t
->toChars() : "NULL");
2055 fprintf(stderr
, "\tDeduced Type: %s\n", ta
->toChars());
2059 void TemplateTypeParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2061 buf
->writestring(ident
->toChars());
2064 buf
->writestring(" : ");
2065 specType
->toCBuffer(buf
, NULL
, hgs
);
2069 buf
->writestring(" = ");
2070 defaultType
->toCBuffer(buf
, NULL
, hgs
);
2075 void *TemplateTypeParameter::dummyArg()
2081 { // Use this for alias-parameter's too (?)
2082 t
= new TypeIdentifier(loc
, ident
);
2088 Object
*TemplateTypeParameter::specialization()
2094 Object
*TemplateTypeParameter::defaultArg(Scope
*sc
)
2101 t
= t
->syntaxCopy();
2102 t
= t
->semantic(loc
, sc
);
2107 /* ======================== TemplateThisParameter =========================== */
2112 TemplateThisParameter::TemplateThisParameter(Loc loc
, Identifier
*ident
,
2115 : TemplateTypeParameter(loc
, ident
, specType
, defaultType
)
2119 TemplateThisParameter
*TemplateThisParameter::isTemplateThisParameter()
2124 TemplateParameter
*TemplateThisParameter::syntaxCopy()
2126 TemplateThisParameter
*tp
= new TemplateThisParameter(loc
, ident
, specType
, defaultType
);
2128 tp
->specType
= specType
->syntaxCopy();
2130 tp
->defaultType
= defaultType
->syntaxCopy();
2134 void TemplateThisParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2136 buf
->writestring("this ");
2137 TemplateTypeParameter::toCBuffer(buf
, hgs
);
2141 /* ======================== TemplateAliasParameter ========================== */
2145 Dsymbol
*TemplateAliasParameter::sdummy
= NULL
;
2147 TemplateAliasParameter::TemplateAliasParameter(Loc loc
, Identifier
*ident
, Type
*specAliasT
, Type
*defaultAlias
)
2148 : TemplateParameter(loc
, ident
)
2150 this->ident
= ident
;
2151 this->specAliasT
= specAliasT
;
2152 this->defaultAlias
= defaultAlias
;
2154 this->specAlias
= NULL
;
2157 TemplateAliasParameter
*TemplateAliasParameter::isTemplateAliasParameter()
2162 TemplateParameter
*TemplateAliasParameter::syntaxCopy()
2164 TemplateAliasParameter
*tp
= new TemplateAliasParameter(loc
, ident
, specAliasT
, defaultAlias
);
2166 tp
->specAliasT
= specAliasT
->syntaxCopy();
2168 tp
->defaultAlias
= defaultAlias
->syntaxCopy();
2172 void TemplateAliasParameter::declareParameter(Scope
*sc
)
2174 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2175 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2176 if (!sc
->insert(sparam
))
2177 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2180 void TemplateAliasParameter::semantic(Scope
*sc
)
2184 specAlias
= specAliasT
->toDsymbol(sc
);
2186 error("%s is not a symbol", specAliasT
->toChars());
2188 #if 0 // Don't do semantic() until instantiation
2190 defaultAlias
= defaultAlias
->semantic(loc
, sc
);
2194 int TemplateAliasParameter::overloadMatch(TemplateParameter
*tp
)
2196 TemplateAliasParameter
*tap
= tp
->isTemplateAliasParameter();
2200 if (specAlias
!= tap
->specAlias
)
2210 MATCH
TemplateAliasParameter::matchArg(Scope
*sc
,
2211 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2212 Declaration
**psparam
)
2218 //printf("TemplateAliasParameter::matchArg()\n");
2220 if (i
< tiargs
->dim
)
2221 oarg
= (Object
*)tiargs
->data
[i
];
2223 { // Get default argument instead
2224 oarg
= defaultArg(sc
);
2226 { assert(i
< dedtypes
->dim
);
2227 // It might have already been deduced
2228 oarg
= (Object
*)dedtypes
->data
[i
];
2234 sa
= getDsymbol(oarg
);
2240 if (!sa
|| sa
== sdummy
)
2242 if (sa
!= specAlias
)
2245 else if (dedtypes
->data
[i
])
2246 { // Must match already deduced symbol
2247 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
2252 dedtypes
->data
[i
] = sa
;
2254 *psparam
= new AliasDeclaration(loc
, ident
, sa
);
2259 return MATCHnomatch
;
2263 void TemplateAliasParameter::print(Object
*oarg
, Object
*oded
)
2265 fprintf(stderr
, " %s\n", ident
->toChars());
2267 Dsymbol
*sa
= isDsymbol(oded
);
2270 fprintf(stderr
, "\tArgument alias: %s\n", sa
->toChars());
2273 void TemplateAliasParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2275 buf
->writestring("alias ");
2276 buf
->writestring(ident
->toChars());
2279 buf
->writestring(" : ");
2280 specAliasT
->toCBuffer(buf
, NULL
, hgs
);
2284 buf
->writestring(" = ");
2285 defaultAlias
->toCBuffer(buf
, NULL
, hgs
);
2290 void *TemplateAliasParameter::dummyArg()
2297 sdummy
= new Dsymbol();
2304 Object
*TemplateAliasParameter::specialization()
2310 Object
*TemplateAliasParameter::defaultArg(Scope
*sc
)
2316 s
= defaultAlias
->toDsymbol(sc
);
2318 error("%s is not a symbol", defaultAlias
->toChars());
2323 /* ======================== TemplateValueParameter ========================== */
2327 Expression
*TemplateValueParameter::edummy
= NULL
;
2329 TemplateValueParameter::TemplateValueParameter(Loc loc
, Identifier
*ident
, Type
*valType
,
2330 Expression
*specValue
, Expression
*defaultValue
)
2331 : TemplateParameter(loc
, ident
)
2333 this->ident
= ident
;
2334 this->valType
= valType
;
2335 this->specValue
= specValue
;
2336 this->defaultValue
= defaultValue
;
2339 TemplateValueParameter
*TemplateValueParameter::isTemplateValueParameter()
2344 TemplateParameter
*TemplateValueParameter::syntaxCopy()
2346 TemplateValueParameter
*tp
=
2347 new TemplateValueParameter(loc
, ident
, valType
, specValue
, defaultValue
);
2348 tp
->valType
= valType
->syntaxCopy();
2350 tp
->specValue
= specValue
->syntaxCopy();
2352 tp
->defaultValue
= defaultValue
->syntaxCopy();
2356 void TemplateValueParameter::declareParameter(Scope
*sc
)
2358 VarDeclaration
*v
= new VarDeclaration(loc
, valType
, ident
, NULL
);
2359 v
->storage_class
= STCtemplateparameter
;
2361 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2365 void TemplateValueParameter::semantic(Scope
*sc
)
2367 sparam
->semantic(sc
);
2368 valType
= valType
->semantic(loc
, sc
);
2369 if (!(valType
->isintegral() || valType
->isfloating() || valType
->isString()) &&
2370 valType
->ty
!= Tident
)
2371 error(loc
, "arithmetic/string type expected for value-parameter, not %s", valType
->toChars());
2374 { Expression
*e
= specValue
;
2376 e
= e
->semantic(sc
);
2377 e
= e
->implicitCastTo(sc
, valType
);
2378 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2379 if (e
->op
== TOKint64
|| e
->op
== TOKfloat64
||
2380 e
->op
== TOKcomplex80
|| e
->op
== TOKnull
|| e
->op
== TOKstring
)
2385 #if 0 // defer semantic analysis to arg match
2387 { Expression
*e
= defaultValue
;
2389 e
= e
->semantic(sc
);
2390 e
= e
->implicitCastTo(sc
, valType
);
2391 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2392 if (e
->op
== TOKint64
)
2399 int TemplateValueParameter::overloadMatch(TemplateParameter
*tp
)
2401 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
2405 if (valType
!= tvp
->valType
)
2408 if (valType
&& !valType
->equals(tvp
->valType
))
2411 if (specValue
!= tvp
->specValue
)
2422 MATCH
TemplateValueParameter::matchArg(Scope
*sc
,
2423 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2424 Declaration
**psparam
)
2426 //printf("TemplateValueParameter::matchArg()\n");
2429 Declaration
*sparam
;
2430 MATCH m
= MATCHexact
;
2434 if (i
< tiargs
->dim
)
2435 oarg
= (Object
*)tiargs
->data
[i
];
2437 { // Get default argument instead
2438 oarg
= defaultArg(sc
);
2440 { assert(i
< dedtypes
->dim
);
2441 // It might have already been deduced
2442 oarg
= (Object
*)dedtypes
->data
[i
];
2448 ei
= isExpression(oarg
);
2456 if (!ei
|| ei
== edummy
)
2459 Expression
*e
= specValue
;
2461 e
= e
->semantic(sc
);
2462 e
= e
->implicitCastTo(sc
, valType
);
2463 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2465 ei
= ei
->syntaxCopy();
2466 ei
= ei
->semantic(sc
);
2467 ei
= ei
->optimize(WANTvalue
| WANTinterpret
);
2468 //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars());
2469 //printf("e : %s, %s\n", e->toChars(), e->type->toChars());
2473 else if (dedtypes
->data
[i
])
2474 { // Must match already deduced value
2475 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
2477 if (!ei
|| !ei
->equals(e
))
2481 //printf("valType: %s, ty = %d\n", valType->toChars(), valType->ty);
2482 vt
= valType
->semantic(0, sc
);
2483 //printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars());
2486 m
= (MATCH
)ei
->implicitConvTo(vt
);
2487 //printf("m: %d\n", m);
2491 dedtypes
->data
[i
] = ei
;
2493 init
= new ExpInitializer(loc
, ei
);
2494 sparam
= new VarDeclaration(loc
, vt
, ident
, init
);
2495 sparam
->storage_class
= STCconst
;
2500 //printf("\tno match\n");
2502 return MATCHnomatch
;
2506 void TemplateValueParameter::print(Object
*oarg
, Object
*oded
)
2508 fprintf(stderr
, " %s\n", ident
->toChars());
2510 Expression
*ea
= isExpression(oded
);
2513 fprintf(stderr
, "\tSpecialization: %s\n", specValue
->toChars());
2514 fprintf(stderr
, "\tArgument Value: %s\n", ea
? ea
->toChars() : "NULL");
2518 void TemplateValueParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2520 valType
->toCBuffer(buf
, ident
, hgs
);
2523 buf
->writestring(" : ");
2524 specValue
->toCBuffer(buf
, hgs
);
2528 buf
->writestring(" = ");
2529 defaultValue
->toCBuffer(buf
, hgs
);
2534 void *TemplateValueParameter::dummyArg()
2540 // Create a dummy value
2542 edummy
= valType
->defaultInit();
2549 Object
*TemplateValueParameter::specialization()
2555 Object
*TemplateValueParameter::defaultArg(Scope
*sc
)
2557 Expression
*e
= defaultValue
;
2560 e
= e
->syntaxCopy();
2561 e
= e
->semantic(sc
);
2563 if (e
->op
== TOKdefault
)
2564 { DefaultInitExp
*de
= (DefaultInitExp
*)e
;
2565 e
= de
->resolve(loc
, sc
);
2572 /* ======================== TemplateTupleParameter ========================== */
2574 // variadic-parameter
2576 TemplateTupleParameter::TemplateTupleParameter(Loc loc
, Identifier
*ident
)
2577 : TemplateParameter(loc
, ident
)
2579 this->ident
= ident
;
2582 TemplateTupleParameter
*TemplateTupleParameter::isTemplateTupleParameter()
2587 TemplateParameter
*TemplateTupleParameter::syntaxCopy()
2589 TemplateTupleParameter
*tp
= new TemplateTupleParameter(loc
, ident
);
2593 void TemplateTupleParameter::declareParameter(Scope
*sc
)
2595 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2596 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2597 if (!sc
->insert(sparam
))
2598 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2601 void TemplateTupleParameter::semantic(Scope
*sc
)
2605 int TemplateTupleParameter::overloadMatch(TemplateParameter
*tp
)
2607 TemplateTupleParameter
*tvp
= tp
->isTemplateTupleParameter();
2618 MATCH
TemplateTupleParameter::matchArg(Scope
*sc
,
2619 Objects
*tiargs
, int i
, TemplateParameters
*parameters
,
2621 Declaration
**psparam
)
2623 //printf("TemplateTupleParameter::matchArg()\n");
2625 /* The rest of the actual arguments (tiargs[]) form the match
2626 * for the variadic parameter.
2628 assert(i
+ 1 == dedtypes
->dim
); // must be the last one
2630 if (i
+ 1 == tiargs
->dim
&& isTuple((Object
*)tiargs
->data
[i
]))
2631 ovar
= isTuple((Object
*)tiargs
->data
[i
]);
2635 //printf("ovar = %p\n", ovar);
2636 if (i
< tiargs
->dim
)
2638 //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
2639 ovar
->objects
.setDim(tiargs
->dim
- i
);
2640 for (size_t j
= 0; j
< ovar
->objects
.dim
; j
++)
2641 ovar
->objects
.data
[j
] = tiargs
->data
[i
+ j
];
2644 *psparam
= new TupleDeclaration(loc
, ident
, &ovar
->objects
);
2645 dedtypes
->data
[i
] = (void *)ovar
;
2650 void TemplateTupleParameter::print(Object
*oarg
, Object
*oded
)
2652 printf(" %s... [", ident
->toChars());
2653 Tuple
*v
= isTuple(oded
);
2656 //printf("|%d| ", v->objects.dim);
2657 for (int i
= 0; i
< v
->objects
.dim
; i
++)
2662 Object
*o
= (Object
*)v
->objects
.data
[i
];
2664 Dsymbol
*sa
= isDsymbol(o
);
2666 printf("alias: %s", sa
->toChars());
2668 Type
*ta
= isType(o
);
2670 printf("type: %s", ta
->toChars());
2672 Expression
*ea
= isExpression(o
);
2674 printf("exp: %s", ea
->toChars());
2676 assert(!isTuple(o
)); // no nested Tuple arguments
2682 void TemplateTupleParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2684 buf
->writestring(ident
->toChars());
2685 buf
->writestring("...");
2689 void *TemplateTupleParameter::dummyArg()
2695 Object
*TemplateTupleParameter::specialization()
2701 Object
*TemplateTupleParameter::defaultArg(Scope
*sc
)
2706 /* ======================== TemplateInstance ================================ */
2708 TemplateInstance::TemplateInstance(Loc loc
, Identifier
*ident
)
2709 : ScopeDsymbol(NULL
)
2712 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident
? ident
->toChars() : "null");
2716 this->tiargs
= NULL
;
2717 this->tempdecl
= NULL
;
2719 this->argsym
= NULL
;
2720 this->aliasdecl
= NULL
;
2721 this->semanticdone
= 0;
2722 this->withsym
= NULL
;
2725 this->objFileModule
= NULL
;
2727 this->havetempdecl
= 0;
2728 this->isnested
= NULL
;
2733 TemplateInstance::TemplateInstance(Loc loc
, TemplateDeclaration
*td
, Objects
*tiargs
)
2734 : ScopeDsymbol(NULL
)
2737 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td
->toChars());
2740 this->name
= td
->ident
;
2741 this->tiargs
= tiargs
;
2742 this->tempdecl
= td
;
2744 this->argsym
= NULL
;
2745 this->aliasdecl
= NULL
;
2746 this->semanticdone
= 0;
2747 this->withsym
= NULL
;
2750 this->objFileModule
= NULL
;
2752 this->havetempdecl
= 1;
2753 this->isnested
= NULL
;
2756 assert((size_t)tempdecl
->scope
> 0x10000);
2760 Objects
*TemplateInstance::arraySyntaxCopy(Objects
*objs
)
2764 { a
= new Objects();
2765 a
->setDim(objs
->dim
);
2766 for (size_t i
= 0; i
< objs
->dim
; i
++)
2768 Type
*ta
= isType((Object
*)objs
->data
[i
]);
2770 a
->data
[i
] = ta
->syntaxCopy();
2773 Expression
*ea
= isExpression((Object
*)objs
->data
[i
]);
2775 a
->data
[i
] = ea
->syntaxCopy();
2782 Dsymbol
*TemplateInstance::syntaxCopy(Dsymbol
*s
)
2784 TemplateInstance
*ti
;
2788 ti
= (TemplateInstance
*)s
;
2790 ti
= new TemplateInstance(loc
, name
);
2792 ti
->tiargs
= arraySyntaxCopy(tiargs
);
2794 ScopeDsymbol::syntaxCopy(ti
);
2800 #include "d-dmd-gcc.h"
2803 void TemplateInstance::semantic(Scope
*sc
)
2809 /* Trying to soldier on rarely generates useful messages
2817 printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
2821 fprintf(stderr, "ti '%s' (%p), belongs in '%s'\n", toChars(), this,
2822 sc->module->toPrettyChars());
2824 fprintf(stderr, " -- really '%s' (%p)\n", inst->toChars(), inst);
2826 fprintf(stderr, " -- doing semantic\n");
2830 if (inst
) // if semantic() was already run
2833 printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst
->toChars(), inst
);
2838 if (semanticdone
!= 0)
2840 error(loc
, "recursive template expansion");
2847 printf("\tdo semantic\n");
2851 assert((size_t)tempdecl
->scope
> 0x10000);
2853 tdtypes
.setDim(tempdecl
->parameters
->dim
);
2854 if (!tempdecl
->matchWithInstance(this, &tdtypes
, 0))
2856 error("incompatible arguments for template instantiation");
2863 // Run semantic on each argument, place results in tiargs[]
2866 tempdecl
= findTemplateDeclaration(sc
);
2868 tempdecl
= findBestMatch(sc
);
2869 if (!tempdecl
|| global
.errors
)
2871 //printf("error return %p, %d\n", tempdecl, global.errors);
2872 return; // error recovery
2878 /* See if there is an existing TemplateInstantiation that already
2879 * implements the typeargs. If so, just refer to that one instead.
2882 for (size_t i
= 0; i
< tempdecl
->instances
.dim
; i
++)
2884 TemplateInstance
*ti
= (TemplateInstance
*)tempdecl
->instances
.data
[i
];
2886 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i
, ti
, ti
->toChars());
2888 assert(tdtypes
.dim
== ti
->tdtypes
.dim
);
2890 // Nesting must match
2891 if (isnested
!= ti
->isnested
)
2894 if (isnested
&& sc
->parent
!= ti
->parent
)
2897 for (size_t j
= 0; j
< tdtypes
.dim
; j
++)
2898 { Object
*o1
= (Object
*)tdtypes
.data
[j
];
2899 Object
*o2
= (Object
*)ti
->tdtypes
.data
[j
];
2900 if (!match(o1
, o2
, tempdecl
, sc
))
2906 parent
= ti
->parent
;
2908 printf("\tit's a match with instance %p\n", inst
);
2916 /* So, we need to implement 'this' instance.
2919 printf("\timplement template instance '%s'\n", toChars());
2921 unsigned errorsave
= global
.errors
;
2923 int tempdecl_instance_idx
= tempdecl
->instances
.dim
;
2924 tempdecl
->instances
.push(this);
2925 parent
= tempdecl
->parent
;
2926 //printf("parent = '%s'\n", parent->kind());
2928 ident
= genIdent(); // need an identifier for name mangling purposes.
2934 //printf("parent = '%s'\n", parent->kind());
2936 // Add 'this' to the enclosing scope's members[] so the semantic routines
2937 // will get called on the instance members
2939 int dosemantic3
= 0;
2943 /* For "all" and "private" template modes, templates are always
2944 emitted. Problem: This picks up templates that aren't even
2945 needed in the current module. */
2947 if (d_gcc_force_templates())
2949 //fprintf(stderr, "\t0: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
2950 objFileModule
= d_gcc_get_output_module();
2951 a
= objFileModule
->members
;
2956 if (sc
->scopesym
&& sc
->scopesym
->members
&& !sc
->scopesym
->isTemplateMixin())
2958 //printf("\t1: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
2959 a
= sc
->scopesym
->members
;
2962 Dsymbol
* p
= sc
->scopesym
;
2964 TemplateInstance
* i
;
2967 if ( (i
= p
->isTemplateInstance()) ) {
2968 if (i
->objFileModule
) {
2969 objFileModule
= i
->objFileModule
;
2972 } else if ( (m
= p
->isModule()) ) {
2973 objFileModule
= m
; // %% importedFrom ?
2978 // fprintf(stderr, "\t1: adding %s to module %s via %s %s\n", tempdecl->toChars(), objFileModule?objFileModule->toChars():"", sc->scopesym->kind(), sc->scopesym->toChars());
2983 { Module
*m
= sc
->module
->importedFrom
;
2984 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
2986 if (m
->semanticdone
>= 3)
2992 for (int i
= 0; 1; i
++)
2999 if (this == (Dsymbol
*)a
->data
[i
]) // if already in Array
3005 // Copy the syntax trees from the TemplateDeclaration
3006 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
3008 // Create our own scope for the template parameters
3009 Scope
*scope
= tempdecl
->scope
;
3012 error("forward reference to template declaration %s\n", tempdecl
->toChars());
3017 printf("\tcreate scope for template parameters '%s'\n", toChars());
3019 argsym
= new ScopeDsymbol();
3020 argsym
->parent
= scope
->parent
;
3021 scope
= scope
->push(argsym
);
3023 // Declare each template parameter as an alias for the argument type
3024 declareParameters(scope
);
3026 // Add members of template instance to template instance symbol table
3027 // parent = scope->scopesym;
3028 symtab
= new DsymbolTable();
3030 for (int i
= 0; i
< members
->dim
; i
++)
3032 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3034 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i
, s
->toChars(), s
, s
->kind(), this->toChars(), memnum
);
3036 memnum
|= s
->addMember(scope
, this, memnum
);
3039 printf("adding members done\n");
3042 /* See if there is only one member of template instance, and that
3043 * member has the same name as the template instance.
3044 * If so, this template instance becomes an alias for that member.
3046 //printf("members->dim = %d\n", members->dim);
3050 if (Dsymbol::oneMembers(members
, &s
) && s
)
3052 //printf("s->kind = '%s'\n", s->kind());
3054 //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
3055 if (s
->ident
&& s
->ident
->equals(tempdecl
->ident
))
3057 //printf("setting aliasdecl\n");
3058 aliasdecl
= new AliasDeclaration(loc
, s
->ident
, s
);
3063 // Do semantic() analysis on template instance members
3065 printf("\tdo semantic() on template instance members '%s'\n", toChars());
3068 sc2
= scope
->push(this);
3069 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
3070 sc2
->parent
= /*isnested ? sc->parent :*/ this;
3071 sc2
->inDtemplate
= !tempdecl
->dltSource
;
3079 for (int i
= 0; i
< members
->dim
; i
++)
3081 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3082 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
3083 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
3085 // s->parent = sc->parent;
3086 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3088 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3089 sc2
->module
->runDeferredSemantic();
3094 __except (__ehfilter(GetExceptionInformation()))
3096 global
.gag
= 0; // ensure error message gets printed
3097 error("recursive expansion");
3103 /* If any of the instantiation members didn't get semantic() run
3104 * on them due to forward references, we cannot run semantic2()
3105 * or semantic3() yet.
3107 for (size_t i
= 0; i
< Module::deferred
.dim
; i
++)
3108 { Dsymbol
*sd
= (Dsymbol
*)Module::deferred
.data
[i
];
3110 if (sd
->parent
== this)
3111 goto Laftersemantic
;
3114 /* The problem is when to parse the initializer for a variable.
3115 * Perhaps VarDeclaration::semantic() should do it like it does
3116 * for initializers inside a function.
3118 // if (sc->parent->isFuncDeclaration())
3120 /* BUG 782: this has problems if the classes this depends on
3121 * are forward referenced. Find a way to defer semantic()
3126 if (sc
->func
|| dosemantic3
)
3136 // Give additional context info if error occurred during instantiation
3137 if (global
.errors
!= errorsave
)
3139 error("error instantiating");
3142 tempdecl
->instances
.remove(tempdecl_instance_idx
);
3146 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3151 void TemplateInstance::semanticTiargs(Scope
*sc
)
3153 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3154 semanticTiargs(loc
, sc
, tiargs
);
3157 void TemplateInstance::semanticTiargs(Loc loc
, Scope
*sc
, Objects
*tiargs
)
3159 // Run semantic on each argument, place results in tiargs[]
3160 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3163 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3165 Object
*o
= (Object
*)tiargs
->data
[j
];
3166 Type
*ta
= isType(o
);
3167 Expression
*ea
= isExpression(o
);
3168 Dsymbol
*sa
= isDsymbol(o
);
3170 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
3173 //printf("type %s\n", ta->toChars());
3174 // It might really be an Expression or an Alias
3175 ta
->resolve(loc
, sc
, &ea
, &ta
, &sa
);
3178 ea
= ea
->semantic(sc
);
3179 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3180 tiargs
->data
[j
] = ea
;
3183 { tiargs
->data
[j
] = sa
;
3184 TupleDeclaration
*d
= sa
->toAlias()->isTupleDeclaration();
3187 size_t dim
= d
->objects
->dim
;
3189 tiargs
->insert(j
, d
->objects
);
3195 if (ta
->ty
== Ttuple
)
3197 TypeTuple
*tt
= (TypeTuple
*)ta
;
3198 size_t dim
= tt
->arguments
->dim
;
3201 { tiargs
->reserve(dim
);
3202 for (size_t i
= 0; i
< dim
; i
++)
3203 { Argument
*arg
= (Argument
*)tt
->arguments
->data
[i
];
3204 tiargs
->insert(j
+ i
, arg
->type
);
3210 tiargs
->data
[j
] = ta
;
3214 assert(global
.errors
);
3215 tiargs
->data
[j
] = Type::terror
;
3221 { assert(global
.errors
);
3222 ea
= new IntegerExp(0);
3225 ea
= ea
->semantic(sc
);
3226 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3227 tiargs
->data
[j
] = ea
;
3228 if (ea
->op
== TOKtype
)
3229 tiargs
->data
[j
] = ea
->type
;
3238 //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
3241 printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
3242 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3244 Object
*o
= (Object
*)tiargs
->data
[j
];
3245 Type
*ta
= isType(o
);
3246 Expression
*ea
= isExpression(o
);
3247 Dsymbol
*sa
= isDsymbol(o
);
3248 Tuple
*va
= isTuple(o
);
3250 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j
, ta
, ea
, sa
, va
);
3255 /**********************************************
3256 * Find template declaration corresponding to template instance.
3259 TemplateDeclaration
*TemplateInstance::findTemplateDeclaration(Scope
*sc
)
3261 //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
3266 * figure out which TemplateDeclaration foo refers to.
3274 s
= sc
->search(loc
, id
, &scopesym
);
3276 { error("identifier '%s' is not defined", id
->toChars());
3280 printf("It's an instance of '%s' kind '%s'\n", s
->toChars(), s
->kind());
3282 printf("s->parent = '%s'\n", s
->parent
->toChars());
3284 withsym
= scopesym
->isWithScopeSymbol();
3286 /* We might have found an alias within a template when
3287 * we really want the template.
3289 TemplateInstance
*ti
;
3291 (ti
= s
->parent
->isTemplateInstance()) != NULL
)
3295 ti
->toAlias()->ident
== id
)
3299 /* This is so that one can refer to the enclosing
3300 * template, even if it has the same name as a member
3301 * of the template, if it has a !(arguments)
3303 tempdecl
= ti
->tempdecl
;
3304 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3305 tempdecl
= tempdecl
->overroot
; // then get the start
3312 /* It should be a TemplateDeclaration, not some other symbol
3314 tempdecl
= s
->isTemplateDeclaration();
3317 if (!s
->parent
&& global
.errors
)
3319 if (!s
->parent
&& s
->getType())
3320 { Dsymbol
*s2
= s
->getType()->toDsymbol(sc
);
3323 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3329 //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
3331 //assert(s->parent);
3332 TemplateInstance
*ti
= s
->parent
? s
->parent
->isTemplateInstance() : NULL
;
3335 ti
->toAlias()->ident
== id
)
3339 /* This is so that one can refer to the enclosing
3340 * template, even if it has the same name as a member
3341 * of the template, if it has a !(arguments)
3343 tempdecl
= ti
->tempdecl
;
3344 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3345 tempdecl
= tempdecl
->overroot
; // then get the start
3349 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3355 assert(tempdecl
->isTemplateDeclaration());
3359 TemplateDeclaration
*TemplateInstance::findBestMatch(Scope
*sc
)
3361 /* Since there can be multiple TemplateDeclaration's with the same
3362 * name, look for the best match.
3364 TemplateDeclaration
*td_ambig
= NULL
;
3365 TemplateDeclaration
*td_best
= NULL
;
3366 MATCH m_best
= MATCHnomatch
;
3370 printf("TemplateInstance::findBestMatch()\n");
3372 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
3376 //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
3378 // If more arguments than parameters,
3379 // then this is no match.
3380 if (td
->parameters
->dim
< tiargs
->dim
)
3382 if (!td
->isVariadic())
3386 dedtypes
.setDim(td
->parameters
->dim
);
3390 error("forward reference to template declaration %s", td
->toChars());
3393 m
= td
->matchWithInstance(this, &dedtypes
, 0);
3394 //printf("m = %d\n", m);
3395 if (!m
) // no match at all
3408 // Disambiguate by picking the most specialized TemplateDeclaration
3409 int c1
= td
->leastAsSpecialized(td_best
);
3410 int c2
= td_best
->leastAsSpecialized(td
);
3411 //printf("c1 = %d, c2 = %d\n", c1, c2);
3421 Lambig
: // td_best and td are ambiguous
3425 Ltd_best
: // td_best is the best match so far
3429 Ltd
: // td is the new best match
3433 tdtypes
.setDim(dedtypes
.dim
);
3434 memcpy(tdtypes
.data
, dedtypes
.data
, tdtypes
.dim
* sizeof(void *));
3440 error("%s does not match any template declaration", toChars());
3445 error("%s matches more than one template declaration, %s and %s",
3446 toChars(), td_best
->toChars(), td_ambig
->toChars());
3449 /* The best match is td_best
3454 /* Cast any value arguments to be same type as value parameter
3456 for (size_t i
= 0; i
< tiargs
->dim
; i
++)
3457 { Object
*o
= (Object
*)tiargs
->data
[i
];
3458 Expression
*ea
= isExpression(o
); // value argument
3459 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3461 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3465 ea
= ea
->castTo(tvp
->valType
);
3466 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3467 tiargs
->data
[i
] = (Object
*)ea
;
3473 printf("\tIt's a match with template declaration '%s'\n", tempdecl
->toChars());
3479 /*****************************************
3480 * Determines if a TemplateInstance will need a nested
3481 * generation of the TemplateDeclaration.
3484 int TemplateInstance::isNested(Objects
*args
)
3486 //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars());
3488 /* A nested instance happens when an argument references a local
3489 * symbol that is on the stack.
3491 for (size_t i
= 0; i
< args
->dim
; i
++)
3492 { Object
*o
= (Object
*)args
->data
[i
];
3493 Expression
*ea
= isExpression(o
);
3494 Dsymbol
*sa
= isDsymbol(o
);
3495 Tuple
*va
= isTuple(o
);
3498 if (ea
->op
== TOKvar
)
3500 sa
= ((VarExp
*)ea
)->var
;
3503 if (ea
->op
== TOKfunction
)
3505 sa
= ((FuncExp
*)ea
)->fd
;
3512 Declaration
*d
= sa
->isDeclaration();
3513 if (d
&& !d
->isDataseg() &&
3515 !(d
->storage_class
& STCmanifest
) &&
3517 (!d
->isFuncDeclaration() || d
->isFuncDeclaration()->isNested()) &&
3520 // if module level template
3521 if (tempdecl
->toParent()->isModule())
3522 { Dsymbol
*dparent
= d
->toParent();
3525 else if (isnested
!= dparent
)
3527 /* Select the more deeply nested of the two.
3528 * Error if one is not nested inside the other.
3530 for (Dsymbol
*p
= isnested
; p
; p
= p
->parent
)
3533 goto L1
; // isnested is most nested
3535 for (Dsymbol
*p
= dparent
; 1; p
= p
->parent
)
3538 { isnested
= dparent
;
3539 goto L1
; // dparent is most nested
3542 error("is nested in both %s and %s", isnested
->toChars(), dparent
->toChars());
3545 //printf("\tnested inside %s\n", isnested->toChars());
3549 error("cannot use local '%s' as template parameter", d
->toChars());
3554 nested
|= isNested(&va
->objects
);
3560 /****************************************
3561 * This instance needs an identifier for name mangling purposes.
3562 * Create one by taking the template declaration name and adding
3563 * the type signature for it.
3566 Identifier
*TemplateInstance::genIdent()
3571 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
3572 id
= tempdecl
->ident
->toChars();
3573 buf
.printf("__T%"PRIuSIZE
"%s", strlen(id
), id
);
3575 for (int i
= 0; i
< args
->dim
; i
++)
3576 { Object
*o
= (Object
*)args
->data
[i
];
3577 Type
*ta
= isType(o
);
3578 Expression
*ea
= isExpression(o
);
3579 Dsymbol
*sa
= isDsymbol(o
);
3580 Tuple
*va
= isTuple(o
);
3581 //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
3586 buf
.writestring(ta
->deco
);
3590 printf("ta = %d, %s\n", ta
->ty
, ta
->toChars());
3592 assert(global
.errors
);
3599 if (ea
->op
== TOKvar
)
3601 sa
= ((VarExp
*)ea
)->var
;
3605 if (ea
->op
== TOKfunction
)
3607 sa
= ((FuncExp
*)ea
)->fd
;
3612 if (ea
->op
== TOKtuple
)
3613 { ea
->error("tuple is not a valid template value argument");
3617 /* Use deco that matches what it would be for a function parameter
3619 buf
.writestring(ea
->type
->deco
);
3621 // Use type of parameter, not type of argument
3622 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3624 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3626 buf
.writestring(tvp
->valType
->deco
);
3628 ea
->toMangleBuffer(&buf
);
3634 Declaration
*d
= sa
->isDeclaration();
3635 if (d
&& !d
->type
->deco
)
3636 error("forward reference of %s", d
->toChars());
3639 char *p
= sa
->mangle();
3640 buf
.printf("%"PRIuSIZE
"%s", strlen(p
), p
);
3645 assert(i
+ 1 == args
->dim
); // must be last one
3646 args
= &va
->objects
;
3655 return new Identifier(id
, TOKidentifier
);
3659 /****************************************************
3660 * Declare parameters of template instance, initialize them with the
3661 * template instance arguments.
3664 void TemplateInstance::declareParameters(Scope
*scope
)
3666 //printf("TemplateInstance::declareParameters()\n");
3667 for (int i
= 0; i
< tdtypes
.dim
; i
++)
3669 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3670 //Object *o = (Object *)tiargs->data[i];
3671 Object
*o
= (Object
*)tdtypes
.data
[i
];
3673 //printf("\ttdtypes[%d] = %p\n", i, o);
3674 tempdecl
->declareParameter(scope
, tp
, o
);
3679 void TemplateInstance::semantic2(Scope
*sc
)
3682 if (semanticdone
>= 2)
3686 printf("+TemplateInstance::semantic2('%s')\n", toChars());
3688 if (!errors
&& members
)
3690 sc
= tempdecl
->scope
;
3692 sc
= sc
->push(argsym
);
3693 sc
= sc
->push(this);
3694 for (i
= 0; i
< members
->dim
; i
++)
3696 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3698 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
3706 printf("-TemplateInstance::semantic2('%s')\n", toChars());
3710 void TemplateInstance::semantic3(Scope
*sc
)
3713 printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone
);
3715 //if (toChars()[0] == 'D') *(char*)0=0;
3716 if (semanticdone
>= 3)
3719 if (!errors
&& members
)
3721 sc
= tempdecl
->scope
;
3722 sc
= sc
->push(argsym
);
3723 sc
= sc
->push(this);
3724 sc
->inDtemplate
= !tempdecl
->dltSource
;
3725 for (int i
= 0; i
< members
->dim
; i
++)
3727 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3735 void TemplateInstance::toObjFile(int multiobj
)
3738 printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
3740 if (!errors
&& members
)
3743 // Append to list of object files to be written later
3747 for (int i
= 0; i
< members
->dim
; i
++)
3749 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3750 s
->toObjFile(multiobj
);
3756 void TemplateInstance::inlineScan()
3759 printf("TemplateInstance::inlineScan('%s')\n", toChars());
3761 if (!errors
&& members
)
3763 for (int i
= 0; i
< members
->dim
; i
++)
3765 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3771 void TemplateInstance::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3775 Identifier
*id
= name
;
3776 buf
->writestring(id
->toChars());
3777 buf
->writestring("!(");
3779 buf
->writestring("...");
3783 Objects
*args
= tiargs
;
3784 for (i
= 0; i
< args
->dim
; i
++)
3787 buf
->writeByte(',');
3788 Object
*oarg
= (Object
*)args
->data
[i
];
3789 ObjectToCBuffer(buf
, hgs
, oarg
);
3793 buf
->writeByte(')');
3797 Dsymbol
*TemplateInstance::toAlias()
3800 printf("TemplateInstance::toAlias()\n");
3803 { error("cannot resolve forward reference");
3808 return inst
->toAlias();
3811 return aliasdecl
->toAlias();
3816 AliasDeclaration
*TemplateInstance::isAliasDeclaration()
3821 char *TemplateInstance::kind()
3823 return "template instance";
3826 int TemplateInstance::oneMember(Dsymbol
**ps
)
3832 char *TemplateInstance::toChars()
3838 toCBuffer(&buf
, &hgs
);
3844 /* ======================== TemplateMixin ================================ */
3846 TemplateMixin::TemplateMixin(Loc loc
, Identifier
*ident
, Type
*tqual
,
3847 Array
*idents
, Objects
*tiargs
)
3848 : TemplateInstance(loc
, (Identifier
*)idents
->data
[idents
->dim
- 1])
3850 //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
3851 this->ident
= ident
;
3852 this->tqual
= tqual
;
3853 this->idents
= idents
;
3854 this->tiargs
= tiargs
? tiargs
: new Objects();
3858 Dsymbol
*TemplateMixin::syntaxCopy(Dsymbol
*s
)
3859 { TemplateMixin
*tm
;
3861 Array
*ids
= new Array();
3862 ids
->setDim(idents
->dim
);
3863 for (int i
= 0; i
< idents
->dim
; i
++)
3864 { // Matches TypeQualified::syntaxCopyHelper()
3865 Identifier
*id
= (Identifier
*)idents
->data
[i
];
3866 if (id
->dyncast() == DYNCAST_DSYMBOL
)
3868 TemplateInstance
*ti
= (TemplateInstance
*)id
;
3870 ti
= (TemplateInstance
*)ti
->syntaxCopy(NULL
);
3871 id
= (Identifier
*)ti
;
3876 tm
= new TemplateMixin(loc
, ident
,
3877 (Type
*)(tqual
? tqual
->syntaxCopy() : NULL
),
3879 TemplateInstance::syntaxCopy(tm
);
3883 void TemplateMixin::semantic(Scope
*sc
)
3886 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
3890 // This for when a class/struct contains mixin members, and
3891 // is done over because of forward references
3892 (!parent
|| !toParent()->isAggregateDeclaration()))
3895 printf("\tsemantic done\n");
3902 printf("\tdo semantic\n");
3908 scx
= scope
; // save so we don't make redundant copies
3912 // Follow qualifications to find the TemplateDeclaration
3919 { s
= tqual
->toDsymbol(sc
);
3925 id
= (Identifier
*)idents
->data
[0];
3926 switch (id
->dyncast())
3928 case DYNCAST_IDENTIFIER
:
3929 s
= sc
->search(loc
, id
, NULL
);
3932 case DYNCAST_DSYMBOL
:
3934 TemplateInstance
*ti
= (TemplateInstance
*)id
;
3944 for (; i
< idents
->dim
; i
++)
3948 id
= (Identifier
*)idents
->data
[i
];
3949 s
= s
->searchX(loc
, sc
, id
);
3953 error("is not defined");
3957 tempdecl
= s
->toAlias()->isTemplateDeclaration();
3960 error("%s isn't a template", s
->toChars());
3966 // Look for forward reference
3968 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
3972 /* Cannot handle forward references if mixin is a struct member,
3973 * because addField must happen during struct's semantic, not
3974 * during the mixin semantic.
3975 * runDeferred will re-run mixin's semantic outside of the struct's
3979 AggregateDeclaration
*ad
= toParent()->isAggregateDeclaration();
3984 // Forward reference
3985 //printf("forward reference - deferring\n");
3986 scope
= scx
? scx
: new Scope(*sc
);
3988 scope
->module
->addDeferredSemantic(this);
3994 // Run semantic on each argument, place results in tiargs[]
3997 tempdecl
= findBestMatch(sc
);
4000 return; // error recovery
4007 parent
= sc
->parent
;
4009 /* Detect recursive mixin instantiations.
4011 for (Dsymbol
*s
= parent
; s
; s
= s
->parent
)
4013 //printf("\ts = '%s'\n", s->toChars());
4014 TemplateMixin
*tm
= s
->isTemplateMixin();
4015 if (!tm
|| tempdecl
!= tm
->tempdecl
)
4018 for (int i
= 0; i
< tiargs
->dim
; i
++)
4019 { Object
*o
= (Object
*)tiargs
->data
[i
];
4020 Type
*ta
= isType(o
);
4021 Expression
*ea
= isExpression(o
);
4022 Dsymbol
*sa
= isDsymbol(o
);
4023 Object
*tmo
= (Object
*)tm
->tiargs
->data
[i
];
4026 Type
*tmta
= isType(tmo
);
4029 if (!ta
->equals(tmta
))
4033 { Expression
*tme
= isExpression(tmo
);
4034 if (!tme
|| !ea
->equals(tme
))
4039 Dsymbol
*tmsa
= isDsymbol(tmo
);
4046 error("recursive mixin instantiation");
4053 // Copy the syntax trees from the TemplateDeclaration
4054 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
4058 symtab
= new DsymbolTable();
4060 for (Scope
*sce
= sc
; 1; sce
= sce
->enclosing
)
4062 ScopeDsymbol
*sds
= (ScopeDsymbol
*)sce
->scopesym
;
4065 sds
->importScope(this, PROTpublic
);
4071 printf("\tcreate scope for template parameters '%s'\n", toChars());
4074 scy
= sc
->push(this);
4077 argsym
= new ScopeDsymbol();
4078 argsym
->parent
= scy
->parent
;
4079 Scope
*scope
= scy
->push(argsym
);
4081 unsigned errorsave
= global
.errors
;
4083 // Declare each template parameter as an alias for the argument type
4084 declareParameters(scope
);
4086 // Add members to enclosing scope, as well as this scope
4087 for (unsigned i
= 0; i
< members
->dim
; i
++)
4090 s
= (Dsymbol
*)members
->data
[i
];
4091 s
->addMember(scope
, this, i
);
4093 //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
4094 //printf("s->parent = %s\n", s->parent->toChars());
4097 // Do semantic() analysis on template instance members
4099 printf("\tdo semantic() on template instance members '%s'\n", toChars());
4102 sc2
= scope
->push(this);
4103 sc2
->offset
= sc
->offset
;
4104 for (int i
= 0; i
< members
->dim
; i
++)
4106 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4109 sc
->offset
= sc2
->offset
;
4111 /* The problem is when to parse the initializer for a variable.
4112 * Perhaps VarDeclaration::semantic() should do it like it does
4113 * for initializers inside a function.
4115 // if (sc->parent->isFuncDeclaration())
4124 // Give additional context info if error occurred during instantiation
4125 if (global
.errors
!= errorsave
)
4127 error("error instantiating");
4134 // if (!isAnonymous())
4139 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
4143 void TemplateMixin::semantic2(Scope
*sc
)
4146 if (semanticdone
>= 2)
4150 printf("+TemplateMixin::semantic2('%s')\n", toChars());
4155 sc
= sc
->push(argsym
);
4156 sc
= sc
->push(this);
4157 for (i
= 0; i
< members
->dim
; i
++)
4159 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4161 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
4169 printf("-TemplateMixin::semantic2('%s')\n", toChars());
4173 void TemplateMixin::semantic3(Scope
*sc
)
4176 if (semanticdone
>= 3)
4180 printf("TemplateMixin::semantic3('%s')\n", toChars());
4184 sc
= sc
->push(argsym
);
4185 sc
= sc
->push(this);
4186 for (i
= 0; i
< members
->dim
; i
++)
4188 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4196 void TemplateMixin::inlineScan()
4198 TemplateInstance::inlineScan();
4201 char *TemplateMixin::kind()
4206 int TemplateMixin::oneMember(Dsymbol
**ps
)
4208 return Dsymbol::oneMember(ps
);
4211 int TemplateMixin::hasPointers()
4213 //printf("TemplateMixin::hasPointers() %s\n", toChars());
4214 for (size_t i
= 0; i
< members
->dim
; i
++)
4216 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4217 //printf(" s = %s %s\n", s->kind(), s->toChars());
4218 if (s
->hasPointers())
4226 char *TemplateMixin::toChars()
4232 TemplateInstance::toCBuffer(&buf
, &hgs
);
4238 void TemplateMixin::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4240 buf
->writestring("mixin ");
4242 for (i
= 0; i
< idents
->dim
; i
++)
4243 { Identifier
*id
= (Identifier
*)idents
->data
[i
];
4246 buf
->writeByte('.');
4247 buf
->writestring(id
->toChars());
4249 buf
->writestring("!(");
4252 for (i
= 0; i
< tiargs
->dim
; i
++)
4254 buf
->writebyte(',');
4255 Object
*oarg
= (Object
*)tiargs
->data
[i
];
4256 Type
*t
= isType(oarg
);
4257 Expression
*e
= isExpression(oarg
);
4258 Dsymbol
*s
= isDsymbol(oarg
);
4260 t
->toCBuffer(buf
, NULL
, hgs
);
4262 e
->toCBuffer(buf
, hgs
);
4265 char *p
= s
->ident
? s
->ident
->toChars() : s
->toChars();
4266 buf
->writestring(p
);
4270 buf
->writestring("NULL");
4278 buf
->writebyte(')');
4279 buf
->writebyte(';');
4284 void TemplateMixin::toObjFile(int multiobj
)
4286 //printf("TemplateMixin::toObjFile('%s')\n", toChars());
4287 TemplateInstance::toObjFile(multiobj
);