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 * match this is at least as specialized as td2
614 * 0 td2 is more specialized than this
617 MATCH
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 MATCH m
= td2
->matchWithInstance(&ti
, &dedtypes
, 1);
658 /* A non-variadic template is more specialized than a
661 if (isVariadic() && !td2
->isVariadic())
665 printf(" matches %d, so is least as specialized\n", m
);
671 printf(" doesn't match, so is not as specialized\n");
677 /*************************************************
678 * Match function arguments against a specific template function.
680 * loc instantiation location
681 * targsi Expression/Type initial list of template arguments
682 * ethis 'this' argument if !NULL
683 * fargs arguments to function
685 * dedargs Expression/Type deduced template arguments
690 MATCH
TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc
, Objects
*targsi
,
691 Expression
*ethis
, Expressions
*fargs
,
697 size_t nargsi
; // array size of targsi
700 MATCH match
= MATCHexact
;
701 FuncDeclaration
*fd
= onemember
->toAlias()->isFuncDeclaration();
702 TypeFunction
*fdtype
; // type of fd
703 TemplateTupleParameter
*tp
;
704 Objects dedtypes
; // for T:T*, the dedargs is the T*, dedtypes is the T
707 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
708 for (i
= 0; i
< fargs
->dim
; i
++)
709 { Expression
*e
= (Expression
*)fargs
->data
[i
];
710 printf("\tfarg[%d] is %s, type is %s\n", i
, e
->toChars(), e
->type
->toChars());
714 assert((size_t)scope
> 0x10000);
716 dedargs
->setDim(parameters
->dim
);
719 dedtypes
.setDim(parameters
->dim
);
722 // Set up scope for parameters
723 ScopeDsymbol
*paramsym
= new ScopeDsymbol();
724 paramsym
->parent
= scope
->parent
;
725 Scope
*paramscope
= scope
->push(paramsym
);
731 { // Set initial template arguments
733 nargsi
= targsi
->dim
;
734 if (nargsi
> parameters
->dim
)
737 dedargs
->setDim(nargsi
);
741 memcpy(dedargs
->data
, targsi
->data
, nargsi
* sizeof(*dedargs
->data
));
743 for (i
= 0; i
< nargsi
; i
++)
744 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
748 m
= tp
->matchArg(paramscope
, dedargs
, i
, parameters
, &dedtypes
, &sparam
);
749 //printf("\tdeduceType m = %d\n", m);
750 if (m
== MATCHnomatch
)
755 sparam
->semantic(paramscope
);
756 if (!paramscope
->insert(sparam
))
761 assert(fd
->type
->ty
== Tfunction
);
762 fdtype
= (TypeFunction
*)fd
->type
;
764 nfparams
= Argument::dim(fdtype
->parameters
); // number of function parameters
765 nfargs
= fargs
->dim
; // number of function arguments
767 /* Check for match of function arguments with variadic template
768 * parameter, such as:
770 * template Foo(T, A...) { void Foo(T t, A a); }
771 * void main() { Foo(1,2,3); }
773 if (tp
) // if variadic
775 if (nfparams
== 0) // if no function parameters
777 Tuple
*t
= new Tuple();
778 //printf("t = %p\n", t);
779 dedargs
->data
[parameters
->dim
- 1] = (void *)t
;
782 else if (nfargs
< nfparams
- 1)
786 /* Figure out which of the function parameters matches
787 * the tuple template parameter. Do this by matching
789 * Set the index of this function parameter to fptupindex.
791 for (fptupindex
= 0; fptupindex
< nfparams
; fptupindex
++)
793 Argument
*fparam
= (Argument
*)fdtype
->parameters
->data
[fptupindex
];
794 if (fparam
->type
->ty
!= Tident
)
796 TypeIdentifier
*tid
= (TypeIdentifier
*)fparam
->type
;
797 if (!tp
->ident
->equals(tid
->ident
) || tid
->idents
.dim
)
800 if (fdtype
->varargs
) // variadic function doesn't
801 goto Lnomatch
; // go with variadic template
803 /* The types of the function arguments
804 * now form the tuple argument.
806 Tuple
*t
= new Tuple();
807 dedargs
->data
[parameters
->dim
- 1] = (void *)t
;
809 tuple_dim
= nfargs
- (nfparams
- 1);
810 t
->objects
.setDim(tuple_dim
);
811 for (i
= 0; i
< tuple_dim
; i
++)
812 { Expression
*farg
= (Expression
*)fargs
->data
[fptupindex
+ i
];
813 t
->objects
.data
[i
] = (void *)farg
->type
;
822 if (nfparams
== nfargs
)
824 else if (nfargs
> nfparams
)
826 if (fdtype
->varargs
== 0)
827 goto Lnomatch
; // too many args, no match
828 match
= MATCHconvert
; // match ... with a conversion
832 // Match 'ethis' to any TemplateThisParameter's
835 for (size_t i
= 0; i
< parameters
->dim
; i
++)
836 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
837 TemplateThisParameter
*ttp
= tp
->isTemplateThisParameter();
841 Type
*t
= new TypeIdentifier(0, ttp
->ident
);
842 m
= ethis
->type
->deduceType(scope
, t
, parameters
, &dedtypes
);
846 match
= m
; // pick worst match
851 // Loop through the function parameters
852 for (i
= 0; i
< nfparams
; i
++)
854 /* Skip over function parameters which wound up
855 * as part of a template tuple parameter.
858 { if (fptupindex
== nfparams
- 1)
864 Argument
*fparam
= Argument::getNth(fdtype
->parameters
, i
);
866 if (i
>= nfargs
) // if not enough arguments
868 if (fparam
->defaultArg
)
869 { /* Default arguments do not participate in template argument
876 { Expression
*farg
= (Expression
*)fargs
->data
[i
];
878 printf("\tfarg->type = %s\n", farg
->type
->toChars());
879 printf("\tfparam->type = %s\n", fparam
->type
->toChars());
882 //m = farg->type->toHeadMutable()->deduceType(scope, fparam->type, parameters, &dedtypes);
883 m
= farg
->type
->deduceType(scope
, fparam
->type
, parameters
, &dedtypes
);
884 //printf("\tdeduceType m = %d\n", m);
886 /* If no match, see if there's a conversion to a delegate
888 if (!m
&& fparam
->type
->toBasetype()->ty
== Tdelegate
)
890 TypeDelegate
*td
= (TypeDelegate
*)fparam
->type
->toBasetype();
891 TypeFunction
*tf
= (TypeFunction
*)td
->next
;
893 if (!tf
->varargs
&& Argument::dim(tf
->parameters
) == 0)
895 m
= farg
->type
->deduceType(scope
, tf
->next
, parameters
, &dedtypes
);
896 if (!m
&& tf
->next
->toBasetype()->ty
== Tvoid
)
899 //printf("\tm2 = %d\n", m);
904 match
= m
; // pick worst match
908 if (!(fdtype
->varargs
== 2 && i
+ 1 == nfparams
))
911 /* Check for match with function parameter T...
913 Type
*t
= fparam
->type
;
916 // Perhaps we can do better with this, see TypeFunction::callMatch()
930 /* Fill in any missing arguments with their defaults.
932 for (i
= nargsi
; i
< dedargs
->dim
; i
++)
934 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
935 //printf("tp[%d] = %s\n", i, tp->ident->toChars());
936 /* For T:T*, the dedargs is the T*, dedtypes is the T
937 * But for function templates, we really need them to match
939 Object
*oarg
= (Object
*)dedargs
->data
[i
];
940 Object
*oded
= (Object
*)dedtypes
.data
[i
];
941 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
946 if (tp
->specialization())
947 { /* The specialization can work as long as afterwards
951 dedargs
->data
[i
] = (void *)oded
;
952 MATCH m2
= tp
->matchArg(paramscope
, dedargs
, i
, parameters
, &dedtypes
, &sparam
, 0);
953 //printf("m2 = %d\n", m2);
957 match
= m2
; // pick worst match
958 if (dedtypes
.data
[i
] != oded
)
959 error("specialization not allowed for deduced parameter %s", tp
->ident
->toChars());
963 { oded
= tp
->defaultArg(loc
, paramscope
);
967 declareParameter(paramscope
, tp
, oded
);
968 dedargs
->data
[i
] = (void *)oded
;
973 for (i
= 0; i
< dedargs
->dim
; i
++)
974 { Type
*t
= (Type
*)dedargs
->data
[i
];
975 printf("\tdedargs[%d] = %d, %s\n", i
, t
->dyncast(), t
->toChars());
980 //printf("\tmatch %d\n", match);
985 //printf("\tnomatch\n");
989 /**************************************************
990 * Declare template parameter tp with value o.
993 void TemplateDeclaration::declareParameter(Scope
*sc
, TemplateParameter
*tp
, Object
*o
)
995 //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);
997 Type
*targ
= isType(o
);
998 Expression
*ea
= isExpression(o
);
999 Dsymbol
*sa
= isDsymbol(o
);
1000 Tuple
*va
= isTuple(o
);
1006 //printf("type %s\n", targ->toChars());
1007 s
= new AliasDeclaration(0, tp
->ident
, targ
);
1011 //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
1012 s
= new AliasDeclaration(0, tp
->ident
, sa
);
1016 // tdtypes.data[i] always matches ea here
1017 Initializer
*init
= new ExpInitializer(loc
, ea
);
1018 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1021 VarDeclaration
*v
= new VarDeclaration(loc
, tvp
->valType
, tp
->ident
, init
);
1022 v
->storage_class
= STCmanifest
;
1027 //printf("\ttuple\n");
1028 s
= new TupleDeclaration(loc
, tp
->ident
, &va
->objects
);
1038 error("declaration %s is already defined", tp
->ident
->toChars());
1042 /**************************************
1043 * Determine if TemplateDeclaration is variadic.
1046 TemplateTupleParameter
*isVariadic(TemplateParameters
*parameters
)
1047 { size_t dim
= parameters
->dim
;
1048 TemplateTupleParameter
*tp
= NULL
;
1051 tp
= ((TemplateParameter
*)parameters
->data
[dim
- 1])->isTemplateTupleParameter();
1055 TemplateTupleParameter
*TemplateDeclaration::isVariadic()
1057 return ::isVariadic(parameters
);
1060 /***********************************
1061 * We can overload templates.
1064 int TemplateDeclaration::isOverloadable()
1069 /*************************************************
1070 * Given function arguments, figure out which template function
1071 * to expand, and return that function.
1072 * If no match, give error message and return NULL.
1074 * sc instantiation scope
1075 * loc instantiation location
1076 * targsi initial list of template arguments
1077 * ethis if !NULL, the 'this' pointer argument
1078 * fargs arguments to function
1079 * flags 1: do not issue error message on no match, just return NULL
1082 FuncDeclaration
*TemplateDeclaration::deduceFunctionTemplate(Scope
*sc
, Loc loc
,
1083 Objects
*targsi
, Expression
*ethis
, Expressions
*fargs
, int flags
)
1085 MATCH m_best
= MATCHnomatch
;
1086 TemplateDeclaration
*td_ambig
= NULL
;
1087 TemplateDeclaration
*td_best
= NULL
;
1088 Objects
*tdargs
= new Objects();
1089 TemplateInstance
*ti
;
1090 FuncDeclaration
*fd
;
1093 printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
1094 printf(" targsi:\n");
1096 { for (int i
= 0; i
< targsi
->dim
; i
++)
1097 { Object
*arg
= (Object
*)targsi
->data
[i
];
1098 printf("\t%s\n", arg
->toChars());
1101 printf(" fargs:\n");
1102 for (int i
= 0; i
< fargs
->dim
; i
++)
1103 { Expression
*arg
= (Expression
*)fargs
->data
[i
];
1104 printf("\t%s %s\n", arg
->type
->toChars(), arg
->toChars());
1105 //printf("\tty = %d\n", arg->type->ty);
1109 for (TemplateDeclaration
*td
= this; td
; td
= td
->overnext
)
1113 error("forward reference to template %s", td
->toChars());
1116 if (!td
->onemember
|| !td
->onemember
->toAlias()->isFuncDeclaration())
1118 error("is not a function template");
1125 m
= td
->deduceFunctionTemplateMatch(loc
, targsi
, ethis
, fargs
, &dedargs
);
1126 //printf("deduceFunctionTemplateMatch = %d\n", m);
1127 if (!m
) // if no match
1136 // Disambiguate by picking the most specialized TemplateDeclaration
1137 MATCH c1
= td
->leastAsSpecialized(td_best
);
1138 MATCH c2
= td_best
->leastAsSpecialized(td
);
1139 //printf("c1 = %d, c2 = %d\n", c1, c2);
1149 Lambig
: // td_best and td are ambiguous
1153 Ltd_best
: // td_best is the best match so far
1157 Ltd
: // td is the new best match
1159 assert((size_t)td
->scope
> 0x10000);
1162 tdargs
->setDim(dedargs
.dim
);
1163 memcpy(tdargs
->data
, dedargs
.data
, tdargs
->dim
* sizeof(void *));
1169 error(loc
, "does not match any function template declaration");
1174 error(loc
, "%s matches more than one function template declaration, %s and %s",
1175 toChars(), td_best
->toChars(), td_ambig
->toChars());
1178 /* The best match is td_best with arguments tdargs.
1179 * Now instantiate the template.
1181 assert((size_t)td_best
->scope
> 0x10000);
1182 ti
= new TemplateInstance(loc
, td_best
, tdargs
);
1184 fd
= ti
->toAlias()->isFuncDeclaration();
1195 Objects
*args
= targsi
;
1197 { for (int i
= 0; i
< args
->dim
; i
++)
1200 bufa
.writeByte(',');
1201 Object
*oarg
= (Object
*)args
->data
[i
];
1202 ObjectToCBuffer(&bufa
, &hgs
, oarg
);
1207 argExpTypesToCBuffer(&buf
, fargs
, &hgs
);
1209 error(loc
, "cannot deduce template function from argument types !(%s)(%s)",
1210 bufa
.toChars(), buf
.toChars());
1215 void TemplateDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1217 #if 0 // Should handle template functions
1218 if (onemember
&& onemember
->isFuncDeclaration())
1219 buf
->writestring("foo ");
1221 buf
->writestring(kind());
1222 buf
->writeByte(' ');
1223 buf
->writestring(ident
->toChars());
1224 buf
->writeByte('(');
1225 for (int i
= 0; i
< parameters
->dim
; i
++)
1227 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1229 tp
= (TemplateParameter
*)origParameters
->data
[i
];
1231 buf
->writeByte(',');
1232 tp
->toCBuffer(buf
, hgs
);
1234 buf
->writeByte(')');
1240 buf
->writebyte('{');
1242 for (int i
= 0; i
< members
->dim
; i
++)
1244 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1245 s
->toCBuffer(buf
, hgs
);
1247 buf
->writebyte('}');
1254 char *TemplateDeclaration::toChars()
1258 memset(&hgs
, 0, sizeof(hgs
));
1259 buf
.writestring(ident
->toChars());
1261 for (int i
= 0; i
< parameters
->dim
; i
++)
1263 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1266 tp
->toCBuffer(&buf
, &hgs
);
1270 return (char *)buf
.extractData();
1273 /* ======================== Type ============================================ */
1276 * Given an identifier, figure out which TemplateParameter it is.
1277 * Return -1 if not found.
1280 int templateIdentifierLookup(Identifier
*id
, TemplateParameters
*parameters
)
1282 for (size_t i
= 0; i
< parameters
->dim
; i
++)
1283 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1285 if (tp
->ident
->equals(id
))
1291 int templateParameterLookup(Type
*tparam
, TemplateParameters
*parameters
)
1293 assert(tparam
->ty
== Tident
);
1294 TypeIdentifier
*tident
= (TypeIdentifier
*)tparam
;
1295 //printf("\ttident = '%s'\n", tident->toChars());
1296 if (tident
->idents
.dim
== 0)
1298 return templateIdentifierLookup(tident
->ident
, parameters
);
1303 /* These form the heart of template argument deduction.
1304 * Given 'this' being the type argument to the template instance,
1305 * it is matched against the template declaration parameter specialization
1306 * 'tparam' to determine the type to be used for the parameter.
1308 * template Foo(T:T*) // template declaration
1309 * Foo!(int*) // template instantiation
1313 * parameters = [ T:T* ] // Array of TemplateParameter's
1315 * dedtypes = [ int ] // Array of Expression/Type's
1318 MATCH
Type::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
,
1321 //printf("Type::deduceType()\n");
1322 //printf("\tthis = %d, ", ty); print();
1323 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1327 if (tparam
->ty
== Tmaybe
)
1328 tparam
= tparam
->nextOf();
1329 if (this->ty
== Tmaybe
)
1330 return nextOf()->deduceType(sc
, tparam
, parameters
, dedtypes
);
1335 if (tparam
->ty
== Tident
)
1337 // Determine which parameter tparam is
1338 int i
= templateParameterLookup(tparam
, parameters
);
1343 /* BUG: what if tparam is a template instance, that
1344 * has as an argument another Tident?
1346 tparam
= tparam
->semantic(0, sc
);
1347 assert(tparam
->ty
!= Tident
);
1348 return deduceType(sc
, tparam
, parameters
, dedtypes
);
1351 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1353 // Found the corresponding parameter tp
1354 if (!tp
->isTemplateTypeParameter())
1356 Type
*at
= (Type
*)dedtypes
->data
[i
];
1359 if (tparam
->isMutable())
1360 { // foo(U:U) T => T
1361 // foo(U:U) const(T) => const(T)
1362 // foo(U:U) invariant(T) => invariant(T)
1363 dedtypes
->data
[i
] = (void *)this;
1366 else if (mod
== tparam
->mod
)
1367 { // foo(U:const(U)) const(T) => T
1368 // foo(U:invariant(U)) invariant(T) => T
1369 dedtypes
->data
[i
] = (void *)mutableOf();
1372 else if (tparam
->isConst())
1373 { // foo(U:const(U)) T => T
1374 // foo(U:const(U)) invariant(T) => T
1375 dedtypes
->data
[i
] = (void *)mutableOf();
1379 { // foo(U:invariant(U)) T => nomatch
1380 // foo(U:invariant(U)) const(T) => nomatch
1386 else if (ty
== Tclass
&& at
->ty
== Tclass
)
1388 return implicitConvTo(at
);
1390 else if (ty
== Tsarray
&& at
->ty
== Tarray
&&
1391 nextOf()->implicitConvTo(at
->nextOf()) >= MATCHconst
)
1399 if (ty
!= tparam
->ty
)
1403 return nextOf()->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1409 return MATCHnomatch
;
1415 MATCH
TypeSArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
,
1419 printf("TypeSArray::deduceType()\n");
1420 printf("\tthis = %d, ", ty
); print();
1421 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1424 // Extra check that array dimensions must match
1427 if (tparam
->ty
== Tsarray
)
1429 TypeSArray
*tp
= (TypeSArray
*)tparam
;
1431 if (tp
->dim
->op
== TOKvar
&&
1432 ((VarExp
*)tp
->dim
)->var
->storage_class
& STCtemplateparameter
)
1433 { int i
= templateIdentifierLookup(((VarExp
*)tp
->dim
)->var
->ident
, parameters
);
1434 // This code matches code in TypeInstance::deduceType()
1437 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1438 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1441 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
1444 if (!dim
->equals(e
))
1448 { Type
*vt
= tvp
->valType
->semantic(0, sc
);
1449 MATCH m
= (MATCH
)dim
->implicitConvTo(vt
);
1452 dedtypes
->data
[i
] = dim
;
1455 else if (dim
->toInteger() != tp
->dim
->toInteger())
1456 return MATCHnomatch
;
1458 else if (tparam
->ty
== Taarray
)
1460 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1461 if (tp
->index
->ty
== Tident
)
1462 { TypeIdentifier
*tident
= (TypeIdentifier
*)tp
->index
;
1464 if (tident
->idents
.dim
== 0)
1465 { Identifier
*id
= tident
->ident
;
1467 for (size_t i
= 0; i
< parameters
->dim
; i
++)
1469 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1471 if (tp
->ident
->equals(id
))
1472 { // Found the corresponding template parameter
1473 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1474 if (!tvp
|| !tvp
->valType
->isintegral())
1477 if (dedtypes
->data
[i
])
1479 if (!dim
->equals((Object
*)dedtypes
->data
[i
]))
1483 { dedtypes
->data
[i
] = (void *)dim
;
1485 return next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1491 else if (tparam
->ty
== Tarray
)
1494 m
= next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1495 if (m
== MATCHexact
)
1500 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1503 return MATCHnomatch
;
1506 MATCH
TypeAArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1509 printf("TypeAArray::deduceType()\n");
1510 printf("\tthis = %d, ", ty
); print();
1511 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1514 // Extra check that index type must match
1515 if (tparam
&& tparam
->ty
== Taarray
)
1517 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1518 if (!index
->deduceType(sc
, tp
->index
, parameters
, dedtypes
))
1520 return MATCHnomatch
;
1523 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1526 MATCH
TypeFunction::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1528 //printf("TypeFunction::deduceType()\n");
1529 //printf("\tthis = %d, ", ty); print();
1530 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1532 // Extra check that function characteristics must match
1533 if (tparam
&& tparam
->ty
== Tfunction
)
1535 TypeFunction
*tp
= (TypeFunction
*)tparam
;
1536 if (varargs
!= tp
->varargs
||
1537 linkage
!= tp
->linkage
)
1538 return MATCHnomatch
;
1540 size_t nfargs
= Argument::dim(this->parameters
);
1541 size_t nfparams
= Argument::dim(tp
->parameters
);
1543 /* See if tuple match
1545 if (nfparams
> 0 && nfargs
>= nfparams
- 1)
1547 /* See if 'A' of the template parameter matches 'A'
1548 * of the type of the last function parameter.
1550 Argument
*fparam
= (Argument
*)tp
->parameters
->data
[nfparams
- 1];
1551 if (fparam
->type
->ty
!= Tident
)
1553 TypeIdentifier
*tid
= (TypeIdentifier
*)fparam
->type
;
1554 if (tid
->idents
.dim
)
1557 /* Look through parameters to find tuple matching tid->ident
1561 { if (tupi
== parameters
->dim
)
1563 TemplateParameter
*t
= (TemplateParameter
*)parameters
->data
[tupi
];
1564 TemplateTupleParameter
*tup
= t
->isTemplateTupleParameter();
1565 if (tup
&& tup
->ident
->equals(tid
->ident
))
1569 /* The types of the function arguments [nfparams - 1 .. nfargs]
1570 * now form the tuple argument.
1572 int tuple_dim
= nfargs
- (nfparams
- 1);
1574 /* See if existing tuple, and whether it matches or not
1576 Object
*o
= (Object
*)dedtypes
->data
[tupi
];
1578 { // Existing deduced argument must be a tuple, and must match
1579 Tuple
*t
= isTuple(o
);
1580 if (!t
|| t
->objects
.dim
!= tuple_dim
)
1581 return MATCHnomatch
;
1582 for (size_t i
= 0; i
< tuple_dim
; i
++)
1583 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1584 if (!arg
->type
->equals((Object
*)t
->objects
.data
[i
]))
1585 return MATCHnomatch
;
1589 { // Create new tuple
1590 Tuple
*t
= new Tuple();
1591 t
->objects
.setDim(tuple_dim
);
1592 for (size_t i
= 0; i
< tuple_dim
; i
++)
1593 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1594 t
->objects
.data
[i
] = (void *)arg
->type
;
1596 dedtypes
->data
[tupi
] = (void *)t
;
1598 nfparams
--; // don't consider the last parameter for type deduction
1603 if (nfargs
!= nfparams
)
1604 return MATCHnomatch
;
1606 for (size_t i
= 0; i
< nfparams
; i
++)
1608 Argument
*a
= Argument::getNth(this->parameters
, i
);
1609 Argument
*ap
= Argument::getNth(tp
->parameters
, i
);
1610 if (a
->storageClass
!= ap
->storageClass
||
1611 !a
->type
->deduceType(sc
, ap
->type
, parameters
, dedtypes
))
1612 return MATCHnomatch
;
1615 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1618 MATCH
TypeIdentifier::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1621 if (tparam
&& tparam
->ty
== Tident
)
1623 TypeIdentifier
*tp
= (TypeIdentifier
*)tparam
;
1625 for (int i
= 0; i
< idents
.dim
; i
++)
1627 Identifier
*id1
= (Identifier
*)idents
.data
[i
];
1628 Identifier
*id2
= (Identifier
*)tp
->idents
.data
[i
];
1630 if (!id1
->equals(id2
))
1631 return MATCHnomatch
;
1634 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1637 MATCH
TypeInstance::deduceType(Scope
*sc
,
1638 Type
*tparam
, TemplateParameters
*parameters
,
1641 //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
1642 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1645 if (tparam
&& tparam
->ty
== Tinstance
)
1647 TypeInstance
*tp
= (TypeInstance
*)tparam
;
1649 //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
1650 //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
1651 if (!tp
->tempinst
->tempdecl
)
1652 { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
1653 if (!tp
->tempinst
->name
->equals(tempinst
->name
))
1656 * template Foo(T : sa!(T), alias sa)
1658 int i
= templateIdentifierLookup(tp
->tempinst
->name
, parameters
);
1660 { /* Didn't find it as a parameter identifier. Try looking
1661 * it up and seeing if is an alias. See Bugzilla 1454
1663 Dsymbol
*s
= tempinst
->tempdecl
->scope
->search(0, tp
->tempinst
->name
, NULL
);
1667 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
1668 if (td
&& td
== tempinst
->tempdecl
)
1673 TemplateParameter
*tpx
= (TemplateParameter
*)parameters
->data
[i
];
1674 // This logic duplicates tpx->matchArg()
1675 TemplateAliasParameter
*ta
= tpx
->isTemplateAliasParameter();
1678 Dsymbol
*sa
= tempinst
->tempdecl
;
1681 if (ta
->specAlias
&& sa
!= ta
->specAlias
)
1683 if (dedtypes
->data
[i
])
1684 { // Must match already deduced symbol
1685 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
1690 dedtypes
->data
[i
] = sa
;
1693 else if (tempinst
->tempdecl
!= tp
->tempinst
->tempdecl
)
1697 if (tempinst
->tiargs
->dim
!= tp
->tempinst
->tiargs
->dim
)
1700 for (int i
= 0; i
< tempinst
->tiargs
->dim
; i
++)
1702 //printf("\ttest: tempinst->tiargs[%d]\n", i);
1704 Object
*o1
= (Object
*)tempinst
->tiargs
->data
[i
];
1705 Object
*o2
= (Object
*)tp
->tempinst
->tiargs
->data
[i
];
1707 Type
*t1
= isType(o1
);
1708 Type
*t2
= isType(o2
);
1710 Expression
*e1
= isExpression(o1
);
1711 Expression
*e2
= isExpression(o2
);
1714 if (t1
) printf("t1 = %s\n", t1
->toChars());
1715 if (t2
) printf("t2 = %s\n", t2
->toChars());
1716 if (e1
) printf("e1 = %s\n", e1
->toChars());
1717 if (e2
) printf("e2 = %s\n", e2
->toChars());
1722 if (!t1
->deduceType(sc
, t2
, parameters
, dedtypes
))
1727 if (!e1
->equals(e2
))
1728 { if (e2
->op
== TOKvar
)
1731 * (T:Number!(e2), int e2)
1733 j
= templateIdentifierLookup(((VarExp
*)e2
)->var
->ident
, parameters
);
1739 else if (e1
&& t2
&& t2
->ty
== Tident
)
1741 j
= templateParameterLookup(t2
, parameters
);
1745 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[j
];
1746 // BUG: use tp->matchArg() instead of the following
1747 TemplateValueParameter
*tv
= tp
->isTemplateValueParameter();
1750 Expression
*e
= (Expression
*)dedtypes
->data
[j
];
1757 { Type
*vt
= tv
->valType
->semantic(0, sc
);
1758 MATCH m
= (MATCH
)e1
->implicitConvTo(vt
);
1761 dedtypes
->data
[j
] = e1
;
1764 // BUG: Need to handle alias and tuple parameters
1769 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1772 return MATCHnomatch
;
1775 MATCH
TypeStruct::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1777 //printf("TypeStruct::deduceType()\n");
1778 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
1779 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1781 /* If this struct is a template struct, and we're matching
1782 * it against a template instance, convert the struct type
1783 * to a template instance, too, and try again.
1785 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1787 if (tparam
&& tparam
->ty
== Tinstance
)
1789 if (ti
&& ti
->toAlias() == sym
)
1791 TypeInstance
*t
= new TypeInstance(0, ti
);
1792 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1795 /* Match things like:
1798 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1799 if (tpi
->idents
.dim
)
1800 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1801 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1803 Type
*tparent
= sym
->parent
->getType();
1806 /* Slice off the .foo in S!(T).foo
1809 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1818 if (tparam
&& tparam
->ty
== Tstruct
)
1820 TypeStruct
*tp
= (TypeStruct
*)tparam
;
1823 return MATCHnomatch
;
1825 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1828 MATCH
TypeEnum::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1831 if (tparam
&& tparam
->ty
== Tenum
)
1833 TypeEnum
*tp
= (TypeEnum
*)tparam
;
1836 return MATCHnomatch
;
1838 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1841 MATCH
TypeTypedef::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1844 if (tparam
&& tparam
->ty
== Ttypedef
)
1846 TypeTypedef
*tp
= (TypeTypedef
*)tparam
;
1849 return MATCHnomatch
;
1851 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1854 MATCH
TypeClass::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1856 //printf("TypeClass::deduceType(this = %s)\n", toChars());
1858 /* If this class is a template class, and we're matching
1859 * it against a template instance, convert the class type
1860 * to a template instance, too, and try again.
1862 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1864 if (tparam
&& tparam
->ty
== Tinstance
)
1866 if (ti
&& ti
->toAlias() == sym
)
1868 TypeInstance
*t
= new TypeInstance(0, ti
);
1869 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1872 /* Match things like:
1875 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1876 if (tpi
->idents
.dim
)
1877 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1878 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1880 Type
*tparent
= sym
->parent
->getType();
1883 /* Slice off the .foo in S!(T).foo
1886 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1895 if (tparam
&& tparam
->ty
== Tclass
)
1897 TypeClass
*tp
= (TypeClass
*)tparam
;
1899 //printf("\t%d\n", (MATCH) implicitConvTo(tp));
1900 return implicitConvTo(tp
);
1902 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1905 /* ======================== TemplateParameter =============================== */
1907 TemplateParameter::TemplateParameter(Loc loc
, Identifier
*ident
)
1910 this->ident
= ident
;
1911 this->sparam
= NULL
;
1914 TemplateTypeParameter
*TemplateParameter::isTemplateTypeParameter()
1919 TemplateValueParameter
*TemplateParameter::isTemplateValueParameter()
1924 TemplateAliasParameter
*TemplateParameter::isTemplateAliasParameter()
1929 TemplateTupleParameter
*TemplateParameter::isTemplateTupleParameter()
1935 TemplateThisParameter
*TemplateParameter::isTemplateThisParameter()
1941 /* ======================== TemplateTypeParameter =========================== */
1945 TemplateTypeParameter::TemplateTypeParameter(Loc loc
, Identifier
*ident
, Type
*specType
,
1947 : TemplateParameter(loc
, ident
)
1949 this->ident
= ident
;
1950 this->specType
= specType
;
1951 this->defaultType
= defaultType
;
1954 TemplateTypeParameter
*TemplateTypeParameter::isTemplateTypeParameter()
1959 TemplateParameter
*TemplateTypeParameter::syntaxCopy()
1961 TemplateTypeParameter
*tp
= new TemplateTypeParameter(loc
, ident
, specType
, defaultType
);
1963 tp
->specType
= specType
->syntaxCopy();
1965 tp
->defaultType
= defaultType
->syntaxCopy();
1969 void TemplateTypeParameter::declareParameter(Scope
*sc
)
1971 //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
1972 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
1973 sparam
= new AliasDeclaration(loc
, ident
, ti
);
1974 if (!sc
->insert(sparam
))
1975 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
1978 void TemplateTypeParameter::semantic(Scope
*sc
)
1980 //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
1983 specType
= specType
->semantic(loc
, sc
);
1985 #if 0 // Don't do semantic() until instantiation
1988 defaultType
= defaultType
->semantic(loc
, sc
);
1993 /****************************************
1994 * Determine if two TemplateParameters are the same
1995 * as far as TemplateDeclaration overloading goes.
2001 int TemplateTypeParameter::overloadMatch(TemplateParameter
*tp
)
2003 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
2007 if (specType
!= ttp
->specType
)
2010 if (specType
&& !specType
->equals(ttp
->specType
))
2020 /*******************************************
2021 * Match to a particular TemplateParameter.
2024 * tiargs[] actual arguments to template instance
2025 * parameters[] template parameters
2026 * dedtypes[] deduced arguments to template instance
2027 * *psparam set to symbol declared and initialized to dedtypes[i]
2028 * flags 1: don't do 'toHeadMutable()'
2031 MATCH
TemplateTypeParameter::matchArg(Scope
*sc
, Objects
*tiargs
,
2032 int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2033 Declaration
**psparam
, int flags
)
2035 //printf("TemplateTypeParameter::matchArg()\n");
2038 MATCH m
= MATCHexact
;
2041 if (i
< tiargs
->dim
)
2042 oarg
= (Object
*)tiargs
->data
[i
];
2044 { // Get default argument instead
2045 oarg
= defaultArg(loc
, sc
);
2047 { assert(i
< dedtypes
->dim
);
2048 // It might have already been deduced
2049 oarg
= (Object
*)dedtypes
->data
[i
];
2054 flags
|= 1; // already deduced, so don't to toHeadMutable()
2061 //printf("test1 %s %p %p %p\n", oarg->toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
2064 //printf("ta is %s\n", ta->toChars());
2066 t
= (Type
*)dedtypes
->data
[i
];
2070 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
2071 MATCH m2
= ta
->deduceType(sc
, specType
, parameters
, dedtypes
);
2072 if (m2
== MATCHnomatch
)
2073 { //printf("\tfailed deduceType\n");
2079 t
= (Type
*)dedtypes
->data
[i
];
2083 // So that matches with specializations are better
2087 * template Foo(T), Foo!(const int), => ta == int
2089 // if (!(flags & 1))
2090 // ta = ta->toHeadMutable();
2093 { // Must match already deduced type
2097 { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
2105 dedtypes
->data
[i
] = ta
;
2108 *psparam
= new AliasDeclaration(loc
, ident
, t
);
2109 //printf("\tm = %d\n", m);
2114 //printf("\tm = %d\n", MATCHnomatch);
2115 return MATCHnomatch
;
2119 void TemplateTypeParameter::print(Object
*oarg
, Object
*oded
)
2121 fprintf(stderr
, " %s\n", ident
->toChars());
2123 Type
*t
= isType(oarg
);
2124 Type
*ta
= isType(oded
);
2129 fprintf(stderr
, "\tSpecialization: %s\n", specType
->toChars());
2131 fprintf(stderr
, "\tDefault: %s\n", defaultType
->toChars());
2132 fprintf(stderr
, "\tArgument: %s\n", t
? t
->toChars() : "NULL");
2133 fprintf(stderr
, "\tDeduced Type: %s\n", ta
->toChars());
2137 void TemplateTypeParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2139 buf
->writestring(ident
->toChars());
2142 buf
->writestring(" : ");
2143 specType
->toCBuffer(buf
, NULL
, hgs
);
2147 buf
->writestring(" = ");
2148 defaultType
->toCBuffer(buf
, NULL
, hgs
);
2153 void *TemplateTypeParameter::dummyArg()
2159 { // Use this for alias-parameter's too (?)
2160 t
= new TypeIdentifier(loc
, ident
);
2166 Object
*TemplateTypeParameter::specialization()
2172 Object
*TemplateTypeParameter::defaultArg(Loc loc
, Scope
*sc
)
2179 t
= t
->syntaxCopy();
2180 t
= t
->semantic(loc
, sc
);
2185 /* ======================== TemplateThisParameter =========================== */
2190 TemplateThisParameter::TemplateThisParameter(Loc loc
, Identifier
*ident
,
2193 : TemplateTypeParameter(loc
, ident
, specType
, defaultType
)
2197 TemplateThisParameter
*TemplateThisParameter::isTemplateThisParameter()
2202 TemplateParameter
*TemplateThisParameter::syntaxCopy()
2204 TemplateThisParameter
*tp
= new TemplateThisParameter(loc
, ident
, specType
, defaultType
);
2206 tp
->specType
= specType
->syntaxCopy();
2208 tp
->defaultType
= defaultType
->syntaxCopy();
2212 void TemplateThisParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2214 buf
->writestring("this ");
2215 TemplateTypeParameter::toCBuffer(buf
, hgs
);
2219 /* ======================== TemplateAliasParameter ========================== */
2223 Dsymbol
*TemplateAliasParameter::sdummy
= NULL
;
2225 TemplateAliasParameter::TemplateAliasParameter(Loc loc
, Identifier
*ident
, Type
*specAliasT
, Type
*defaultAlias
)
2226 : TemplateParameter(loc
, ident
)
2228 this->ident
= ident
;
2229 this->specAliasT
= specAliasT
;
2230 this->defaultAlias
= defaultAlias
;
2232 this->specAlias
= NULL
;
2235 TemplateAliasParameter
*TemplateAliasParameter::isTemplateAliasParameter()
2240 TemplateParameter
*TemplateAliasParameter::syntaxCopy()
2242 TemplateAliasParameter
*tp
= new TemplateAliasParameter(loc
, ident
, specAliasT
, defaultAlias
);
2244 tp
->specAliasT
= specAliasT
->syntaxCopy();
2246 tp
->defaultAlias
= defaultAlias
->syntaxCopy();
2250 void TemplateAliasParameter::declareParameter(Scope
*sc
)
2252 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2253 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2254 if (!sc
->insert(sparam
))
2255 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2258 void TemplateAliasParameter::semantic(Scope
*sc
)
2262 specAlias
= specAliasT
->toDsymbol(sc
);
2264 error("%s is not a symbol", specAliasT
->toChars());
2266 #if 0 // Don't do semantic() until instantiation
2268 defaultAlias
= defaultAlias
->semantic(loc
, sc
);
2272 int TemplateAliasParameter::overloadMatch(TemplateParameter
*tp
)
2274 TemplateAliasParameter
*tap
= tp
->isTemplateAliasParameter();
2278 if (specAlias
!= tap
->specAlias
)
2288 MATCH
TemplateAliasParameter::matchArg(Scope
*sc
,
2289 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2290 Declaration
**psparam
, int flags
)
2296 //printf("TemplateAliasParameter::matchArg()\n");
2298 if (i
< tiargs
->dim
)
2299 oarg
= (Object
*)tiargs
->data
[i
];
2301 { // Get default argument instead
2302 oarg
= defaultArg(loc
, sc
);
2304 { assert(i
< dedtypes
->dim
);
2305 // It might have already been deduced
2306 oarg
= (Object
*)dedtypes
->data
[i
];
2312 sa
= getDsymbol(oarg
);
2318 if (!sa
|| sa
== sdummy
)
2320 if (sa
!= specAlias
)
2323 else if (dedtypes
->data
[i
])
2324 { // Must match already deduced symbol
2325 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
2330 dedtypes
->data
[i
] = sa
;
2332 *psparam
= new AliasDeclaration(loc
, ident
, sa
);
2337 return MATCHnomatch
;
2341 void TemplateAliasParameter::print(Object
*oarg
, Object
*oded
)
2343 fprintf(stderr
, " %s\n", ident
->toChars());
2345 Dsymbol
*sa
= isDsymbol(oded
);
2348 fprintf(stderr
, "\tArgument alias: %s\n", sa
->toChars());
2351 void TemplateAliasParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2353 buf
->writestring("alias ");
2354 buf
->writestring(ident
->toChars());
2357 buf
->writestring(" : ");
2358 specAliasT
->toCBuffer(buf
, NULL
, hgs
);
2362 buf
->writestring(" = ");
2363 defaultAlias
->toCBuffer(buf
, NULL
, hgs
);
2368 void *TemplateAliasParameter::dummyArg()
2375 sdummy
= new Dsymbol();
2382 Object
*TemplateAliasParameter::specialization()
2388 Object
*TemplateAliasParameter::defaultArg(Loc loc
, Scope
*sc
)
2394 s
= defaultAlias
->toDsymbol(sc
);
2396 error("%s is not a symbol", defaultAlias
->toChars());
2401 /* ======================== TemplateValueParameter ========================== */
2405 Expression
*TemplateValueParameter::edummy
= NULL
;
2407 TemplateValueParameter::TemplateValueParameter(Loc loc
, Identifier
*ident
, Type
*valType
,
2408 Expression
*specValue
, Expression
*defaultValue
)
2409 : TemplateParameter(loc
, ident
)
2411 this->ident
= ident
;
2412 this->valType
= valType
;
2413 this->specValue
= specValue
;
2414 this->defaultValue
= defaultValue
;
2417 TemplateValueParameter
*TemplateValueParameter::isTemplateValueParameter()
2422 TemplateParameter
*TemplateValueParameter::syntaxCopy()
2424 TemplateValueParameter
*tp
=
2425 new TemplateValueParameter(loc
, ident
, valType
, specValue
, defaultValue
);
2426 tp
->valType
= valType
->syntaxCopy();
2428 tp
->specValue
= specValue
->syntaxCopy();
2430 tp
->defaultValue
= defaultValue
->syntaxCopy();
2434 void TemplateValueParameter::declareParameter(Scope
*sc
)
2436 VarDeclaration
*v
= new VarDeclaration(loc
, valType
, ident
, NULL
);
2437 v
->storage_class
= STCtemplateparameter
;
2439 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2443 void TemplateValueParameter::semantic(Scope
*sc
)
2445 sparam
->semantic(sc
);
2446 valType
= valType
->semantic(loc
, sc
);
2447 if (!(valType
->isintegral() || valType
->isfloating() || valType
->isString()) &&
2448 valType
->ty
!= Tident
)
2449 error(loc
, "arithmetic/string type expected for value-parameter, not %s", valType
->toChars());
2452 { Expression
*e
= specValue
;
2454 e
= e
->semantic(sc
);
2455 e
= e
->implicitCastTo(sc
, valType
);
2456 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2457 if (e
->op
== TOKint64
|| e
->op
== TOKfloat64
||
2458 e
->op
== TOKcomplex80
|| e
->op
== TOKnull
|| e
->op
== TOKstring
)
2463 #if 0 // defer semantic analysis to arg match
2465 { Expression
*e
= defaultValue
;
2467 e
= e
->semantic(sc
);
2468 e
= e
->implicitCastTo(sc
, valType
);
2469 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2470 if (e
->op
== TOKint64
)
2477 int TemplateValueParameter::overloadMatch(TemplateParameter
*tp
)
2479 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
2483 if (valType
!= tvp
->valType
)
2486 if (valType
&& !valType
->equals(tvp
->valType
))
2489 if (specValue
!= tvp
->specValue
)
2500 MATCH
TemplateValueParameter::matchArg(Scope
*sc
,
2501 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2502 Declaration
**psparam
, int flags
)
2504 //printf("TemplateValueParameter::matchArg()\n");
2507 Declaration
*sparam
;
2508 MATCH m
= MATCHexact
;
2512 if (i
< tiargs
->dim
)
2513 oarg
= (Object
*)tiargs
->data
[i
];
2515 { // Get default argument instead
2516 oarg
= defaultArg(loc
, sc
);
2518 { assert(i
< dedtypes
->dim
);
2519 // It might have already been deduced
2520 oarg
= (Object
*)dedtypes
->data
[i
];
2526 ei
= isExpression(oarg
);
2532 if (ei
&& ei
->op
== TOKvar
)
2533 { // Resolve const variables that we had skipped earlier
2534 ei
= ei
->optimize(WANTvalue
| WANTinterpret
);
2539 if (!ei
|| ei
== edummy
)
2542 Expression
*e
= specValue
;
2544 e
= e
->semantic(sc
);
2545 e
= e
->implicitCastTo(sc
, valType
);
2546 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2547 //e->type = e->type->toHeadMutable();
2549 ei
= ei
->syntaxCopy();
2550 ei
= ei
->semantic(sc
);
2551 ei
= ei
->optimize(WANTvalue
| WANTinterpret
);
2552 //ei->type = ei->type->toHeadMutable();
2553 //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
2554 //printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
2558 else if (dedtypes
->data
[i
])
2559 { // Must match already deduced value
2560 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
2562 if (!ei
|| !ei
->equals(e
))
2566 //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
2567 vt
= valType
->semantic(0, sc
);
2568 //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
2569 //printf("vt = %s\n", vt->toChars());
2572 //ei->type = ei->type->toHeadMutable();
2573 m
= (MATCH
)ei
->implicitConvTo(vt
);
2574 //printf("m: %d\n", m);
2578 dedtypes
->data
[i
] = ei
;
2580 init
= new ExpInitializer(loc
, ei
);
2581 sparam
= new VarDeclaration(loc
, vt
, ident
, init
);
2582 sparam
->storage_class
= STCmanifest
;
2587 //printf("\tno match\n");
2589 return MATCHnomatch
;
2593 void TemplateValueParameter::print(Object
*oarg
, Object
*oded
)
2595 fprintf(stderr
, " %s\n", ident
->toChars());
2597 Expression
*ea
= isExpression(oded
);
2600 fprintf(stderr
, "\tSpecialization: %s\n", specValue
->toChars());
2601 fprintf(stderr
, "\tArgument Value: %s\n", ea
? ea
->toChars() : "NULL");
2605 void TemplateValueParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2607 valType
->toCBuffer(buf
, ident
, hgs
);
2610 buf
->writestring(" : ");
2611 specValue
->toCBuffer(buf
, hgs
);
2615 buf
->writestring(" = ");
2616 defaultValue
->toCBuffer(buf
, hgs
);
2621 void *TemplateValueParameter::dummyArg()
2627 // Create a dummy value
2629 edummy
= valType
->defaultInit();
2636 Object
*TemplateValueParameter::specialization()
2642 Object
*TemplateValueParameter::defaultArg(Loc loc
, Scope
*sc
)
2644 Expression
*e
= defaultValue
;
2647 e
= e
->syntaxCopy();
2648 e
= e
->semantic(sc
);
2650 if (e
->op
== TOKdefault
)
2651 { DefaultInitExp
*de
= (DefaultInitExp
*)e
;
2652 e
= de
->resolve(loc
, sc
);
2659 /* ======================== TemplateTupleParameter ========================== */
2661 // variadic-parameter
2663 TemplateTupleParameter::TemplateTupleParameter(Loc loc
, Identifier
*ident
)
2664 : TemplateParameter(loc
, ident
)
2666 this->ident
= ident
;
2669 TemplateTupleParameter
*TemplateTupleParameter::isTemplateTupleParameter()
2674 TemplateParameter
*TemplateTupleParameter::syntaxCopy()
2676 TemplateTupleParameter
*tp
= new TemplateTupleParameter(loc
, ident
);
2680 void TemplateTupleParameter::declareParameter(Scope
*sc
)
2682 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2683 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2684 if (!sc
->insert(sparam
))
2685 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2688 void TemplateTupleParameter::semantic(Scope
*sc
)
2692 int TemplateTupleParameter::overloadMatch(TemplateParameter
*tp
)
2694 TemplateTupleParameter
*tvp
= tp
->isTemplateTupleParameter();
2705 MATCH
TemplateTupleParameter::matchArg(Scope
*sc
,
2706 Objects
*tiargs
, int i
, TemplateParameters
*parameters
,
2708 Declaration
**psparam
, int flags
)
2710 //printf("TemplateTupleParameter::matchArg()\n");
2712 /* The rest of the actual arguments (tiargs[]) form the match
2713 * for the variadic parameter.
2715 assert(i
+ 1 == dedtypes
->dim
); // must be the last one
2717 if (i
+ 1 == tiargs
->dim
&& isTuple((Object
*)tiargs
->data
[i
]))
2718 ovar
= isTuple((Object
*)tiargs
->data
[i
]);
2722 //printf("ovar = %p\n", ovar);
2723 if (i
< tiargs
->dim
)
2725 //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
2726 ovar
->objects
.setDim(tiargs
->dim
- i
);
2727 for (size_t j
= 0; j
< ovar
->objects
.dim
; j
++)
2728 ovar
->objects
.data
[j
] = tiargs
->data
[i
+ j
];
2731 *psparam
= new TupleDeclaration(loc
, ident
, &ovar
->objects
);
2732 dedtypes
->data
[i
] = (void *)ovar
;
2737 void TemplateTupleParameter::print(Object
*oarg
, Object
*oded
)
2739 printf(" %s... [", ident
->toChars());
2740 Tuple
*v
= isTuple(oded
);
2743 //printf("|%d| ", v->objects.dim);
2744 for (int i
= 0; i
< v
->objects
.dim
; i
++)
2749 Object
*o
= (Object
*)v
->objects
.data
[i
];
2751 Dsymbol
*sa
= isDsymbol(o
);
2753 printf("alias: %s", sa
->toChars());
2755 Type
*ta
= isType(o
);
2757 printf("type: %s", ta
->toChars());
2759 Expression
*ea
= isExpression(o
);
2761 printf("exp: %s", ea
->toChars());
2763 assert(!isTuple(o
)); // no nested Tuple arguments
2769 void TemplateTupleParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2771 buf
->writestring(ident
->toChars());
2772 buf
->writestring("...");
2776 void *TemplateTupleParameter::dummyArg()
2782 Object
*TemplateTupleParameter::specialization()
2788 Object
*TemplateTupleParameter::defaultArg(Loc loc
, Scope
*sc
)
2793 /* ======================== TemplateInstance ================================ */
2795 TemplateInstance::TemplateInstance(Loc loc
, Identifier
*ident
)
2796 : ScopeDsymbol(NULL
)
2799 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident
? ident
->toChars() : "null");
2803 this->tiargs
= NULL
;
2804 this->tempdecl
= NULL
;
2806 this->argsym
= NULL
;
2807 this->aliasdecl
= NULL
;
2808 this->semanticdone
= 0;
2809 this->withsym
= NULL
;
2812 this->objFileModule
= NULL
;
2814 this->havetempdecl
= 0;
2815 this->isnested
= NULL
;
2820 TemplateInstance::TemplateInstance(Loc loc
, TemplateDeclaration
*td
, Objects
*tiargs
)
2821 : ScopeDsymbol(NULL
)
2824 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td
->toChars());
2827 this->name
= td
->ident
;
2828 this->tiargs
= tiargs
;
2829 this->tempdecl
= td
;
2831 this->argsym
= NULL
;
2832 this->aliasdecl
= NULL
;
2833 this->semanticdone
= 0;
2834 this->withsym
= NULL
;
2837 this->objFileModule
= NULL
;
2839 this->havetempdecl
= 1;
2840 this->isnested
= NULL
;
2843 assert((size_t)tempdecl
->scope
> 0x10000);
2847 Objects
*TemplateInstance::arraySyntaxCopy(Objects
*objs
)
2851 { a
= new Objects();
2852 a
->setDim(objs
->dim
);
2853 for (size_t i
= 0; i
< objs
->dim
; i
++)
2855 Type
*ta
= isType((Object
*)objs
->data
[i
]);
2857 a
->data
[i
] = ta
->syntaxCopy();
2860 Expression
*ea
= isExpression((Object
*)objs
->data
[i
]);
2862 a
->data
[i
] = ea
->syntaxCopy();
2869 Dsymbol
*TemplateInstance::syntaxCopy(Dsymbol
*s
)
2871 TemplateInstance
*ti
;
2875 ti
= (TemplateInstance
*)s
;
2877 ti
= new TemplateInstance(loc
, name
);
2879 ti
->tiargs
= arraySyntaxCopy(tiargs
);
2881 ScopeDsymbol::syntaxCopy(ti
);
2887 #include "d-dmd-gcc.h"
2890 void TemplateInstance::semantic(Scope
*sc
)
2896 /* Trying to soldier on rarely generates useful messages
2904 printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
2908 fprintf(stderr, "ti '%s' (%p), belongs in '%s'\n", toChars(), this,
2909 sc->module->toPrettyChars());
2911 fprintf(stderr, " -- really '%s' (%p)\n", inst->toChars(), inst);
2913 fprintf(stderr, " -- doing semantic\n");
2917 if (inst
) // if semantic() was already run
2920 printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst
->toChars(), inst
);
2925 if (semanticdone
!= 0)
2927 error(loc
, "recursive template expansion");
2934 printf("\tdo semantic\n");
2938 assert((size_t)tempdecl
->scope
> 0x10000);
2940 tdtypes
.setDim(tempdecl
->parameters
->dim
);
2941 if (!tempdecl
->matchWithInstance(this, &tdtypes
, 2))
2943 error("incompatible arguments for template instantiation");
2950 // Run semantic on each argument, place results in tiargs[]
2953 tempdecl
= findTemplateDeclaration(sc
);
2955 tempdecl
= findBestMatch(sc
);
2956 if (!tempdecl
|| global
.errors
)
2958 //printf("error return %p, %d\n", tempdecl, global.errors);
2959 return; // error recovery
2965 /* See if there is an existing TemplateInstantiation that already
2966 * implements the typeargs. If so, just refer to that one instead.
2969 for (size_t i
= 0; i
< tempdecl
->instances
.dim
; i
++)
2971 TemplateInstance
*ti
= (TemplateInstance
*)tempdecl
->instances
.data
[i
];
2973 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i
, ti
, ti
->toChars());
2975 assert(tdtypes
.dim
== ti
->tdtypes
.dim
);
2977 // Nesting must match
2978 if (isnested
!= ti
->isnested
)
2981 if (isnested
&& sc
->parent
!= ti
->parent
)
2984 for (size_t j
= 0; j
< tdtypes
.dim
; j
++)
2985 { Object
*o1
= (Object
*)tdtypes
.data
[j
];
2986 Object
*o2
= (Object
*)ti
->tdtypes
.data
[j
];
2987 if (!match(o1
, o2
, tempdecl
, sc
))
2993 parent
= ti
->parent
;
2995 printf("\tit's a match with instance %p\n", inst
);
3003 /* So, we need to implement 'this' instance.
3006 printf("\timplement template instance '%s'\n", toChars());
3008 unsigned errorsave
= global
.errors
;
3010 int tempdecl_instance_idx
= tempdecl
->instances
.dim
;
3011 tempdecl
->instances
.push(this);
3012 parent
= tempdecl
->parent
;
3013 //printf("parent = '%s'\n", parent->kind());
3015 ident
= genIdent(); // need an identifier for name mangling purposes.
3021 //printf("parent = '%s'\n", parent->kind());
3023 // Add 'this' to the enclosing scope's members[] so the semantic routines
3024 // will get called on the instance members
3026 int dosemantic3
= 0;
3031 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3037 /* For "all" and "private" template modes, templates are always
3038 emitted. Problem: This picks up templates that aren't even
3039 needed in the current module. */
3041 if (d_gcc_force_templates())
3043 //fprintf(stderr, "\t0: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
3044 objFileModule
= d_gcc_get_output_module();
3045 a
= objFileModule
->members
;
3050 //if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3051 if (scx
&& scx
->scopesym
&& scx
->scopesym
->members
&& !scx
->scopesym
->isTemplateMixin())
3053 //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3054 a
= scx
->scopesym
->members
;
3057 Dsymbol
* p
= scx
->scopesym
;
3059 TemplateInstance
* i
;
3062 if ( (i
= p
->isTemplateInstance()) ) {
3063 if (i
->objFileModule
) {
3064 objFileModule
= i
->objFileModule
;
3067 } else if ( (m
= p
->isModule()) ) {
3068 objFileModule
= m
; // %% importedFrom ?
3073 // fprintf(stderr, "\t1: adding %s to module %s via %s %s\n", tempdecl->toChars(), objFileModule?objFileModule->toChars():"", sc->scopesym->kind(), sc->scopesym->toChars());
3078 { Module
*m
= sc
->module
->importedFrom
;
3079 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
3081 if (m
->semanticdone
>= 3)
3087 for (int i
= 0; 1; i
++)
3094 if (this == (Dsymbol
*)a
->data
[i
]) // if already in Array
3100 // Copy the syntax trees from the TemplateDeclaration
3101 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
3103 // Create our own scope for the template parameters
3104 Scope
*scope
= tempdecl
->scope
;
3107 error("forward reference to template declaration %s\n", tempdecl
->toChars());
3112 printf("\tcreate scope for template parameters '%s'\n", toChars());
3114 argsym
= new ScopeDsymbol();
3115 argsym
->parent
= scope
->parent
;
3116 scope
= scope
->push(argsym
);
3118 // Declare each template parameter as an alias for the argument type
3119 declareParameters(scope
);
3121 // Add members of template instance to template instance symbol table
3122 // parent = scope->scopesym;
3123 symtab
= new DsymbolTable();
3125 for (int i
= 0; i
< members
->dim
; i
++)
3127 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3129 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i
, s
->toChars(), s
, s
->kind(), this->toChars(), memnum
);
3131 memnum
|= s
->addMember(scope
, this, memnum
);
3134 printf("adding members done\n");
3137 /* See if there is only one member of template instance, and that
3138 * member has the same name as the template instance.
3139 * If so, this template instance becomes an alias for that member.
3141 //printf("members->dim = %d\n", members->dim);
3145 if (Dsymbol::oneMembers(members
, &s
) && s
)
3147 //printf("s->kind = '%s'\n", s->kind());
3149 //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
3150 if (s
->ident
&& s
->ident
->equals(tempdecl
->ident
))
3152 //printf("setting aliasdecl\n");
3153 aliasdecl
= new AliasDeclaration(loc
, s
->ident
, s
);
3158 // Do semantic() analysis on template instance members
3160 printf("\tdo semantic() on template instance members '%s'\n", toChars());
3163 sc2
= scope
->push(this);
3164 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
3165 sc2
->parent
= /*isnested ? sc->parent :*/ this;
3166 sc2
->fromDcode
= !tempdecl
->dltSource
;
3174 for (int i
= 0; i
< members
->dim
; i
++)
3176 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3177 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
3178 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
3180 // s->parent = sc->parent;
3181 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3183 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3184 sc2
->module
->runDeferredSemantic();
3189 __except (__ehfilter(GetExceptionInformation()))
3191 global
.gag
= 0; // ensure error message gets printed
3192 error("recursive expansion");
3198 /* If any of the instantiation members didn't get semantic() run
3199 * on them due to forward references, we cannot run semantic2()
3200 * or semantic3() yet.
3202 for (size_t i
= 0; i
< Module::deferred
.dim
; i
++)
3203 { Dsymbol
*sd
= (Dsymbol
*)Module::deferred
.data
[i
];
3205 if (sd
->parent
== this)
3206 goto Laftersemantic
;
3209 /* The problem is when to parse the initializer for a variable.
3210 * Perhaps VarDeclaration::semantic() should do it like it does
3211 * for initializers inside a function.
3213 // if (sc->parent->isFuncDeclaration())
3215 /* BUG 782: this has problems if the classes this depends on
3216 * are forward referenced. Find a way to defer semantic()
3221 if (sc
->func
|| dosemantic3
)
3231 // Give additional context info if error occurred during instantiation
3232 if (global
.errors
!= errorsave
)
3234 error("error instantiating");
3237 tempdecl
->instances
.remove(tempdecl_instance_idx
);
3241 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3246 void TemplateInstance::semanticTiargs(Scope
*sc
)
3248 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3249 semanticTiargs(loc
, sc
, tiargs
, 0);
3252 /**********************************
3254 * flags 1: replace const variables with their initializers
3257 void TemplateInstance::semanticTiargs(Loc loc
, Scope
*sc
, Objects
*tiargs
, int flags
)
3259 // Run semantic on each argument, place results in tiargs[]
3260 //printf("+TemplateInstance::semanticTiargs()\n");
3263 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3265 Object
*o
= (Object
*)tiargs
->data
[j
];
3266 Type
*ta
= isType(o
);
3267 Expression
*ea
= isExpression(o
);
3268 Dsymbol
*sa
= isDsymbol(o
);
3270 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
3273 //printf("type %s\n", ta->toChars());
3274 // It might really be an Expression or an Alias
3275 ta
->resolve(loc
, sc
, &ea
, &ta
, &sa
);
3278 ea
= ea
->semantic(sc
);
3279 /* This test is to skip substituting a const var with
3280 * its initializer. The problem is the initializer won't
3281 * match with an 'alias' parameter. Instead, do the
3282 * const substitution in TemplateValueParameter::matchArg().
3284 if (ea
->op
!= TOKvar
|| flags
& 1)
3285 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3286 tiargs
->data
[j
] = ea
;
3289 { tiargs
->data
[j
] = sa
;
3290 TupleDeclaration
*d
= sa
->toAlias()->isTupleDeclaration();
3293 size_t dim
= d
->objects
->dim
;
3295 tiargs
->insert(j
, d
->objects
);
3301 if (ta
->ty
== Ttuple
)
3303 TypeTuple
*tt
= (TypeTuple
*)ta
;
3304 size_t dim
= tt
->arguments
->dim
;
3307 { tiargs
->reserve(dim
);
3308 for (size_t i
= 0; i
< dim
; i
++)
3309 { Argument
*arg
= (Argument
*)tt
->arguments
->data
[i
];
3310 tiargs
->insert(j
+ i
, arg
->type
);
3316 tiargs
->data
[j
] = ta
;
3320 assert(global
.errors
);
3321 tiargs
->data
[j
] = Type::terror
;
3327 { assert(global
.errors
);
3328 ea
= new IntegerExp(0);
3331 ea
= ea
->semantic(sc
);
3332 if (ea
->op
!= TOKvar
|| flags
& 1)
3333 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3334 tiargs
->data
[j
] = ea
;
3335 if (ea
->op
== TOKtype
)
3336 tiargs
->data
[j
] = ea
->type
;
3345 //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
3348 printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
3349 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3351 Object
*o
= (Object
*)tiargs
->data
[j
];
3352 Type
*ta
= isType(o
);
3353 Expression
*ea
= isExpression(o
);
3354 Dsymbol
*sa
= isDsymbol(o
);
3355 Tuple
*va
= isTuple(o
);
3357 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j
, ta
, ea
, sa
, va
);
3362 /**********************************************
3363 * Find template declaration corresponding to template instance.
3366 TemplateDeclaration
*TemplateInstance::findTemplateDeclaration(Scope
*sc
)
3368 //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
3373 * figure out which TemplateDeclaration foo refers to.
3381 s
= sc
->search(loc
, id
, &scopesym
);
3383 { error("identifier '%s' is not defined", id
->toChars());
3387 printf("It's an instance of '%s' kind '%s'\n", s
->toChars(), s
->kind());
3389 printf("s->parent = '%s'\n", s
->parent
->toChars());
3391 withsym
= scopesym
->isWithScopeSymbol();
3393 /* We might have found an alias within a template when
3394 * we really want the template.
3396 TemplateInstance
*ti
;
3398 (ti
= s
->parent
->isTemplateInstance()) != NULL
)
3402 ti
->toAlias()->ident
== id
)
3406 /* This is so that one can refer to the enclosing
3407 * template, even if it has the same name as a member
3408 * of the template, if it has a !(arguments)
3410 tempdecl
= ti
->tempdecl
;
3411 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3412 tempdecl
= tempdecl
->overroot
; // then get the start
3419 /* It should be a TemplateDeclaration, not some other symbol
3421 tempdecl
= s
->isTemplateDeclaration();
3424 if (!s
->parent
&& global
.errors
)
3426 if (!s
->parent
&& s
->getType())
3427 { Dsymbol
*s2
= s
->getType()->toDsymbol(sc
);
3430 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3436 //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
3438 //assert(s->parent);
3439 TemplateInstance
*ti
= s
->parent
? s
->parent
->isTemplateInstance() : NULL
;
3442 ti
->toAlias()->ident
== id
)
3446 /* This is so that one can refer to the enclosing
3447 * template, even if it has the same name as a member
3448 * of the template, if it has a !(arguments)
3450 tempdecl
= ti
->tempdecl
;
3451 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3452 tempdecl
= tempdecl
->overroot
; // then get the start
3456 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3462 assert(tempdecl
->isTemplateDeclaration());
3466 TemplateDeclaration
*TemplateInstance::findBestMatch(Scope
*sc
)
3468 /* Since there can be multiple TemplateDeclaration's with the same
3469 * name, look for the best match.
3471 TemplateDeclaration
*td_ambig
= NULL
;
3472 TemplateDeclaration
*td_best
= NULL
;
3473 MATCH m_best
= MATCHnomatch
;
3477 printf("TemplateInstance::findBestMatch()\n");
3479 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
3483 //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
3485 // If more arguments than parameters,
3486 // then this is no match.
3487 if (td
->parameters
->dim
< tiargs
->dim
)
3489 if (!td
->isVariadic())
3493 dedtypes
.setDim(td
->parameters
->dim
);
3497 error("forward reference to template declaration %s", td
->toChars());
3500 m
= td
->matchWithInstance(this, &dedtypes
, 0);
3501 //printf("m = %d\n", m);
3502 if (!m
) // no match at all
3515 // Disambiguate by picking the most specialized TemplateDeclaration
3516 MATCH c1
= td
->leastAsSpecialized(td_best
);
3517 MATCH c2
= td_best
->leastAsSpecialized(td
);
3518 //printf("c1 = %d, c2 = %d\n", c1, c2);
3528 Lambig
: // td_best and td are ambiguous
3532 Ltd_best
: // td_best is the best match so far
3536 Ltd
: // td is the new best match
3540 tdtypes
.setDim(dedtypes
.dim
);
3541 memcpy(tdtypes
.data
, dedtypes
.data
, tdtypes
.dim
* sizeof(void *));
3547 error("%s does not match any template declaration", toChars());
3552 error("%s matches more than one template declaration, %s and %s",
3553 toChars(), td_best
->toChars(), td_ambig
->toChars());
3556 /* The best match is td_best
3561 /* Cast any value arguments to be same type as value parameter
3563 for (size_t i
= 0; i
< tiargs
->dim
; i
++)
3564 { Object
*o
= (Object
*)tiargs
->data
[i
];
3565 Expression
*ea
= isExpression(o
); // value argument
3566 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3568 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3572 ea
= ea
->castTo(tvp
->valType
);
3573 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3574 tiargs
->data
[i
] = (Object
*)ea
;
3580 printf("\tIt's a match with template declaration '%s'\n", tempdecl
->toChars());
3586 /*****************************************
3587 * Determines if a TemplateInstance will need a nested
3588 * generation of the TemplateDeclaration.
3591 int TemplateInstance::isNested(Objects
*args
)
3593 //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars());
3595 /* A nested instance happens when an argument references a local
3596 * symbol that is on the stack.
3598 for (size_t i
= 0; i
< args
->dim
; i
++)
3599 { Object
*o
= (Object
*)args
->data
[i
];
3600 Expression
*ea
= isExpression(o
);
3601 Dsymbol
*sa
= isDsymbol(o
);
3602 Tuple
*va
= isTuple(o
);
3605 if (ea
->op
== TOKvar
)
3607 sa
= ((VarExp
*)ea
)->var
;
3610 if (ea
->op
== TOKfunction
)
3612 sa
= ((FuncExp
*)ea
)->fd
;
3619 Declaration
*d
= sa
->isDeclaration();
3620 if (d
&& !d
->isDataseg() &&
3622 !(d
->storage_class
& STCmanifest
) &&
3624 (!d
->isFuncDeclaration() || d
->isFuncDeclaration()->isNested()) &&
3627 // if module level template
3628 if (tempdecl
->toParent()->isModule())
3629 { Dsymbol
*dparent
= d
->toParent();
3632 else if (isnested
!= dparent
)
3634 /* Select the more deeply nested of the two.
3635 * Error if one is not nested inside the other.
3637 for (Dsymbol
*p
= isnested
; p
; p
= p
->parent
)
3640 goto L1
; // isnested is most nested
3642 for (Dsymbol
*p
= dparent
; 1; p
= p
->parent
)
3645 { isnested
= dparent
;
3646 goto L1
; // dparent is most nested
3649 error("is nested in both %s and %s", isnested
->toChars(), dparent
->toChars());
3652 //printf("\tnested inside %s\n", isnested->toChars());
3656 error("cannot use local '%s' as template parameter", d
->toChars());
3661 nested
|= isNested(&va
->objects
);
3667 /****************************************
3668 * This instance needs an identifier for name mangling purposes.
3669 * Create one by taking the template declaration name and adding
3670 * the type signature for it.
3673 Identifier
*TemplateInstance::genIdent()
3678 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
3679 id
= tempdecl
->ident
->toChars();
3680 buf
.printf("__T%"PRIuSIZE
"%s", strlen(id
), id
);
3682 for (int i
= 0; i
< args
->dim
; i
++)
3683 { Object
*o
= (Object
*)args
->data
[i
];
3684 Type
*ta
= isType(o
);
3685 Expression
*ea
= isExpression(o
);
3686 Dsymbol
*sa
= isDsymbol(o
);
3687 Tuple
*va
= isTuple(o
);
3688 //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
3693 buf
.writestring(ta
->deco
);
3697 printf("ta = %d, %s\n", ta
->ty
, ta
->toChars());
3699 assert(global
.errors
);
3706 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3707 if (ea
->op
== TOKvar
)
3709 sa
= ((VarExp
*)ea
)->var
;
3713 if (ea
->op
== TOKfunction
)
3715 sa
= ((FuncExp
*)ea
)->fd
;
3720 if (ea
->op
== TOKtuple
)
3721 { ea
->error("tuple is not a valid template value argument");
3725 /* Use deco that matches what it would be for a function parameter
3727 //buf.writestring(ea->type->toHeadMutable()->deco);
3728 buf
.writestring(ea
->type
->deco
);
3730 // Use type of parameter, not type of argument
3731 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3733 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3735 buf
.writestring(tvp
->valType
->deco
);
3737 ea
->toMangleBuffer(&buf
);
3743 Declaration
*d
= sa
->isDeclaration();
3744 if (d
&& !d
->type
->deco
)
3745 error("forward reference of %s", d
->toChars());
3748 char *p
= sa
->mangle();
3749 buf
.printf("%"PRIuSIZE
"%s", strlen(p
), p
);
3754 assert(i
+ 1 == args
->dim
); // must be last one
3755 args
= &va
->objects
;
3764 return new Identifier(id
, TOKidentifier
);
3768 /****************************************************
3769 * Declare parameters of template instance, initialize them with the
3770 * template instance arguments.
3773 void TemplateInstance::declareParameters(Scope
*scope
)
3775 //printf("TemplateInstance::declareParameters()\n");
3776 for (int i
= 0; i
< tdtypes
.dim
; i
++)
3778 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3779 //Object *o = (Object *)tiargs->data[i];
3780 Object
*o
= (Object
*)tdtypes
.data
[i
];
3782 //printf("\ttdtypes[%d] = %p\n", i, o);
3783 tempdecl
->declareParameter(scope
, tp
, o
);
3788 void TemplateInstance::semantic2(Scope
*sc
)
3791 if (semanticdone
>= 2)
3795 printf("+TemplateInstance::semantic2('%s')\n", toChars());
3797 if (!errors
&& members
)
3799 sc
= tempdecl
->scope
;
3801 sc
= sc
->push(argsym
);
3802 sc
= sc
->push(this);
3803 for (i
= 0; i
< members
->dim
; i
++)
3805 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3807 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
3815 printf("-TemplateInstance::semantic2('%s')\n", toChars());
3819 void TemplateInstance::semantic3(Scope
*sc
)
3822 printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone
);
3824 //if (toChars()[0] == 'D') *(char*)0=0;
3825 if (semanticdone
>= 3)
3828 if (!errors
&& members
)
3830 sc
= tempdecl
->scope
;
3831 sc
= sc
->push(argsym
);
3832 sc
= sc
->push(this);
3833 sc
->fromDcode
= !tempdecl
->dltSource
;
3834 for (int i
= 0; i
< members
->dim
; i
++)
3836 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3844 void TemplateInstance::toObjFile(int multiobj
)
3847 printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
3849 if (!errors
&& members
)
3852 // Append to list of object files to be written later
3856 for (int i
= 0; i
< members
->dim
; i
++)
3858 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3859 s
->toObjFile(multiobj
);
3865 void TemplateInstance::inlineScan()
3868 printf("TemplateInstance::inlineScan('%s')\n", toChars());
3870 if (!errors
&& members
)
3872 for (int i
= 0; i
< members
->dim
; i
++)
3874 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3880 void TemplateInstance::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3884 Identifier
*id
= name
;
3885 buf
->writestring(id
->toChars());
3886 buf
->writestring("!(");
3888 buf
->writestring("...");
3892 Objects
*args
= tiargs
;
3893 for (i
= 0; i
< args
->dim
; i
++)
3896 buf
->writeByte(',');
3897 Object
*oarg
= (Object
*)args
->data
[i
];
3898 ObjectToCBuffer(buf
, hgs
, oarg
);
3902 buf
->writeByte(')');
3906 Dsymbol
*TemplateInstance::toAlias()
3909 printf("TemplateInstance::toAlias()\n");
3912 { error("cannot resolve forward reference");
3917 return inst
->toAlias();
3920 return aliasdecl
->toAlias();
3925 AliasDeclaration
*TemplateInstance::isAliasDeclaration()
3930 char *TemplateInstance::kind()
3932 return "template instance";
3935 int TemplateInstance::oneMember(Dsymbol
**ps
)
3941 char *TemplateInstance::toChars()
3947 toCBuffer(&buf
, &hgs
);
3953 /* ======================== TemplateMixin ================================ */
3955 TemplateMixin::TemplateMixin(Loc loc
, Identifier
*ident
, Type
*tqual
,
3956 Array
*idents
, Objects
*tiargs
)
3957 : TemplateInstance(loc
, (Identifier
*)idents
->data
[idents
->dim
- 1])
3959 //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
3960 this->ident
= ident
;
3961 this->tqual
= tqual
;
3962 this->idents
= idents
;
3963 this->tiargs
= tiargs
? tiargs
: new Objects();
3967 Dsymbol
*TemplateMixin::syntaxCopy(Dsymbol
*s
)
3968 { TemplateMixin
*tm
;
3970 Array
*ids
= new Array();
3971 ids
->setDim(idents
->dim
);
3972 for (int i
= 0; i
< idents
->dim
; i
++)
3973 { // Matches TypeQualified::syntaxCopyHelper()
3974 Identifier
*id
= (Identifier
*)idents
->data
[i
];
3975 if (id
->dyncast() == DYNCAST_DSYMBOL
)
3977 TemplateInstance
*ti
= (TemplateInstance
*)id
;
3979 ti
= (TemplateInstance
*)ti
->syntaxCopy(NULL
);
3980 id
= (Identifier
*)ti
;
3985 tm
= new TemplateMixin(loc
, ident
,
3986 (Type
*)(tqual
? tqual
->syntaxCopy() : NULL
),
3988 TemplateInstance::syntaxCopy(tm
);
3992 void TemplateMixin::semantic(Scope
*sc
)
3995 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
3999 // This for when a class/struct contains mixin members, and
4000 // is done over because of forward references
4001 (!parent
|| !toParent()->isAggregateDeclaration()))
4004 printf("\tsemantic done\n");
4011 printf("\tdo semantic\n");
4017 scx
= scope
; // save so we don't make redundant copies
4021 // Follow qualifications to find the TemplateDeclaration
4028 { s
= tqual
->toDsymbol(sc
);
4034 id
= (Identifier
*)idents
->data
[0];
4035 switch (id
->dyncast())
4037 case DYNCAST_IDENTIFIER
:
4038 s
= sc
->search(loc
, id
, NULL
);
4041 case DYNCAST_DSYMBOL
:
4043 TemplateInstance
*ti
= (TemplateInstance
*)id
;
4053 for (; i
< idents
->dim
; i
++)
4057 id
= (Identifier
*)idents
->data
[i
];
4058 s
= s
->searchX(loc
, sc
, id
);
4062 error("is not defined");
4066 tempdecl
= s
->toAlias()->isTemplateDeclaration();
4069 error("%s isn't a template", s
->toChars());
4075 // Look for forward reference
4077 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
4081 /* Cannot handle forward references if mixin is a struct member,
4082 * because addField must happen during struct's semantic, not
4083 * during the mixin semantic.
4084 * runDeferred will re-run mixin's semantic outside of the struct's
4088 AggregateDeclaration
*ad
= toParent()->isAggregateDeclaration();
4093 // Forward reference
4094 //printf("forward reference - deferring\n");
4095 scope
= scx
? scx
: new Scope(*sc
);
4097 scope
->module
->addDeferredSemantic(this);
4103 // Run semantic on each argument, place results in tiargs[]
4106 tempdecl
= findBestMatch(sc
);
4109 return; // error recovery
4116 parent
= sc
->parent
;
4118 /* Detect recursive mixin instantiations.
4120 for (Dsymbol
*s
= parent
; s
; s
= s
->parent
)
4122 //printf("\ts = '%s'\n", s->toChars());
4123 TemplateMixin
*tm
= s
->isTemplateMixin();
4124 if (!tm
|| tempdecl
!= tm
->tempdecl
)
4127 for (int i
= 0; i
< tiargs
->dim
; i
++)
4128 { Object
*o
= (Object
*)tiargs
->data
[i
];
4129 Type
*ta
= isType(o
);
4130 Expression
*ea
= isExpression(o
);
4131 Dsymbol
*sa
= isDsymbol(o
);
4132 Object
*tmo
= (Object
*)tm
->tiargs
->data
[i
];
4135 Type
*tmta
= isType(tmo
);
4138 if (!ta
->equals(tmta
))
4142 { Expression
*tme
= isExpression(tmo
);
4143 if (!tme
|| !ea
->equals(tme
))
4148 Dsymbol
*tmsa
= isDsymbol(tmo
);
4155 error("recursive mixin instantiation");
4162 // Copy the syntax trees from the TemplateDeclaration
4163 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
4167 symtab
= new DsymbolTable();
4169 for (Scope
*sce
= sc
; 1; sce
= sce
->enclosing
)
4171 ScopeDsymbol
*sds
= (ScopeDsymbol
*)sce
->scopesym
;
4174 sds
->importScope(this, PROTpublic
);
4180 printf("\tcreate scope for template parameters '%s'\n", toChars());
4183 scy
= sc
->push(this);
4186 argsym
= new ScopeDsymbol();
4187 argsym
->parent
= scy
->parent
;
4188 Scope
*scope
= scy
->push(argsym
);
4190 unsigned errorsave
= global
.errors
;
4192 // Declare each template parameter as an alias for the argument type
4193 declareParameters(scope
);
4195 // Add members to enclosing scope, as well as this scope
4196 for (unsigned i
= 0; i
< members
->dim
; i
++)
4199 s
= (Dsymbol
*)members
->data
[i
];
4200 s
->addMember(scope
, this, i
);
4202 //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
4203 //printf("s->parent = %s\n", s->parent->toChars());
4206 // Do semantic() analysis on template instance members
4208 printf("\tdo semantic() on template instance members '%s'\n", toChars());
4211 sc2
= scope
->push(this);
4212 sc2
->offset
= sc
->offset
;
4213 for (int i
= 0; i
< members
->dim
; i
++)
4215 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4218 sc
->offset
= sc2
->offset
;
4220 /* The problem is when to parse the initializer for a variable.
4221 * Perhaps VarDeclaration::semantic() should do it like it does
4222 * for initializers inside a function.
4224 // if (sc->parent->isFuncDeclaration())
4233 // Give additional context info if error occurred during instantiation
4234 if (global
.errors
!= errorsave
)
4236 error("error instantiating");
4243 // if (!isAnonymous())
4248 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
4252 void TemplateMixin::semantic2(Scope
*sc
)
4255 if (semanticdone
>= 2)
4259 printf("+TemplateMixin::semantic2('%s')\n", toChars());
4264 sc
= sc
->push(argsym
);
4265 sc
= sc
->push(this);
4266 for (i
= 0; i
< members
->dim
; i
++)
4268 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4270 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
4278 printf("-TemplateMixin::semantic2('%s')\n", toChars());
4282 void TemplateMixin::semantic3(Scope
*sc
)
4285 if (semanticdone
>= 3)
4289 printf("TemplateMixin::semantic3('%s')\n", toChars());
4293 sc
= sc
->push(argsym
);
4294 sc
= sc
->push(this);
4295 for (i
= 0; i
< members
->dim
; i
++)
4297 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4305 void TemplateMixin::inlineScan()
4307 TemplateInstance::inlineScan();
4310 char *TemplateMixin::kind()
4315 int TemplateMixin::oneMember(Dsymbol
**ps
)
4317 return Dsymbol::oneMember(ps
);
4320 int TemplateMixin::hasPointers()
4322 //printf("TemplateMixin::hasPointers() %s\n", toChars());
4323 for (size_t i
= 0; i
< members
->dim
; i
++)
4325 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4326 //printf(" s = %s %s\n", s->kind(), s->toChars());
4327 if (s
->hasPointers())
4335 char *TemplateMixin::toChars()
4341 TemplateInstance::toCBuffer(&buf
, &hgs
);
4347 void TemplateMixin::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4349 buf
->writestring("mixin ");
4351 for (i
= 0; i
< idents
->dim
; i
++)
4352 { Identifier
*id
= (Identifier
*)idents
->data
[i
];
4355 buf
->writeByte('.');
4356 buf
->writestring(id
->toChars());
4358 buf
->writestring("!(");
4361 for (i
= 0; i
< tiargs
->dim
; i
++)
4363 buf
->writebyte(',');
4364 Object
*oarg
= (Object
*)tiargs
->data
[i
];
4365 Type
*t
= isType(oarg
);
4366 Expression
*e
= isExpression(oarg
);
4367 Dsymbol
*s
= isDsymbol(oarg
);
4369 t
->toCBuffer(buf
, NULL
, hgs
);
4371 e
->toCBuffer(buf
, hgs
);
4374 char *p
= s
->ident
? s
->ident
->toChars() : s
->toChars();
4375 buf
->writestring(p
);
4379 buf
->writestring("NULL");
4387 buf
->writebyte(')');
4388 buf
->writebyte(';');
4393 void TemplateMixin::toObjFile(int multiobj
)
4395 //printf("TemplateMixin::toObjFile('%s')\n", toChars());
4396 TemplateInstance::toObjFile(multiobj
);