2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 // Handle template implementation
24 long __cdecl
__ehfilter(LPEXCEPTION_POINTERS ep
);
29 #include "stringtable.h"
34 #include "expression.h"
37 #include "aggregate.h"
38 #include "declaration.h"
42 #include "identifier.h"
47 /********************************************
48 * These functions substitute for dynamic_cast. dynamic_cast does not work
49 * on earlier versions of gcc.
52 Expression
*isExpression(Object
*o
)
54 //return dynamic_cast<Expression *>(o);
55 if (!o
|| o
->dyncast() != DYNCAST_EXPRESSION
)
57 return (Expression
*)o
;
60 Dsymbol
*isDsymbol(Object
*o
)
62 //return dynamic_cast<Dsymbol *>(o);
63 if (!o
|| o
->dyncast() != DYNCAST_DSYMBOL
)
68 Type
*isType(Object
*o
)
70 //return dynamic_cast<Type *>(o);
71 if (!o
|| o
->dyncast() != DYNCAST_TYPE
)
76 Tuple
*isTuple(Object
*o
)
78 //return dynamic_cast<Tuple *>(o);
79 if (!o
|| o
->dyncast() != DYNCAST_TUPLE
)
85 /***********************
86 * Try to get arg as a type.
89 Type
*getType(Object
*o
)
93 { Expression
*e
= isExpression(o
);
100 Dsymbol
*getDsymbol(Object
*oarg
)
103 Expression
*ea
= isExpression(oarg
);
105 { // Try to convert Expression to symbol
106 if (ea
->op
== TOKvar
)
107 sa
= ((VarExp
*)ea
)->var
;
108 else if (ea
->op
== TOKfunction
)
109 sa
= ((FuncExp
*)ea
)->fd
;
114 { // Try to convert Type to symbol
115 Type
*ta
= isType(oarg
);
117 sa
= ta
->toDsymbol(NULL
);
119 sa
= isDsymbol(oarg
); // if already a symbol
124 /******************************
125 * If o1 matches o2, return 1.
129 int match(Object
*o1
, Object
*o2
, TemplateDeclaration
*tempdecl
, Scope
*sc
)
131 Type
*t1
= isType(o1
);
132 Type
*t2
= isType(o2
);
133 Expression
*e1
= isExpression(o1
);
134 Expression
*e2
= isExpression(o2
);
135 Dsymbol
*s1
= isDsymbol(o1
);
136 Dsymbol
*s2
= isDsymbol(o2
);
137 Tuple
*v1
= isTuple(o1
);
138 Tuple
*v2
= isTuple(o2
);
140 //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
142 /* A proper implementation of the various equals() overrides
143 * should make it possible to just do o1->equals(o2), but
144 * we'll do that another day.
149 /* if t1 is an instance of ti, then give error
150 * about recursive expansions.
152 Dsymbol
*s
= t1
->toDsymbol(sc
);
154 { TemplateInstance
*ti1
= s
->parent
->isTemplateInstance();
155 if (ti1
&& ti1
->tempdecl
== tempdecl
)
157 for (Scope
*sc1
= sc
; sc1
; sc1
= sc1
->enclosing
)
159 if (sc1
->scopesym
== ti1
)
161 error("recursive template expansion for template argument %s", t1
->toChars());
162 return 1; // fake a match
168 if (!t2
|| !t1
->equals(t2
))
176 printf("match %d\n", e1
->equals(e2
));
190 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
191 if (!s2
|| !s1
->equals(s2
) || s1
->parent
!= s2
->parent
)
200 if (v1
->objects
.dim
!= v2
->objects
.dim
)
202 for (size_t i
= 0; i
< v1
->objects
.dim
; i
++)
204 if (!match((Object
*)v1
->objects
.data
[i
],
205 (Object
*)v2
->objects
.data
[i
],
212 return 0; // nomatch;
215 /****************************************
218 void ObjectToCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
, Object
*oarg
)
220 //printf("ObjectToCBuffer()\n");
221 Type
*t
= isType(oarg
);
222 Expression
*e
= isExpression(oarg
);
223 Dsymbol
*s
= isDsymbol(oarg
);
224 Tuple
*v
= isTuple(oarg
);
226 { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
227 t
->toCBuffer(buf
, NULL
, hgs
);
230 e
->toCBuffer(buf
, hgs
);
233 char *p
= s
->ident
? s
->ident
->toChars() : s
->toChars();
238 Objects
*args
= &v
->objects
;
239 for (size_t i
= 0; i
< args
->dim
; i
++)
243 Object
*o
= (Object
*)args
->data
[i
];
244 ObjectToCBuffer(buf
, hgs
, o
);
249 buf
->writestring("NULL");
254 printf("bad Object = %p\n", oarg
);
262 /* ======================== TemplateDeclaration ============================= */
264 TemplateDeclaration::TemplateDeclaration(Loc loc
, Identifier
*id
, TemplateParameters
*parameters
, Array
*decldefs
)
268 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id
->toChars());
272 for (int i
= 0; i
< parameters
->dim
; i
++)
273 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
274 //printf("\tparameter[%d] = %p\n", i, tp);
275 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
279 printf("\tparameter[%d] = %s : %s\n", i
, tp
->ident
->toChars(), ttp
->specType
? ttp
->specType
->toChars() : "");
284 this->parameters
= parameters
;
285 this->origParameters
= parameters
;
286 this->members
= decldefs
;
287 this->overnext
= NULL
;
288 this->overroot
= NULL
;
290 this->onemember
= NULL
;
293 Dsymbol
*TemplateDeclaration::syntaxCopy(Dsymbol
*)
295 //printf("TemplateDeclaration::syntaxCopy()\n");
296 TemplateDeclaration
*td
;
297 TemplateParameters
*p
;
303 p
= new TemplateParameters();
304 p
->setDim(parameters
->dim
);
305 for (int i
= 0; i
< p
->dim
; i
++)
306 { TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
307 p
->data
[i
] = (void *)tp
->syntaxCopy();
310 d
= Dsymbol::arraySyntaxCopy(members
);
311 td
= new TemplateDeclaration(loc
, ident
, p
, d
);
315 void TemplateDeclaration::semantic(Scope
*sc
)
318 printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident
->toChars());
321 return; // semantic() already run
325 // error("cannot declare template at function scope %s", sc->func->toChars());
328 if (/*global.params.useArrayBounds &&*/ sc
->module
)
330 // Generate this function as it may be used
331 // when template is instantiated in other modules
332 sc
->module
->toModuleArray();
335 if (/*global.params.useAssert &&*/ sc
->module
)
337 // Generate this function as it may be used
338 // when template is instantiated in other modules
339 sc
->module
->toModuleAssert();
342 /* Remember Scope for later instantiations, but make
343 * a copy since attributes can change.
345 this->scope
= new Scope(*sc
);
346 this->scope
->setNoFree();
348 // Set up scope for parameters
349 ScopeDsymbol
*paramsym
= new ScopeDsymbol();
350 paramsym
->parent
= sc
->parent
;
351 Scope
*paramscope
= sc
->push(paramsym
);
352 paramscope
->parameterSpecialization
= 1;
354 if (global
.params
.doDocComments
)
356 origParameters
= new TemplateParameters();
357 origParameters
->setDim(parameters
->dim
);
358 for (int i
= 0; i
< parameters
->dim
; i
++)
360 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
361 origParameters
->data
[i
] = (void *)tp
->syntaxCopy();
365 for (int i
= 0; i
< parameters
->dim
; i
++)
367 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
369 tp
->declareParameter(paramscope
);
372 for (int i
= 0; i
< parameters
->dim
; i
++)
374 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
376 tp
->semantic(paramscope
);
377 if (i
+ 1 != parameters
->dim
&& tp
->isTemplateTupleParameter())
378 error("template tuple parameter must be last one");
386 if (Dsymbol::oneMembers(members
, &s
))
388 if (s
&& s
->ident
&& s
->ident
->equals(ident
))
396 /* BUG: should check:
397 * o no virtual functions or non-static data members of classes
401 char *TemplateDeclaration::kind()
403 return (onemember
&& onemember
->isAggregateDeclaration())
405 : (char *)"template";
408 /**********************************
409 * Overload existing TemplateDeclaration 'this' with the new one 's'.
410 * Return !=0 if successful; i.e. no conflict.
413 int TemplateDeclaration::overloadInsert(Dsymbol
*s
)
415 TemplateDeclaration
**pf
;
416 TemplateDeclaration
*f
;
419 printf("TemplateDeclaration::overloadInsert('%s')\n", s
->toChars());
421 f
= s
->isTemplateDeclaration();
424 TemplateDeclaration
*pthis
= this;
425 for (pf
= &pthis
; *pf
; pf
= &(*pf
)->overnext
)
428 // Conflict if TemplateParameter's match
429 // Will get caught anyway later with TemplateInstance, but
430 // should check it now.
431 TemplateDeclaration
*f2
= *pf
;
433 if (f
->parameters
->dim
!= f2
->parameters
->dim
)
436 for (int i
= 0; i
< f
->parameters
->dim
; i
++)
437 { TemplateParameter
*p1
= (TemplateParameter
*)f
->parameters
->data
[i
];
438 TemplateParameter
*p2
= (TemplateParameter
*)f2
->parameters
->data
[i
];
440 if (!p1
->overloadMatch(p2
))
445 printf("\tfalse: conflict\n");
457 printf("\ttrue: no conflict\n");
462 /***************************************
463 * Given that ti is an instance of this TemplateDeclaration,
464 * deduce the types of the parameters to this, and store
465 * those deduced types in dedtypes[].
467 * flag 1: don't do semantic() because of dummy types
468 * 2: don't change types in matchArg()
470 * dedtypes deduced arguments
471 * Return match level.
474 MATCH
TemplateDeclaration::matchWithInstance(TemplateInstance
*ti
,
475 Objects
*dedtypes
, int flag
)
477 int dedtypes_dim
= dedtypes
->dim
;
481 printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti
->toChars(), flag
);
485 printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim
, parameters
->dim
);
487 printf("ti->tiargs->dim = %d, [0] = %p\n",
489 ti
->tiargs
->data
[0]);
493 int parameters_dim
= parameters
->dim
;
494 int variadic
= isVariadic() != NULL
;
496 // If more arguments than parameters, no match
497 if (ti
->tiargs
->dim
> parameters_dim
&& !variadic
)
500 printf(" no match: more arguments than parameters\n");
505 assert(dedtypes_dim
== parameters_dim
);
506 assert(dedtypes_dim
>= ti
->tiargs
->dim
|| variadic
);
508 // Set up scope for parameters
509 assert((size_t)scope
> 0x10000);
510 ScopeDsymbol
*paramsym
= new ScopeDsymbol();
511 paramsym
->parent
= scope
->parent
;
512 Scope
*paramscope
= scope
->push(paramsym
);
514 // Attempt type deduction
516 for (int i
= 0; i
< dedtypes_dim
; i
++)
518 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
521 //printf("\targument [%d]\n", i);
523 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
524 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
526 printf("\tparameter[%d] is %s : %s\n", i
, tp
->ident
->toChars(), ttp
->specType
? ttp
->specType
->toChars() : "");
530 m2
= tp
->matchArg(paramscope
, ti
->tiargs
, i
, parameters
, dedtypes
, &sparam
);
532 m2
= tp
->matchArg(paramscope
, ti
->tiargs
, i
, parameters
, dedtypes
, &sparam
, (flag
& 2) ? 1 : 0);
535 //printf("\tm2 = %d\n", m2);
537 if (m2
== MATCHnomatch
)
540 printf("\tmatchArg() for parameter %i failed\n", i
);
549 sparam
->semantic(paramscope
);
550 if (!paramscope
->insert(sparam
))
556 // Any parameter left without a type gets the type of its corresponding arg
557 for (int i
= 0; i
< dedtypes_dim
; i
++)
559 if (!dedtypes
->data
[i
])
560 { assert(i
< ti
->tiargs
->dim
);
561 dedtypes
->data
[i
] = ti
->tiargs
->data
[i
];
567 // Print out the results
568 printf("--------------------------\n");
569 printf("template %s\n", toChars());
570 printf("instance %s\n", ti
->toChars());
573 for (int i
= 0; i
< dedtypes_dim
; i
++)
575 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
580 if (i
< ti
->tiargs
->dim
)
581 oarg
= (Object
*)ti
->tiargs
->data
[i
];
584 tp
->print(oarg
, (Object
*)dedtypes
->data
[i
]);
592 printf(" match = %d\n", m
);
598 printf(" no match\n");
605 printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti
, m
);
610 /********************************************
611 * Determine partial specialization order of 'this' vs td2.
613 * 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();
1330 if (tparam
->ty
== Tident
)
1332 // Determine which parameter tparam is
1333 int i
= templateParameterLookup(tparam
, parameters
);
1338 /* BUG: what if tparam is a template instance, that
1339 * has as an argument another Tident?
1341 tparam
= tparam
->semantic(0, sc
);
1342 assert(tparam
->ty
!= Tident
);
1343 return deduceType(sc
, tparam
, parameters
, dedtypes
);
1346 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1348 // Found the corresponding parameter tp
1349 if (!tp
->isTemplateTypeParameter())
1351 Type
*at
= (Type
*)dedtypes
->data
[i
];
1354 if (tparam
->isMutable())
1355 { // foo(U:U) T => T
1356 // foo(U:U) const(T) => const(T)
1357 // foo(U:U) invariant(T) => invariant(T)
1358 dedtypes
->data
[i
] = (void *)this;
1361 else if (mod
== tparam
->mod
)
1362 { // foo(U:const(U)) const(T) => T
1363 // foo(U:invariant(U)) invariant(T) => T
1364 dedtypes
->data
[i
] = (void *)mutableOf();
1367 else if (tparam
->isConst())
1368 { // foo(U:const(U)) T => T
1369 // foo(U:const(U)) invariant(T) => T
1370 dedtypes
->data
[i
] = (void *)mutableOf();
1374 { // foo(U:invariant(U)) T => nomatch
1375 // foo(U:invariant(U)) const(T) => nomatch
1381 else if (ty
== Tclass
&& at
->ty
== Tclass
)
1383 return implicitConvTo(at
);
1385 else if (ty
== Tsarray
&& at
->ty
== Tarray
&&
1386 nextOf()->implicitConvTo(at
->nextOf()) >= MATCHconst
)
1394 if (ty
!= tparam
->ty
)
1398 return nextOf()->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1404 return MATCHnomatch
;
1410 MATCH
TypeSArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
,
1414 printf("TypeSArray::deduceType()\n");
1415 printf("\tthis = %d, ", ty
); print();
1416 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1419 // Extra check that array dimensions must match
1422 if (tparam
->ty
== Tsarray
)
1424 TypeSArray
*tp
= (TypeSArray
*)tparam
;
1426 if (tp
->dim
->op
== TOKvar
&&
1427 ((VarExp
*)tp
->dim
)->var
->storage_class
& STCtemplateparameter
)
1428 { int i
= templateIdentifierLookup(((VarExp
*)tp
->dim
)->var
->ident
, parameters
);
1429 // This code matches code in TypeInstance::deduceType()
1432 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1433 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1436 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
1439 if (!dim
->equals(e
))
1443 { Type
*vt
= tvp
->valType
->semantic(0, sc
);
1444 MATCH m
= (MATCH
)dim
->implicitConvTo(vt
);
1447 dedtypes
->data
[i
] = dim
;
1450 else if (dim
->toInteger() != tp
->dim
->toInteger())
1451 return MATCHnomatch
;
1453 else if (tparam
->ty
== Taarray
)
1455 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1456 if (tp
->index
->ty
== Tident
)
1457 { TypeIdentifier
*tident
= (TypeIdentifier
*)tp
->index
;
1459 if (tident
->idents
.dim
== 0)
1460 { Identifier
*id
= tident
->ident
;
1462 for (size_t i
= 0; i
< parameters
->dim
; i
++)
1464 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[i
];
1466 if (tp
->ident
->equals(id
))
1467 { // Found the corresponding template parameter
1468 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
1469 if (!tvp
|| !tvp
->valType
->isintegral())
1472 if (dedtypes
->data
[i
])
1474 if (!dim
->equals((Object
*)dedtypes
->data
[i
]))
1478 { dedtypes
->data
[i
] = (void *)dim
;
1480 return next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1486 else if (tparam
->ty
== Tarray
)
1489 m
= next
->deduceType(sc
, tparam
->nextOf(), parameters
, dedtypes
);
1490 if (m
== MATCHexact
)
1495 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1498 return MATCHnomatch
;
1501 MATCH
TypeAArray::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1504 printf("TypeAArray::deduceType()\n");
1505 printf("\tthis = %d, ", ty
); print();
1506 printf("\ttparam = %d, ", tparam
->ty
); tparam
->print();
1509 // Extra check that index type must match
1510 if (tparam
&& tparam
->ty
== Taarray
)
1512 TypeAArray
*tp
= (TypeAArray
*)tparam
;
1513 if (!index
->deduceType(sc
, tp
->index
, parameters
, dedtypes
))
1515 return MATCHnomatch
;
1518 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1521 MATCH
TypeFunction::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1523 //printf("TypeFunction::deduceType()\n");
1524 //printf("\tthis = %d, ", ty); print();
1525 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1527 // Extra check that function characteristics must match
1528 if (tparam
&& tparam
->ty
== Tfunction
)
1530 TypeFunction
*tp
= (TypeFunction
*)tparam
;
1531 if (varargs
!= tp
->varargs
||
1532 linkage
!= tp
->linkage
)
1533 return MATCHnomatch
;
1535 size_t nfargs
= Argument::dim(this->parameters
);
1536 size_t nfparams
= Argument::dim(tp
->parameters
);
1538 /* See if tuple match
1540 if (nfparams
> 0 && nfargs
>= nfparams
- 1)
1542 /* See if 'A' of the template parameter matches 'A'
1543 * of the type of the last function parameter.
1545 Argument
*fparam
= (Argument
*)tp
->parameters
->data
[nfparams
- 1];
1546 if (fparam
->type
->ty
!= Tident
)
1548 TypeIdentifier
*tid
= (TypeIdentifier
*)fparam
->type
;
1549 if (tid
->idents
.dim
)
1552 /* Look through parameters to find tuple matching tid->ident
1556 { if (tupi
== parameters
->dim
)
1558 TemplateParameter
*t
= (TemplateParameter
*)parameters
->data
[tupi
];
1559 TemplateTupleParameter
*tup
= t
->isTemplateTupleParameter();
1560 if (tup
&& tup
->ident
->equals(tid
->ident
))
1564 /* The types of the function arguments [nfparams - 1 .. nfargs]
1565 * now form the tuple argument.
1567 int tuple_dim
= nfargs
- (nfparams
- 1);
1569 /* See if existing tuple, and whether it matches or not
1571 Object
*o
= (Object
*)dedtypes
->data
[tupi
];
1573 { // Existing deduced argument must be a tuple, and must match
1574 Tuple
*t
= isTuple(o
);
1575 if (!t
|| t
->objects
.dim
!= tuple_dim
)
1576 return MATCHnomatch
;
1577 for (size_t i
= 0; i
< tuple_dim
; i
++)
1578 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1579 if (!arg
->type
->equals((Object
*)t
->objects
.data
[i
]))
1580 return MATCHnomatch
;
1584 { // Create new tuple
1585 Tuple
*t
= new Tuple();
1586 t
->objects
.setDim(tuple_dim
);
1587 for (size_t i
= 0; i
< tuple_dim
; i
++)
1588 { Argument
*arg
= Argument::getNth(this->parameters
, nfparams
- 1 + i
);
1589 t
->objects
.data
[i
] = (void *)arg
->type
;
1591 dedtypes
->data
[tupi
] = (void *)t
;
1593 nfparams
--; // don't consider the last parameter for type deduction
1598 if (nfargs
!= nfparams
)
1599 return MATCHnomatch
;
1601 for (size_t i
= 0; i
< nfparams
; i
++)
1603 Argument
*a
= Argument::getNth(this->parameters
, i
);
1604 Argument
*ap
= Argument::getNth(tp
->parameters
, i
);
1605 if (a
->storageClass
!= ap
->storageClass
||
1606 !a
->type
->deduceType(sc
, ap
->type
, parameters
, dedtypes
))
1607 return MATCHnomatch
;
1610 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1613 MATCH
TypeIdentifier::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1616 if (tparam
&& tparam
->ty
== Tident
)
1618 TypeIdentifier
*tp
= (TypeIdentifier
*)tparam
;
1620 for (int i
= 0; i
< idents
.dim
; i
++)
1622 Identifier
*id1
= (Identifier
*)idents
.data
[i
];
1623 Identifier
*id2
= (Identifier
*)tp
->idents
.data
[i
];
1625 if (!id1
->equals(id2
))
1626 return MATCHnomatch
;
1629 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1632 MATCH
TypeInstance::deduceType(Scope
*sc
,
1633 Type
*tparam
, TemplateParameters
*parameters
,
1636 //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
1637 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1640 if (tparam
&& tparam
->ty
== Tinstance
)
1642 TypeInstance
*tp
= (TypeInstance
*)tparam
;
1644 //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
1645 //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
1646 if (!tp
->tempinst
->tempdecl
)
1647 { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
1648 if (!tp
->tempinst
->name
->equals(tempinst
->name
))
1651 * template Foo(T : sa!(T), alias sa)
1653 int i
= templateIdentifierLookup(tp
->tempinst
->name
, parameters
);
1655 { /* Didn't find it as a parameter identifier. Try looking
1656 * it up and seeing if is an alias. See Bugzilla 1454
1658 Dsymbol
*s
= tempinst
->tempdecl
->scope
->search(0, tp
->tempinst
->name
, NULL
);
1662 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
1663 if (td
&& td
== tempinst
->tempdecl
)
1668 TemplateParameter
*tpx
= (TemplateParameter
*)parameters
->data
[i
];
1669 // This logic duplicates tpx->matchArg()
1670 TemplateAliasParameter
*ta
= tpx
->isTemplateAliasParameter();
1673 Dsymbol
*sa
= tempinst
->tempdecl
;
1676 if (ta
->specAlias
&& sa
!= ta
->specAlias
)
1678 if (dedtypes
->data
[i
])
1679 { // Must match already deduced symbol
1680 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
1685 dedtypes
->data
[i
] = sa
;
1688 else if (tempinst
->tempdecl
!= tp
->tempinst
->tempdecl
)
1692 if (tempinst
->tiargs
->dim
!= tp
->tempinst
->tiargs
->dim
)
1695 for (int i
= 0; i
< tempinst
->tiargs
->dim
; i
++)
1697 //printf("\ttest: tempinst->tiargs[%d]\n", i);
1699 Object
*o1
= (Object
*)tempinst
->tiargs
->data
[i
];
1700 Object
*o2
= (Object
*)tp
->tempinst
->tiargs
->data
[i
];
1702 Type
*t1
= isType(o1
);
1703 Type
*t2
= isType(o2
);
1705 Expression
*e1
= isExpression(o1
);
1706 Expression
*e2
= isExpression(o2
);
1709 if (t1
) printf("t1 = %s\n", t1
->toChars());
1710 if (t2
) printf("t2 = %s\n", t2
->toChars());
1711 if (e1
) printf("e1 = %s\n", e1
->toChars());
1712 if (e2
) printf("e2 = %s\n", e2
->toChars());
1717 if (!t1
->deduceType(sc
, t2
, parameters
, dedtypes
))
1722 if (!e1
->equals(e2
))
1723 { if (e2
->op
== TOKvar
)
1726 * (T:Number!(e2), int e2)
1728 j
= templateIdentifierLookup(((VarExp
*)e2
)->var
->ident
, parameters
);
1734 else if (e1
&& t2
&& t2
->ty
== Tident
)
1736 j
= templateParameterLookup(t2
, parameters
);
1740 TemplateParameter
*tp
= (TemplateParameter
*)parameters
->data
[j
];
1741 // BUG: use tp->matchArg() instead of the following
1742 TemplateValueParameter
*tv
= tp
->isTemplateValueParameter();
1745 Expression
*e
= (Expression
*)dedtypes
->data
[j
];
1752 { Type
*vt
= tv
->valType
->semantic(0, sc
);
1753 MATCH m
= (MATCH
)e1
->implicitConvTo(vt
);
1756 dedtypes
->data
[j
] = e1
;
1759 // BUG: Need to handle alias and tuple parameters
1764 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1767 return MATCHnomatch
;
1770 MATCH
TypeStruct::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1772 //printf("TypeStruct::deduceType()\n");
1773 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
1774 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1776 /* If this struct is a template struct, and we're matching
1777 * it against a template instance, convert the struct type
1778 * to a template instance, too, and try again.
1780 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1782 if (tparam
&& tparam
->ty
== Tinstance
)
1784 if (ti
&& ti
->toAlias() == sym
)
1786 TypeInstance
*t
= new TypeInstance(0, ti
);
1787 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1790 /* Match things like:
1793 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1794 if (tpi
->idents
.dim
)
1795 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1796 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1798 Type
*tparent
= sym
->parent
->getType();
1801 /* Slice off the .foo in S!(T).foo
1804 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1813 if (tparam
&& tparam
->ty
== Tstruct
)
1815 TypeStruct
*tp
= (TypeStruct
*)tparam
;
1818 return MATCHnomatch
;
1820 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1823 MATCH
TypeEnum::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1826 if (tparam
&& tparam
->ty
== Tenum
)
1828 TypeEnum
*tp
= (TypeEnum
*)tparam
;
1831 return MATCHnomatch
;
1833 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1836 MATCH
TypeTypedef::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1839 if (tparam
&& tparam
->ty
== Ttypedef
)
1841 TypeTypedef
*tp
= (TypeTypedef
*)tparam
;
1844 return MATCHnomatch
;
1846 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1849 MATCH
TypeClass::deduceType(Scope
*sc
, Type
*tparam
, TemplateParameters
*parameters
, Objects
*dedtypes
)
1851 //printf("TypeClass::deduceType(this = %s)\n", toChars());
1853 /* If this class is a template class, and we're matching
1854 * it against a template instance, convert the class type
1855 * to a template instance, too, and try again.
1857 TemplateInstance
*ti
= sym
->parent
->isTemplateInstance();
1859 if (tparam
&& tparam
->ty
== Tinstance
)
1861 if (ti
&& ti
->toAlias() == sym
)
1863 TypeInstance
*t
= new TypeInstance(0, ti
);
1864 return t
->deduceType(sc
, tparam
, parameters
, dedtypes
);
1867 /* Match things like:
1870 TypeInstance
*tpi
= (TypeInstance
*)tparam
;
1871 if (tpi
->idents
.dim
)
1872 { Identifier
*id
= (Identifier
*)tpi
->idents
.data
[tpi
->idents
.dim
- 1];
1873 if (id
->dyncast() == DYNCAST_IDENTIFIER
&& sym
->ident
->equals(id
))
1875 Type
*tparent
= sym
->parent
->getType();
1878 /* Slice off the .foo in S!(T).foo
1881 MATCH m
= tparent
->deduceType(sc
, tpi
, parameters
, dedtypes
);
1890 if (tparam
&& tparam
->ty
== Tclass
)
1892 TypeClass
*tp
= (TypeClass
*)tparam
;
1894 //printf("\t%d\n", (MATCH) implicitConvTo(tp));
1895 return implicitConvTo(tp
);
1897 return Type::deduceType(sc
, tparam
, parameters
, dedtypes
);
1900 /* ======================== TemplateParameter =============================== */
1902 TemplateParameter::TemplateParameter(Loc loc
, Identifier
*ident
)
1905 this->ident
= ident
;
1906 this->sparam
= NULL
;
1909 TemplateTypeParameter
*TemplateParameter::isTemplateTypeParameter()
1914 TemplateValueParameter
*TemplateParameter::isTemplateValueParameter()
1919 TemplateAliasParameter
*TemplateParameter::isTemplateAliasParameter()
1924 TemplateTupleParameter
*TemplateParameter::isTemplateTupleParameter()
1930 TemplateThisParameter
*TemplateParameter::isTemplateThisParameter()
1936 /* ======================== TemplateTypeParameter =========================== */
1940 TemplateTypeParameter::TemplateTypeParameter(Loc loc
, Identifier
*ident
, Type
*specType
,
1942 : TemplateParameter(loc
, ident
)
1944 this->ident
= ident
;
1945 this->specType
= specType
;
1946 this->defaultType
= defaultType
;
1949 TemplateTypeParameter
*TemplateTypeParameter::isTemplateTypeParameter()
1954 TemplateParameter
*TemplateTypeParameter::syntaxCopy()
1956 TemplateTypeParameter
*tp
= new TemplateTypeParameter(loc
, ident
, specType
, defaultType
);
1958 tp
->specType
= specType
->syntaxCopy();
1960 tp
->defaultType
= defaultType
->syntaxCopy();
1964 void TemplateTypeParameter::declareParameter(Scope
*sc
)
1966 //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
1967 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
1968 sparam
= new AliasDeclaration(loc
, ident
, ti
);
1969 if (!sc
->insert(sparam
))
1970 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
1973 void TemplateTypeParameter::semantic(Scope
*sc
)
1975 //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
1978 specType
= specType
->semantic(loc
, sc
);
1980 #if 0 // Don't do semantic() until instantiation
1983 defaultType
= defaultType
->semantic(loc
, sc
);
1988 /****************************************
1989 * Determine if two TemplateParameters are the same
1990 * as far as TemplateDeclaration overloading goes.
1996 int TemplateTypeParameter::overloadMatch(TemplateParameter
*tp
)
1998 TemplateTypeParameter
*ttp
= tp
->isTemplateTypeParameter();
2002 if (specType
!= ttp
->specType
)
2005 if (specType
&& !specType
->equals(ttp
->specType
))
2015 /*******************************************
2016 * Match to a particular TemplateParameter.
2019 * tiargs[] actual arguments to template instance
2020 * parameters[] template parameters
2021 * dedtypes[] deduced arguments to template instance
2022 * *psparam set to symbol declared and initialized to dedtypes[i]
2023 * flags 1: don't do 'toHeadMutable()'
2026 MATCH
TemplateTypeParameter::matchArg(Scope
*sc
, Objects
*tiargs
,
2027 int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2028 Declaration
**psparam
, int flags
)
2030 //printf("TemplateTypeParameter::matchArg()\n");
2033 MATCH m
= MATCHexact
;
2036 if (i
< tiargs
->dim
)
2037 oarg
= (Object
*)tiargs
->data
[i
];
2039 { // Get default argument instead
2040 oarg
= defaultArg(loc
, sc
);
2042 { assert(i
< dedtypes
->dim
);
2043 // It might have already been deduced
2044 oarg
= (Object
*)dedtypes
->data
[i
];
2049 flags
|= 1; // already deduced, so don't to toHeadMutable()
2056 //printf("test1 %s %p %p %p\n", oarg->toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
2059 //printf("ta is %s\n", ta->toChars());
2061 t
= (Type
*)dedtypes
->data
[i
];
2065 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
2066 MATCH m2
= ta
->deduceType(sc
, specType
, parameters
, dedtypes
);
2067 if (m2
== MATCHnomatch
)
2068 { //printf("\tfailed deduceType\n");
2074 t
= (Type
*)dedtypes
->data
[i
];
2078 // So that matches with specializations are better
2082 * template Foo(T), Foo!(const int), => ta == int
2084 // if (!(flags & 1))
2085 // ta = ta->toHeadMutable();
2088 { // Must match already deduced type
2092 { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
2100 dedtypes
->data
[i
] = ta
;
2103 *psparam
= new AliasDeclaration(loc
, ident
, t
);
2104 //printf("\tm = %d\n", m);
2109 //printf("\tm = %d\n", MATCHnomatch);
2110 return MATCHnomatch
;
2114 void TemplateTypeParameter::print(Object
*oarg
, Object
*oded
)
2116 fprintf(stderr
, " %s\n", ident
->toChars());
2118 Type
*t
= isType(oarg
);
2119 Type
*ta
= isType(oded
);
2124 fprintf(stderr
, "\tSpecialization: %s\n", specType
->toChars());
2126 fprintf(stderr
, "\tDefault: %s\n", defaultType
->toChars());
2127 fprintf(stderr
, "\tArgument: %s\n", t
? t
->toChars() : "NULL");
2128 fprintf(stderr
, "\tDeduced Type: %s\n", ta
->toChars());
2132 void TemplateTypeParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2134 buf
->writestring(ident
->toChars());
2137 buf
->writestring(" : ");
2138 specType
->toCBuffer(buf
, NULL
, hgs
);
2142 buf
->writestring(" = ");
2143 defaultType
->toCBuffer(buf
, NULL
, hgs
);
2148 void *TemplateTypeParameter::dummyArg()
2154 { // Use this for alias-parameter's too (?)
2155 t
= new TypeIdentifier(loc
, ident
);
2161 Object
*TemplateTypeParameter::specialization()
2167 Object
*TemplateTypeParameter::defaultArg(Loc loc
, Scope
*sc
)
2174 t
= t
->syntaxCopy();
2175 t
= t
->semantic(loc
, sc
);
2180 /* ======================== TemplateThisParameter =========================== */
2185 TemplateThisParameter::TemplateThisParameter(Loc loc
, Identifier
*ident
,
2188 : TemplateTypeParameter(loc
, ident
, specType
, defaultType
)
2192 TemplateThisParameter
*TemplateThisParameter::isTemplateThisParameter()
2197 TemplateParameter
*TemplateThisParameter::syntaxCopy()
2199 TemplateThisParameter
*tp
= new TemplateThisParameter(loc
, ident
, specType
, defaultType
);
2201 tp
->specType
= specType
->syntaxCopy();
2203 tp
->defaultType
= defaultType
->syntaxCopy();
2207 void TemplateThisParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2209 buf
->writestring("this ");
2210 TemplateTypeParameter::toCBuffer(buf
, hgs
);
2214 /* ======================== TemplateAliasParameter ========================== */
2218 Dsymbol
*TemplateAliasParameter::sdummy
= NULL
;
2220 TemplateAliasParameter::TemplateAliasParameter(Loc loc
, Identifier
*ident
, Type
*specAliasT
, Type
*defaultAlias
)
2221 : TemplateParameter(loc
, ident
)
2223 this->ident
= ident
;
2224 this->specAliasT
= specAliasT
;
2225 this->defaultAlias
= defaultAlias
;
2227 this->specAlias
= NULL
;
2230 TemplateAliasParameter
*TemplateAliasParameter::isTemplateAliasParameter()
2235 TemplateParameter
*TemplateAliasParameter::syntaxCopy()
2237 TemplateAliasParameter
*tp
= new TemplateAliasParameter(loc
, ident
, specAliasT
, defaultAlias
);
2239 tp
->specAliasT
= specAliasT
->syntaxCopy();
2241 tp
->defaultAlias
= defaultAlias
->syntaxCopy();
2245 void TemplateAliasParameter::declareParameter(Scope
*sc
)
2247 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2248 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2249 if (!sc
->insert(sparam
))
2250 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2253 void TemplateAliasParameter::semantic(Scope
*sc
)
2257 specAlias
= specAliasT
->toDsymbol(sc
);
2259 error("%s is not a symbol", specAliasT
->toChars());
2261 #if 0 // Don't do semantic() until instantiation
2263 defaultAlias
= defaultAlias
->semantic(loc
, sc
);
2267 int TemplateAliasParameter::overloadMatch(TemplateParameter
*tp
)
2269 TemplateAliasParameter
*tap
= tp
->isTemplateAliasParameter();
2273 if (specAlias
!= tap
->specAlias
)
2283 MATCH
TemplateAliasParameter::matchArg(Scope
*sc
,
2284 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2285 Declaration
**psparam
, int flags
)
2291 //printf("TemplateAliasParameter::matchArg()\n");
2293 if (i
< tiargs
->dim
)
2294 oarg
= (Object
*)tiargs
->data
[i
];
2296 { // Get default argument instead
2297 oarg
= defaultArg(loc
, sc
);
2299 { assert(i
< dedtypes
->dim
);
2300 // It might have already been deduced
2301 oarg
= (Object
*)dedtypes
->data
[i
];
2307 sa
= getDsymbol(oarg
);
2313 if (!sa
|| sa
== sdummy
)
2315 if (sa
!= specAlias
)
2318 else if (dedtypes
->data
[i
])
2319 { // Must match already deduced symbol
2320 Dsymbol
*s
= (Dsymbol
*)dedtypes
->data
[i
];
2325 dedtypes
->data
[i
] = sa
;
2327 *psparam
= new AliasDeclaration(loc
, ident
, sa
);
2332 return MATCHnomatch
;
2336 void TemplateAliasParameter::print(Object
*oarg
, Object
*oded
)
2338 fprintf(stderr
, " %s\n", ident
->toChars());
2340 Dsymbol
*sa
= isDsymbol(oded
);
2343 fprintf(stderr
, "\tArgument alias: %s\n", sa
->toChars());
2346 void TemplateAliasParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2348 buf
->writestring("alias ");
2349 buf
->writestring(ident
->toChars());
2352 buf
->writestring(" : ");
2353 specAliasT
->toCBuffer(buf
, NULL
, hgs
);
2357 buf
->writestring(" = ");
2358 defaultAlias
->toCBuffer(buf
, NULL
, hgs
);
2363 void *TemplateAliasParameter::dummyArg()
2370 sdummy
= new Dsymbol();
2377 Object
*TemplateAliasParameter::specialization()
2383 Object
*TemplateAliasParameter::defaultArg(Loc loc
, Scope
*sc
)
2389 s
= defaultAlias
->toDsymbol(sc
);
2391 error("%s is not a symbol", defaultAlias
->toChars());
2396 /* ======================== TemplateValueParameter ========================== */
2400 Expression
*TemplateValueParameter::edummy
= NULL
;
2402 TemplateValueParameter::TemplateValueParameter(Loc loc
, Identifier
*ident
, Type
*valType
,
2403 Expression
*specValue
, Expression
*defaultValue
)
2404 : TemplateParameter(loc
, ident
)
2406 this->ident
= ident
;
2407 this->valType
= valType
;
2408 this->specValue
= specValue
;
2409 this->defaultValue
= defaultValue
;
2412 TemplateValueParameter
*TemplateValueParameter::isTemplateValueParameter()
2417 TemplateParameter
*TemplateValueParameter::syntaxCopy()
2419 TemplateValueParameter
*tp
=
2420 new TemplateValueParameter(loc
, ident
, valType
, specValue
, defaultValue
);
2421 tp
->valType
= valType
->syntaxCopy();
2423 tp
->specValue
= specValue
->syntaxCopy();
2425 tp
->defaultValue
= defaultValue
->syntaxCopy();
2429 void TemplateValueParameter::declareParameter(Scope
*sc
)
2431 VarDeclaration
*v
= new VarDeclaration(loc
, valType
, ident
, NULL
);
2432 v
->storage_class
= STCtemplateparameter
;
2434 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2438 void TemplateValueParameter::semantic(Scope
*sc
)
2440 sparam
->semantic(sc
);
2441 valType
= valType
->semantic(loc
, sc
);
2442 if (!(valType
->isintegral() || valType
->isfloating() || valType
->isString()) &&
2443 valType
->ty
!= Tident
)
2444 error(loc
, "arithmetic/string type expected for value-parameter, not %s", valType
->toChars());
2447 { Expression
*e
= specValue
;
2449 e
= e
->semantic(sc
);
2450 e
= e
->implicitCastTo(sc
, valType
);
2451 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2452 if (e
->op
== TOKint64
|| e
->op
== TOKfloat64
||
2453 e
->op
== TOKcomplex80
|| e
->op
== TOKnull
|| e
->op
== TOKstring
)
2458 #if 0 // defer semantic analysis to arg match
2460 { Expression
*e
= defaultValue
;
2462 e
= e
->semantic(sc
);
2463 e
= e
->implicitCastTo(sc
, valType
);
2464 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2465 if (e
->op
== TOKint64
)
2472 int TemplateValueParameter::overloadMatch(TemplateParameter
*tp
)
2474 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
2478 if (valType
!= tvp
->valType
)
2481 if (valType
&& !valType
->equals(tvp
->valType
))
2484 if (specValue
!= tvp
->specValue
)
2495 MATCH
TemplateValueParameter::matchArg(Scope
*sc
,
2496 Objects
*tiargs
, int i
, TemplateParameters
*parameters
, Objects
*dedtypes
,
2497 Declaration
**psparam
, int flags
)
2499 //printf("TemplateValueParameter::matchArg()\n");
2502 Declaration
*sparam
;
2503 MATCH m
= MATCHexact
;
2507 if (i
< tiargs
->dim
)
2508 oarg
= (Object
*)tiargs
->data
[i
];
2510 { // Get default argument instead
2511 oarg
= defaultArg(loc
, sc
);
2513 { assert(i
< dedtypes
->dim
);
2514 // It might have already been deduced
2515 oarg
= (Object
*)dedtypes
->data
[i
];
2521 ei
= isExpression(oarg
);
2527 if (ei
&& ei
->op
== TOKvar
)
2528 { // Resolve const variables that we had skipped earlier
2529 ei
= ei
->optimize(WANTvalue
| WANTinterpret
);
2534 if (!ei
|| ei
== edummy
)
2537 Expression
*e
= specValue
;
2539 e
= e
->semantic(sc
);
2540 e
= e
->implicitCastTo(sc
, valType
);
2541 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2542 //e->type = e->type->toHeadMutable();
2544 ei
= ei
->syntaxCopy();
2545 ei
= ei
->semantic(sc
);
2546 ei
= ei
->optimize(WANTvalue
| WANTinterpret
);
2547 //ei->type = ei->type->toHeadMutable();
2548 //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
2549 //printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
2553 else if (dedtypes
->data
[i
])
2554 { // Must match already deduced value
2555 Expression
*e
= (Expression
*)dedtypes
->data
[i
];
2557 if (!ei
|| !ei
->equals(e
))
2561 //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
2562 vt
= valType
->semantic(0, sc
);
2563 //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
2564 //printf("vt = %s\n", vt->toChars());
2567 //ei->type = ei->type->toHeadMutable();
2568 m
= (MATCH
)ei
->implicitConvTo(vt
);
2569 //printf("m: %d\n", m);
2573 dedtypes
->data
[i
] = ei
;
2575 init
= new ExpInitializer(loc
, ei
);
2576 sparam
= new VarDeclaration(loc
, vt
, ident
, init
);
2577 sparam
->storage_class
= STCmanifest
;
2582 //printf("\tno match\n");
2584 return MATCHnomatch
;
2588 void TemplateValueParameter::print(Object
*oarg
, Object
*oded
)
2590 fprintf(stderr
, " %s\n", ident
->toChars());
2592 Expression
*ea
= isExpression(oded
);
2595 fprintf(stderr
, "\tSpecialization: %s\n", specValue
->toChars());
2596 fprintf(stderr
, "\tArgument Value: %s\n", ea
? ea
->toChars() : "NULL");
2600 void TemplateValueParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2602 valType
->toCBuffer(buf
, ident
, hgs
);
2605 buf
->writestring(" : ");
2606 specValue
->toCBuffer(buf
, hgs
);
2610 buf
->writestring(" = ");
2611 defaultValue
->toCBuffer(buf
, hgs
);
2616 void *TemplateValueParameter::dummyArg()
2622 // Create a dummy value
2624 edummy
= valType
->defaultInit();
2631 Object
*TemplateValueParameter::specialization()
2637 Object
*TemplateValueParameter::defaultArg(Loc loc
, Scope
*sc
)
2639 Expression
*e
= defaultValue
;
2642 e
= e
->syntaxCopy();
2643 e
= e
->semantic(sc
);
2645 if (e
->op
== TOKdefault
)
2646 { DefaultInitExp
*de
= (DefaultInitExp
*)e
;
2647 e
= de
->resolve(loc
, sc
);
2654 /* ======================== TemplateTupleParameter ========================== */
2656 // variadic-parameter
2658 TemplateTupleParameter::TemplateTupleParameter(Loc loc
, Identifier
*ident
)
2659 : TemplateParameter(loc
, ident
)
2661 this->ident
= ident
;
2664 TemplateTupleParameter
*TemplateTupleParameter::isTemplateTupleParameter()
2669 TemplateParameter
*TemplateTupleParameter::syntaxCopy()
2671 TemplateTupleParameter
*tp
= new TemplateTupleParameter(loc
, ident
);
2675 void TemplateTupleParameter::declareParameter(Scope
*sc
)
2677 TypeIdentifier
*ti
= new TypeIdentifier(loc
, ident
);
2678 sparam
= new AliasDeclaration(loc
, ident
, ti
);
2679 if (!sc
->insert(sparam
))
2680 error(loc
, "parameter '%s' multiply defined", ident
->toChars());
2683 void TemplateTupleParameter::semantic(Scope
*sc
)
2687 int TemplateTupleParameter::overloadMatch(TemplateParameter
*tp
)
2689 TemplateTupleParameter
*tvp
= tp
->isTemplateTupleParameter();
2700 MATCH
TemplateTupleParameter::matchArg(Scope
*sc
,
2701 Objects
*tiargs
, int i
, TemplateParameters
*parameters
,
2703 Declaration
**psparam
, int flags
)
2705 //printf("TemplateTupleParameter::matchArg()\n");
2707 /* The rest of the actual arguments (tiargs[]) form the match
2708 * for the variadic parameter.
2710 assert(i
+ 1 == dedtypes
->dim
); // must be the last one
2712 if (i
+ 1 == tiargs
->dim
&& isTuple((Object
*)tiargs
->data
[i
]))
2713 ovar
= isTuple((Object
*)tiargs
->data
[i
]);
2717 //printf("ovar = %p\n", ovar);
2718 if (i
< tiargs
->dim
)
2720 //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
2721 ovar
->objects
.setDim(tiargs
->dim
- i
);
2722 for (size_t j
= 0; j
< ovar
->objects
.dim
; j
++)
2723 ovar
->objects
.data
[j
] = tiargs
->data
[i
+ j
];
2726 *psparam
= new TupleDeclaration(loc
, ident
, &ovar
->objects
);
2727 dedtypes
->data
[i
] = (void *)ovar
;
2732 void TemplateTupleParameter::print(Object
*oarg
, Object
*oded
)
2734 printf(" %s... [", ident
->toChars());
2735 Tuple
*v
= isTuple(oded
);
2738 //printf("|%d| ", v->objects.dim);
2739 for (int i
= 0; i
< v
->objects
.dim
; i
++)
2744 Object
*o
= (Object
*)v
->objects
.data
[i
];
2746 Dsymbol
*sa
= isDsymbol(o
);
2748 printf("alias: %s", sa
->toChars());
2750 Type
*ta
= isType(o
);
2752 printf("type: %s", ta
->toChars());
2754 Expression
*ea
= isExpression(o
);
2756 printf("exp: %s", ea
->toChars());
2758 assert(!isTuple(o
)); // no nested Tuple arguments
2764 void TemplateTupleParameter::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2766 buf
->writestring(ident
->toChars());
2767 buf
->writestring("...");
2771 void *TemplateTupleParameter::dummyArg()
2777 Object
*TemplateTupleParameter::specialization()
2783 Object
*TemplateTupleParameter::defaultArg(Loc loc
, Scope
*sc
)
2788 /* ======================== TemplateInstance ================================ */
2790 TemplateInstance::TemplateInstance(Loc loc
, Identifier
*ident
)
2791 : ScopeDsymbol(NULL
)
2794 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident
? ident
->toChars() : "null");
2798 this->tiargs
= NULL
;
2799 this->tempdecl
= NULL
;
2801 this->argsym
= NULL
;
2802 this->aliasdecl
= NULL
;
2803 this->semanticdone
= 0;
2804 this->withsym
= NULL
;
2807 this->objFileModule
= NULL
;
2809 this->havetempdecl
= 0;
2810 this->isnested
= NULL
;
2815 TemplateInstance::TemplateInstance(Loc loc
, TemplateDeclaration
*td
, Objects
*tiargs
)
2816 : ScopeDsymbol(NULL
)
2819 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td
->toChars());
2822 this->name
= td
->ident
;
2823 this->tiargs
= tiargs
;
2824 this->tempdecl
= td
;
2826 this->argsym
= NULL
;
2827 this->aliasdecl
= NULL
;
2828 this->semanticdone
= 0;
2829 this->withsym
= NULL
;
2832 this->objFileModule
= NULL
;
2834 this->havetempdecl
= 1;
2835 this->isnested
= NULL
;
2838 assert((size_t)tempdecl
->scope
> 0x10000);
2842 Objects
*TemplateInstance::arraySyntaxCopy(Objects
*objs
)
2846 { a
= new Objects();
2847 a
->setDim(objs
->dim
);
2848 for (size_t i
= 0; i
< objs
->dim
; i
++)
2850 Type
*ta
= isType((Object
*)objs
->data
[i
]);
2852 a
->data
[i
] = ta
->syntaxCopy();
2855 Expression
*ea
= isExpression((Object
*)objs
->data
[i
]);
2857 a
->data
[i
] = ea
->syntaxCopy();
2864 Dsymbol
*TemplateInstance::syntaxCopy(Dsymbol
*s
)
2866 TemplateInstance
*ti
;
2870 ti
= (TemplateInstance
*)s
;
2872 ti
= new TemplateInstance(loc
, name
);
2874 ti
->tiargs
= arraySyntaxCopy(tiargs
);
2876 ScopeDsymbol::syntaxCopy(ti
);
2882 #include "d-dmd-gcc.h"
2885 void TemplateInstance::semantic(Scope
*sc
)
2891 /* Trying to soldier on rarely generates useful messages
2899 printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
2903 fprintf(stderr, "ti '%s' (%p), belongs in '%s'\n", toChars(), this,
2904 sc->module->toPrettyChars());
2906 fprintf(stderr, " -- really '%s' (%p)\n", inst->toChars(), inst);
2908 fprintf(stderr, " -- doing semantic\n");
2912 if (inst
) // if semantic() was already run
2915 printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst
->toChars(), inst
);
2920 if (semanticdone
!= 0)
2922 error(loc
, "recursive template expansion");
2929 printf("\tdo semantic\n");
2933 assert((size_t)tempdecl
->scope
> 0x10000);
2935 tdtypes
.setDim(tempdecl
->parameters
->dim
);
2936 if (!tempdecl
->matchWithInstance(this, &tdtypes
, 2))
2938 error("incompatible arguments for template instantiation");
2945 // Run semantic on each argument, place results in tiargs[]
2948 tempdecl
= findTemplateDeclaration(sc
);
2950 tempdecl
= findBestMatch(sc
);
2951 if (!tempdecl
|| global
.errors
)
2953 //printf("error return %p, %d\n", tempdecl, global.errors);
2954 return; // error recovery
2960 /* See if there is an existing TemplateInstantiation that already
2961 * implements the typeargs. If so, just refer to that one instead.
2964 for (size_t i
= 0; i
< tempdecl
->instances
.dim
; i
++)
2966 TemplateInstance
*ti
= (TemplateInstance
*)tempdecl
->instances
.data
[i
];
2968 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i
, ti
, ti
->toChars());
2970 assert(tdtypes
.dim
== ti
->tdtypes
.dim
);
2972 // Nesting must match
2973 if (isnested
!= ti
->isnested
)
2976 if (isnested
&& sc
->parent
!= ti
->parent
)
2979 for (size_t j
= 0; j
< tdtypes
.dim
; j
++)
2980 { Object
*o1
= (Object
*)tdtypes
.data
[j
];
2981 Object
*o2
= (Object
*)ti
->tdtypes
.data
[j
];
2982 if (!match(o1
, o2
, tempdecl
, sc
))
2988 parent
= ti
->parent
;
2990 printf("\tit's a match with instance %p\n", inst
);
2998 /* So, we need to implement 'this' instance.
3001 printf("\timplement template instance '%s'\n", toChars());
3003 unsigned errorsave
= global
.errors
;
3005 int tempdecl_instance_idx
= tempdecl
->instances
.dim
;
3006 tempdecl
->instances
.push(this);
3007 parent
= tempdecl
->parent
;
3008 //printf("parent = '%s'\n", parent->kind());
3010 ident
= genIdent(); // need an identifier for name mangling purposes.
3016 //printf("parent = '%s'\n", parent->kind());
3018 // Add 'this' to the enclosing scope's members[] so the semantic routines
3019 // will get called on the instance members
3021 int dosemantic3
= 0;
3026 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3032 /* For "all" and "private" template modes, templates are always
3033 emitted. Problem: This picks up templates that aren't even
3034 needed in the current module. */
3036 if (d_gcc_force_templates())
3038 //fprintf(stderr, "\t0: adding to %s %s\n", sc->scopesym->kind(), sc->scopesym->toChars());
3039 objFileModule
= d_gcc_get_output_module();
3040 a
= objFileModule
->members
;
3045 //if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3046 if (scx
&& scx
->scopesym
&& scx
->scopesym
->members
&& !scx
->scopesym
->isTemplateMixin())
3048 //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3049 a
= scx
->scopesym
->members
;
3052 Dsymbol
* p
= scx
->scopesym
;
3054 TemplateInstance
* i
;
3057 if ( (i
= p
->isTemplateInstance()) ) {
3058 if (i
->objFileModule
) {
3059 objFileModule
= i
->objFileModule
;
3062 } else if ( (m
= p
->isModule()) ) {
3063 objFileModule
= m
; // %% importedFrom ?
3068 // fprintf(stderr, "\t1: adding %s to module %s via %s %s\n", tempdecl->toChars(), objFileModule?objFileModule->toChars():"", sc->scopesym->kind(), sc->scopesym->toChars());
3073 { Module
*m
= sc
->module
->importedFrom
;
3074 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
3076 if (m
->semanticdone
>= 3)
3082 for (int i
= 0; 1; i
++)
3089 if (this == (Dsymbol
*)a
->data
[i
]) // if already in Array
3095 // Copy the syntax trees from the TemplateDeclaration
3096 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
3098 // Create our own scope for the template parameters
3099 Scope
*scope
= tempdecl
->scope
;
3102 error("forward reference to template declaration %s\n", tempdecl
->toChars());
3107 printf("\tcreate scope for template parameters '%s'\n", toChars());
3109 argsym
= new ScopeDsymbol();
3110 argsym
->parent
= scope
->parent
;
3111 scope
= scope
->push(argsym
);
3113 // Declare each template parameter as an alias for the argument type
3114 declareParameters(scope
);
3116 // Add members of template instance to template instance symbol table
3117 // parent = scope->scopesym;
3118 symtab
= new DsymbolTable();
3120 for (int i
= 0; i
< members
->dim
; i
++)
3122 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3124 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i
, s
->toChars(), s
, s
->kind(), this->toChars(), memnum
);
3126 memnum
|= s
->addMember(scope
, this, memnum
);
3129 printf("adding members done\n");
3132 /* See if there is only one member of template instance, and that
3133 * member has the same name as the template instance.
3134 * If so, this template instance becomes an alias for that member.
3136 //printf("members->dim = %d\n", members->dim);
3140 if (Dsymbol::oneMembers(members
, &s
) && s
)
3142 //printf("s->kind = '%s'\n", s->kind());
3144 //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
3145 if (s
->ident
&& s
->ident
->equals(tempdecl
->ident
))
3147 //printf("setting aliasdecl\n");
3148 aliasdecl
= new AliasDeclaration(loc
, s
->ident
, s
);
3153 // Do semantic() analysis on template instance members
3155 printf("\tdo semantic() on template instance members '%s'\n", toChars());
3158 sc2
= scope
->push(this);
3159 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
3160 sc2
->parent
= /*isnested ? sc->parent :*/ this;
3168 for (int i
= 0; i
< members
->dim
; i
++)
3170 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3171 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
3172 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
3174 // s->parent = sc->parent;
3175 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3177 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3178 sc2
->module
->runDeferredSemantic();
3183 __except (__ehfilter(GetExceptionInformation()))
3185 global
.gag
= 0; // ensure error message gets printed
3186 error("recursive expansion");
3192 /* If any of the instantiation members didn't get semantic() run
3193 * on them due to forward references, we cannot run semantic2()
3194 * or semantic3() yet.
3196 for (size_t i
= 0; i
< Module::deferred
.dim
; i
++)
3197 { Dsymbol
*sd
= (Dsymbol
*)Module::deferred
.data
[i
];
3199 if (sd
->parent
== this)
3200 goto Laftersemantic
;
3203 /* The problem is when to parse the initializer for a variable.
3204 * Perhaps VarDeclaration::semantic() should do it like it does
3205 * for initializers inside a function.
3207 // if (sc->parent->isFuncDeclaration())
3209 /* BUG 782: this has problems if the classes this depends on
3210 * are forward referenced. Find a way to defer semantic()
3215 if (sc
->func
|| dosemantic3
)
3225 // Give additional context info if error occurred during instantiation
3226 if (global
.errors
!= errorsave
)
3228 error("error instantiating");
3231 tempdecl
->instances
.remove(tempdecl_instance_idx
);
3235 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3240 void TemplateInstance::semanticTiargs(Scope
*sc
)
3242 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3243 semanticTiargs(loc
, sc
, tiargs
, 0);
3246 /**********************************
3248 * flags 1: replace const variables with their initializers
3251 void TemplateInstance::semanticTiargs(Loc loc
, Scope
*sc
, Objects
*tiargs
, int flags
)
3253 // Run semantic on each argument, place results in tiargs[]
3254 //printf("+TemplateInstance::semanticTiargs()\n");
3257 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3259 Object
*o
= (Object
*)tiargs
->data
[j
];
3260 Type
*ta
= isType(o
);
3261 Expression
*ea
= isExpression(o
);
3262 Dsymbol
*sa
= isDsymbol(o
);
3264 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
3267 //printf("type %s\n", ta->toChars());
3268 // It might really be an Expression or an Alias
3269 ta
->resolve(loc
, sc
, &ea
, &ta
, &sa
);
3272 ea
= ea
->semantic(sc
);
3273 /* This test is to skip substituting a const var with
3274 * its initializer. The problem is the initializer won't
3275 * match with an 'alias' parameter. Instead, do the
3276 * const substitution in TemplateValueParameter::matchArg().
3278 if (ea
->op
!= TOKvar
|| flags
& 1)
3279 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3280 tiargs
->data
[j
] = ea
;
3283 { tiargs
->data
[j
] = sa
;
3284 TupleDeclaration
*d
= sa
->toAlias()->isTupleDeclaration();
3287 size_t dim
= d
->objects
->dim
;
3289 tiargs
->insert(j
, d
->objects
);
3295 if (ta
->ty
== Ttuple
)
3297 TypeTuple
*tt
= (TypeTuple
*)ta
;
3298 size_t dim
= tt
->arguments
->dim
;
3301 { tiargs
->reserve(dim
);
3302 for (size_t i
= 0; i
< dim
; i
++)
3303 { Argument
*arg
= (Argument
*)tt
->arguments
->data
[i
];
3304 tiargs
->insert(j
+ i
, arg
->type
);
3310 tiargs
->data
[j
] = ta
;
3314 assert(global
.errors
);
3315 tiargs
->data
[j
] = Type::terror
;
3321 { assert(global
.errors
);
3322 ea
= new IntegerExp(0);
3325 ea
= ea
->semantic(sc
);
3326 if (ea
->op
!= TOKvar
|| flags
& 1)
3327 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3328 tiargs
->data
[j
] = ea
;
3329 if (ea
->op
== TOKtype
)
3330 tiargs
->data
[j
] = ea
->type
;
3339 //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
3342 printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
3343 for (size_t j
= 0; j
< tiargs
->dim
; j
++)
3345 Object
*o
= (Object
*)tiargs
->data
[j
];
3346 Type
*ta
= isType(o
);
3347 Expression
*ea
= isExpression(o
);
3348 Dsymbol
*sa
= isDsymbol(o
);
3349 Tuple
*va
= isTuple(o
);
3351 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j
, ta
, ea
, sa
, va
);
3356 /**********************************************
3357 * Find template declaration corresponding to template instance.
3360 TemplateDeclaration
*TemplateInstance::findTemplateDeclaration(Scope
*sc
)
3362 //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
3367 * figure out which TemplateDeclaration foo refers to.
3375 s
= sc
->search(loc
, id
, &scopesym
);
3377 { error("identifier '%s' is not defined", id
->toChars());
3381 printf("It's an instance of '%s' kind '%s'\n", s
->toChars(), s
->kind());
3383 printf("s->parent = '%s'\n", s
->parent
->toChars());
3385 withsym
= scopesym
->isWithScopeSymbol();
3387 /* We might have found an alias within a template when
3388 * we really want the template.
3390 TemplateInstance
*ti
;
3392 (ti
= s
->parent
->isTemplateInstance()) != NULL
)
3396 ti
->toAlias()->ident
== id
)
3400 /* This is so that one can refer to the enclosing
3401 * template, even if it has the same name as a member
3402 * of the template, if it has a !(arguments)
3404 tempdecl
= ti
->tempdecl
;
3405 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3406 tempdecl
= tempdecl
->overroot
; // then get the start
3413 /* It should be a TemplateDeclaration, not some other symbol
3415 tempdecl
= s
->isTemplateDeclaration();
3418 if (!s
->parent
&& global
.errors
)
3420 if (!s
->parent
&& s
->getType())
3421 { Dsymbol
*s2
= s
->getType()->toDsymbol(sc
);
3424 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3430 //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
3432 //assert(s->parent);
3433 TemplateInstance
*ti
= s
->parent
? s
->parent
->isTemplateInstance() : NULL
;
3436 ti
->toAlias()->ident
== id
)
3440 /* This is so that one can refer to the enclosing
3441 * template, even if it has the same name as a member
3442 * of the template, if it has a !(arguments)
3444 tempdecl
= ti
->tempdecl
;
3445 if (tempdecl
->overroot
) // if not start of overloaded list of TemplateDeclaration's
3446 tempdecl
= tempdecl
->overroot
; // then get the start
3450 error("%s is not a template declaration, it is a %s", id
->toChars(), s
->kind());
3456 assert(tempdecl
->isTemplateDeclaration());
3460 TemplateDeclaration
*TemplateInstance::findBestMatch(Scope
*sc
)
3462 /* Since there can be multiple TemplateDeclaration's with the same
3463 * name, look for the best match.
3465 TemplateDeclaration
*td_ambig
= NULL
;
3466 TemplateDeclaration
*td_best
= NULL
;
3467 MATCH m_best
= MATCHnomatch
;
3471 printf("TemplateInstance::findBestMatch()\n");
3473 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
3477 //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
3479 // If more arguments than parameters,
3480 // then this is no match.
3481 if (td
->parameters
->dim
< tiargs
->dim
)
3483 if (!td
->isVariadic())
3487 dedtypes
.setDim(td
->parameters
->dim
);
3491 error("forward reference to template declaration %s", td
->toChars());
3494 m
= td
->matchWithInstance(this, &dedtypes
, 0);
3495 //printf("m = %d\n", m);
3496 if (!m
) // no match at all
3509 // Disambiguate by picking the most specialized TemplateDeclaration
3510 MATCH c1
= td
->leastAsSpecialized(td_best
);
3511 MATCH c2
= td_best
->leastAsSpecialized(td
);
3512 //printf("c1 = %d, c2 = %d\n", c1, c2);
3522 Lambig
: // td_best and td are ambiguous
3526 Ltd_best
: // td_best is the best match so far
3530 Ltd
: // td is the new best match
3534 tdtypes
.setDim(dedtypes
.dim
);
3535 memcpy(tdtypes
.data
, dedtypes
.data
, tdtypes
.dim
* sizeof(void *));
3541 error("%s does not match any template declaration", toChars());
3546 error("%s matches more than one template declaration, %s and %s",
3547 toChars(), td_best
->toChars(), td_ambig
->toChars());
3550 /* The best match is td_best
3555 /* Cast any value arguments to be same type as value parameter
3557 for (size_t i
= 0; i
< tiargs
->dim
; i
++)
3558 { Object
*o
= (Object
*)tiargs
->data
[i
];
3559 Expression
*ea
= isExpression(o
); // value argument
3560 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3562 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3566 ea
= ea
->castTo(tvp
->valType
);
3567 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3568 tiargs
->data
[i
] = (Object
*)ea
;
3574 printf("\tIt's a match with template declaration '%s'\n", tempdecl
->toChars());
3580 /*****************************************
3581 * Determines if a TemplateInstance will need a nested
3582 * generation of the TemplateDeclaration.
3585 int TemplateInstance::isNested(Objects
*args
)
3587 //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars());
3589 /* A nested instance happens when an argument references a local
3590 * symbol that is on the stack.
3592 for (size_t i
= 0; i
< args
->dim
; i
++)
3593 { Object
*o
= (Object
*)args
->data
[i
];
3594 Expression
*ea
= isExpression(o
);
3595 Dsymbol
*sa
= isDsymbol(o
);
3596 Tuple
*va
= isTuple(o
);
3599 if (ea
->op
== TOKvar
)
3601 sa
= ((VarExp
*)ea
)->var
;
3604 if (ea
->op
== TOKfunction
)
3606 sa
= ((FuncExp
*)ea
)->fd
;
3613 Declaration
*d
= sa
->isDeclaration();
3614 if (d
&& !d
->isDataseg() &&
3616 !(d
->storage_class
& STCmanifest
) &&
3618 (!d
->isFuncDeclaration() || d
->isFuncDeclaration()->isNested()) &&
3621 // if module level template
3622 if (tempdecl
->toParent()->isModule())
3623 { Dsymbol
*dparent
= d
->toParent();
3626 else if (isnested
!= dparent
)
3628 /* Select the more deeply nested of the two.
3629 * Error if one is not nested inside the other.
3631 for (Dsymbol
*p
= isnested
; p
; p
= p
->parent
)
3634 goto L1
; // isnested is most nested
3636 for (Dsymbol
*p
= dparent
; 1; p
= p
->parent
)
3639 { isnested
= dparent
;
3640 goto L1
; // dparent is most nested
3643 error("is nested in both %s and %s", isnested
->toChars(), dparent
->toChars());
3646 //printf("\tnested inside %s\n", isnested->toChars());
3650 error("cannot use local '%s' as template parameter", d
->toChars());
3655 nested
|= isNested(&va
->objects
);
3661 /****************************************
3662 * This instance needs an identifier for name mangling purposes.
3663 * Create one by taking the template declaration name and adding
3664 * the type signature for it.
3667 Identifier
*TemplateInstance::genIdent()
3672 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
3673 id
= tempdecl
->ident
->toChars();
3674 buf
.printf("__T%"PRIuSIZE
"%s", strlen(id
), id
);
3676 for (int i
= 0; i
< args
->dim
; i
++)
3677 { Object
*o
= (Object
*)args
->data
[i
];
3678 Type
*ta
= isType(o
);
3679 Expression
*ea
= isExpression(o
);
3680 Dsymbol
*sa
= isDsymbol(o
);
3681 Tuple
*va
= isTuple(o
);
3682 //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
3687 buf
.writestring(ta
->deco
);
3691 printf("ta = %d, %s\n", ta
->ty
, ta
->toChars());
3693 assert(global
.errors
);
3700 ea
= ea
->optimize(WANTvalue
| WANTinterpret
);
3701 if (ea
->op
== TOKvar
)
3703 sa
= ((VarExp
*)ea
)->var
;
3707 if (ea
->op
== TOKfunction
)
3709 sa
= ((FuncExp
*)ea
)->fd
;
3714 if (ea
->op
== TOKtuple
)
3715 { ea
->error("tuple is not a valid template value argument");
3719 /* Use deco that matches what it would be for a function parameter
3721 //buf.writestring(ea->type->toHeadMutable()->deco);
3722 buf
.writestring(ea
->type
->deco
);
3724 // Use type of parameter, not type of argument
3725 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3727 TemplateValueParameter
*tvp
= tp
->isTemplateValueParameter();
3729 buf
.writestring(tvp
->valType
->deco
);
3731 ea
->toMangleBuffer(&buf
);
3737 Declaration
*d
= sa
->isDeclaration();
3738 if (d
&& !d
->type
->deco
)
3739 error("forward reference of %s", d
->toChars());
3742 char *p
= sa
->mangle();
3743 buf
.printf("%"PRIuSIZE
"%s", strlen(p
), p
);
3748 assert(i
+ 1 == args
->dim
); // must be last one
3749 args
= &va
->objects
;
3758 return new Identifier(id
, TOKidentifier
);
3762 /****************************************************
3763 * Declare parameters of template instance, initialize them with the
3764 * template instance arguments.
3767 void TemplateInstance::declareParameters(Scope
*scope
)
3769 //printf("TemplateInstance::declareParameters()\n");
3770 for (int i
= 0; i
< tdtypes
.dim
; i
++)
3772 TemplateParameter
*tp
= (TemplateParameter
*)tempdecl
->parameters
->data
[i
];
3773 //Object *o = (Object *)tiargs->data[i];
3774 Object
*o
= (Object
*)tdtypes
.data
[i
];
3776 //printf("\ttdtypes[%d] = %p\n", i, o);
3777 tempdecl
->declareParameter(scope
, tp
, o
);
3782 void TemplateInstance::semantic2(Scope
*sc
)
3785 if (semanticdone
>= 2)
3789 printf("+TemplateInstance::semantic2('%s')\n", toChars());
3791 if (!errors
&& members
)
3793 sc
= tempdecl
->scope
;
3795 sc
= sc
->push(argsym
);
3796 sc
= sc
->push(this);
3797 for (i
= 0; i
< members
->dim
; i
++)
3799 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3801 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
3809 printf("-TemplateInstance::semantic2('%s')\n", toChars());
3813 void TemplateInstance::semantic3(Scope
*sc
)
3816 printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone
);
3818 //if (toChars()[0] == 'D') *(char*)0=0;
3819 if (semanticdone
>= 3)
3822 if (!errors
&& members
)
3824 sc
= tempdecl
->scope
;
3825 sc
= sc
->push(argsym
);
3826 sc
= sc
->push(this);
3827 for (int i
= 0; i
< members
->dim
; i
++)
3829 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3837 void TemplateInstance::toObjFile(int multiobj
)
3840 printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
3842 if (!errors
&& members
)
3845 // Append to list of object files to be written later
3849 for (int i
= 0; i
< members
->dim
; i
++)
3851 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3852 s
->toObjFile(multiobj
);
3858 void TemplateInstance::inlineScan()
3861 printf("TemplateInstance::inlineScan('%s')\n", toChars());
3863 if (!errors
&& members
)
3865 for (int i
= 0; i
< members
->dim
; i
++)
3867 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
3873 void TemplateInstance::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3877 Identifier
*id
= name
;
3878 buf
->writestring(id
->toChars());
3879 buf
->writestring("!(");
3881 buf
->writestring("...");
3885 Objects
*args
= tiargs
;
3886 for (i
= 0; i
< args
->dim
; i
++)
3889 buf
->writeByte(',');
3890 Object
*oarg
= (Object
*)args
->data
[i
];
3891 ObjectToCBuffer(buf
, hgs
, oarg
);
3895 buf
->writeByte(')');
3899 Dsymbol
*TemplateInstance::toAlias()
3902 printf("TemplateInstance::toAlias()\n");
3905 { error("cannot resolve forward reference");
3910 return inst
->toAlias();
3913 return aliasdecl
->toAlias();
3918 AliasDeclaration
*TemplateInstance::isAliasDeclaration()
3923 char *TemplateInstance::kind()
3925 return "template instance";
3928 int TemplateInstance::oneMember(Dsymbol
**ps
)
3934 char *TemplateInstance::toChars()
3940 toCBuffer(&buf
, &hgs
);
3946 /* ======================== TemplateMixin ================================ */
3948 TemplateMixin::TemplateMixin(Loc loc
, Identifier
*ident
, Type
*tqual
,
3949 Array
*idents
, Objects
*tiargs
)
3950 : TemplateInstance(loc
, (Identifier
*)idents
->data
[idents
->dim
- 1])
3952 //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
3953 this->ident
= ident
;
3954 this->tqual
= tqual
;
3955 this->idents
= idents
;
3956 this->tiargs
= tiargs
? tiargs
: new Objects();
3960 Dsymbol
*TemplateMixin::syntaxCopy(Dsymbol
*s
)
3961 { TemplateMixin
*tm
;
3963 Array
*ids
= new Array();
3964 ids
->setDim(idents
->dim
);
3965 for (int i
= 0; i
< idents
->dim
; i
++)
3966 { // Matches TypeQualified::syntaxCopyHelper()
3967 Identifier
*id
= (Identifier
*)idents
->data
[i
];
3968 if (id
->dyncast() == DYNCAST_DSYMBOL
)
3970 TemplateInstance
*ti
= (TemplateInstance
*)id
;
3972 ti
= (TemplateInstance
*)ti
->syntaxCopy(NULL
);
3973 id
= (Identifier
*)ti
;
3978 tm
= new TemplateMixin(loc
, ident
,
3979 (Type
*)(tqual
? tqual
->syntaxCopy() : NULL
),
3981 TemplateInstance::syntaxCopy(tm
);
3985 void TemplateMixin::semantic(Scope
*sc
)
3988 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
3992 // This for when a class/struct contains mixin members, and
3993 // is done over because of forward references
3994 (!parent
|| !toParent()->isAggregateDeclaration()))
3997 printf("\tsemantic done\n");
4004 printf("\tdo semantic\n");
4010 scx
= scope
; // save so we don't make redundant copies
4014 // Follow qualifications to find the TemplateDeclaration
4021 { s
= tqual
->toDsymbol(sc
);
4027 id
= (Identifier
*)idents
->data
[0];
4028 switch (id
->dyncast())
4030 case DYNCAST_IDENTIFIER
:
4031 s
= sc
->search(loc
, id
, NULL
);
4034 case DYNCAST_DSYMBOL
:
4036 TemplateInstance
*ti
= (TemplateInstance
*)id
;
4046 for (; i
< idents
->dim
; i
++)
4050 id
= (Identifier
*)idents
->data
[i
];
4051 s
= s
->searchX(loc
, sc
, id
);
4055 error("is not defined");
4059 tempdecl
= s
->toAlias()->isTemplateDeclaration();
4062 error("%s isn't a template", s
->toChars());
4068 // Look for forward reference
4070 for (TemplateDeclaration
*td
= tempdecl
; td
; td
= td
->overnext
)
4074 /* Cannot handle forward references if mixin is a struct member,
4075 * because addField must happen during struct's semantic, not
4076 * during the mixin semantic.
4077 * runDeferred will re-run mixin's semantic outside of the struct's
4081 AggregateDeclaration
*ad
= toParent()->isAggregateDeclaration();
4086 // Forward reference
4087 //printf("forward reference - deferring\n");
4088 scope
= scx
? scx
: new Scope(*sc
);
4090 scope
->module
->addDeferredSemantic(this);
4096 // Run semantic on each argument, place results in tiargs[]
4099 tempdecl
= findBestMatch(sc
);
4102 return; // error recovery
4109 parent
= sc
->parent
;
4111 /* Detect recursive mixin instantiations.
4113 for (Dsymbol
*s
= parent
; s
; s
= s
->parent
)
4115 //printf("\ts = '%s'\n", s->toChars());
4116 TemplateMixin
*tm
= s
->isTemplateMixin();
4117 if (!tm
|| tempdecl
!= tm
->tempdecl
)
4120 for (int i
= 0; i
< tiargs
->dim
; i
++)
4121 { Object
*o
= (Object
*)tiargs
->data
[i
];
4122 Type
*ta
= isType(o
);
4123 Expression
*ea
= isExpression(o
);
4124 Dsymbol
*sa
= isDsymbol(o
);
4125 Object
*tmo
= (Object
*)tm
->tiargs
->data
[i
];
4128 Type
*tmta
= isType(tmo
);
4131 if (!ta
->equals(tmta
))
4135 { Expression
*tme
= isExpression(tmo
);
4136 if (!tme
|| !ea
->equals(tme
))
4141 Dsymbol
*tmsa
= isDsymbol(tmo
);
4148 error("recursive mixin instantiation");
4155 // Copy the syntax trees from the TemplateDeclaration
4156 members
= Dsymbol::arraySyntaxCopy(tempdecl
->members
);
4160 symtab
= new DsymbolTable();
4162 for (Scope
*sce
= sc
; 1; sce
= sce
->enclosing
)
4164 ScopeDsymbol
*sds
= (ScopeDsymbol
*)sce
->scopesym
;
4167 sds
->importScope(this, PROTpublic
);
4173 printf("\tcreate scope for template parameters '%s'\n", toChars());
4176 scy
= sc
->push(this);
4179 argsym
= new ScopeDsymbol();
4180 argsym
->parent
= scy
->parent
;
4181 Scope
*scope
= scy
->push(argsym
);
4183 unsigned errorsave
= global
.errors
;
4185 // Declare each template parameter as an alias for the argument type
4186 declareParameters(scope
);
4188 // Add members to enclosing scope, as well as this scope
4189 for (unsigned i
= 0; i
< members
->dim
; i
++)
4192 s
= (Dsymbol
*)members
->data
[i
];
4193 s
->addMember(scope
, this, i
);
4195 //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
4196 //printf("s->parent = %s\n", s->parent->toChars());
4199 // Do semantic() analysis on template instance members
4201 printf("\tdo semantic() on template instance members '%s'\n", toChars());
4204 sc2
= scope
->push(this);
4205 sc2
->offset
= sc
->offset
;
4206 for (int i
= 0; i
< members
->dim
; i
++)
4208 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4211 sc
->offset
= sc2
->offset
;
4213 /* The problem is when to parse the initializer for a variable.
4214 * Perhaps VarDeclaration::semantic() should do it like it does
4215 * for initializers inside a function.
4217 // if (sc->parent->isFuncDeclaration())
4226 // Give additional context info if error occurred during instantiation
4227 if (global
.errors
!= errorsave
)
4229 error("error instantiating");
4236 // if (!isAnonymous())
4241 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
4245 void TemplateMixin::semantic2(Scope
*sc
)
4248 if (semanticdone
>= 2)
4252 printf("+TemplateMixin::semantic2('%s')\n", toChars());
4257 sc
= sc
->push(argsym
);
4258 sc
= sc
->push(this);
4259 for (i
= 0; i
< members
->dim
; i
++)
4261 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4263 printf("\tmember '%s', kind = '%s'\n", s
->toChars(), s
->kind());
4271 printf("-TemplateMixin::semantic2('%s')\n", toChars());
4275 void TemplateMixin::semantic3(Scope
*sc
)
4278 if (semanticdone
>= 3)
4282 printf("TemplateMixin::semantic3('%s')\n", toChars());
4286 sc
= sc
->push(argsym
);
4287 sc
= sc
->push(this);
4288 for (i
= 0; i
< members
->dim
; i
++)
4290 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4298 void TemplateMixin::inlineScan()
4300 TemplateInstance::inlineScan();
4303 char *TemplateMixin::kind()
4308 int TemplateMixin::oneMember(Dsymbol
**ps
)
4310 return Dsymbol::oneMember(ps
);
4313 int TemplateMixin::hasPointers()
4315 //printf("TemplateMixin::hasPointers() %s\n", toChars());
4316 for (size_t i
= 0; i
< members
->dim
; i
++)
4318 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
4319 //printf(" s = %s %s\n", s->kind(), s->toChars());
4320 if (s
->hasPointers())
4328 char *TemplateMixin::toChars()
4334 TemplateInstance::toCBuffer(&buf
, &hgs
);
4340 void TemplateMixin::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4342 buf
->writestring("mixin ");
4344 for (i
= 0; i
< idents
->dim
; i
++)
4345 { Identifier
*id
= (Identifier
*)idents
->data
[i
];
4348 buf
->writeByte('.');
4349 buf
->writestring(id
->toChars());
4351 buf
->writestring("!(");
4354 for (i
= 0; i
< tiargs
->dim
; i
++)
4356 buf
->writebyte(',');
4357 Object
*oarg
= (Object
*)tiargs
->data
[i
];
4358 Type
*t
= isType(oarg
);
4359 Expression
*e
= isExpression(oarg
);
4360 Dsymbol
*s
= isDsymbol(oarg
);
4362 t
->toCBuffer(buf
, NULL
, hgs
);
4364 e
->toCBuffer(buf
, hgs
);
4367 char *p
= s
->ident
? s
->ident
->toChars() : s
->toChars();
4368 buf
->writestring(p
);
4372 buf
->writestring("NULL");
4380 buf
->writebyte(')');
4381 buf
->writebyte(';');
4386 void TemplateMixin::toObjFile(int multiobj
)
4388 //printf("TemplateMixin::toObjFile('%s')\n", toChars());
4389 TemplateInstance::toObjFile(multiobj
);