145
|
1
|
|
2 /* Compiler implementation of the D programming language
|
|
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
|
|
4 * written by Walter Bright
|
|
5 * http://www.digitalmars.com
|
|
6 * Distributed under the Boost Software License, Version 1.0.
|
|
7 * http://www.boost.org/LICENSE_1_0.txt
|
|
8 * https://github.com/dlang/dmd/blob/master/src/dmd/template.h
|
|
9 */
|
|
10
|
|
11 #pragma once
|
|
12
|
|
13 #include "root/root.h"
|
|
14 #include "arraytypes.h"
|
|
15 #include "dsymbol.h"
|
|
16
|
|
17
|
|
18 struct OutBuffer;
|
|
19 class Identifier;
|
|
20 class TemplateInstance;
|
|
21 class TemplateParameter;
|
|
22 class TemplateTypeParameter;
|
|
23 class TemplateThisParameter;
|
|
24 class TemplateValueParameter;
|
|
25 class TemplateAliasParameter;
|
|
26 class TemplateTupleParameter;
|
|
27 class Type;
|
|
28 class TypeQualified;
|
|
29 class TypeTypeof;
|
|
30 struct Scope;
|
|
31 class Expression;
|
|
32 class AliasDeclaration;
|
|
33 class FuncDeclaration;
|
|
34 class Parameter;
|
|
35 enum MATCH;
|
|
36 enum PASS;
|
|
37
|
|
38 class Tuple : public RootObject
|
|
39 {
|
|
40 public:
|
|
41 Objects objects;
|
|
42
|
|
43 // kludge for template.isType()
|
|
44 int dyncast() const { return DYNCAST_TUPLE; }
|
|
45
|
|
46 const char *toChars() { return objects.toChars(); }
|
|
47 };
|
|
48
|
|
49 struct TemplatePrevious
|
|
50 {
|
|
51 TemplatePrevious *prev;
|
|
52 Scope *sc;
|
|
53 Objects *dedargs;
|
|
54 };
|
|
55
|
|
56 class TemplateDeclaration : public ScopeDsymbol
|
|
57 {
|
|
58 public:
|
|
59 TemplateParameters *parameters; // array of TemplateParameter's
|
|
60
|
|
61 TemplateParameters *origParameters; // originals for Ddoc
|
|
62 Expression *constraint;
|
|
63
|
|
64 // Hash table to look up TemplateInstance's of this TemplateDeclaration
|
|
65 void *instances;
|
|
66
|
|
67 TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
|
68 TemplateDeclaration *overroot; // first in overnext list
|
|
69 FuncDeclaration *funcroot; // first function in unified overload list
|
|
70
|
|
71 Dsymbol *onemember; // if !=NULL then one member of this template
|
|
72
|
|
73 bool literal; // this template declaration is a literal
|
|
74 bool ismixin; // template declaration is only to be used as a mixin
|
|
75 bool isstatic; // this is static template declaration
|
|
76 Prot protection;
|
|
77
|
|
78 TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack
|
|
79
|
|
80 TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
|
81 Expression *constraint, Dsymbols *decldefs, bool ismixin = false, bool literal = false);
|
|
82 Dsymbol *syntaxCopy(Dsymbol *);
|
|
83 void semantic(Scope *sc);
|
|
84 bool overloadInsert(Dsymbol *s);
|
|
85 bool hasStaticCtorOrDtor();
|
|
86 const char *kind() const;
|
|
87 const char *toChars();
|
|
88
|
|
89 Prot prot();
|
|
90
|
|
91 bool evaluateConstraint(TemplateInstance *ti, Scope *sc, Scope *paramscope, Objects *dedtypes, FuncDeclaration *fd);
|
|
92
|
|
93 MATCH matchWithInstance(Scope *sc, TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag);
|
|
94 MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs);
|
|
95
|
|
96 MATCH deduceFunctionTemplateMatch(TemplateInstance *ti, Scope *sc, FuncDeclaration *&fd, Type *tthis, Expressions *fargs);
|
|
97 RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o);
|
|
98 FuncDeclaration *doHeaderInstantiation(TemplateInstance *ti, Scope *sc, FuncDeclaration *fd, Type *tthis, Expressions *fargs);
|
|
99 TemplateInstance *findExistingInstance(TemplateInstance *tithis, Expressions *fargs);
|
|
100 TemplateInstance *addInstance(TemplateInstance *ti);
|
|
101 void removeInstance(TemplateInstance *handle);
|
|
102
|
|
103 TemplateDeclaration *isTemplateDeclaration() { return this; }
|
|
104
|
|
105 TemplateTupleParameter *isVariadic();
|
|
106 bool isOverloadable();
|
|
107
|
|
108 void accept(Visitor *v) { v->visit(this); }
|
|
109 };
|
|
110
|
|
111 /* For type-parameter:
|
|
112 * template Foo(ident) // specType is set to NULL
|
|
113 * template Foo(ident : specType)
|
|
114 * For value-parameter:
|
|
115 * template Foo(valType ident) // specValue is set to NULL
|
|
116 * template Foo(valType ident : specValue)
|
|
117 * For alias-parameter:
|
|
118 * template Foo(alias ident)
|
|
119 * For this-parameter:
|
|
120 * template Foo(this ident)
|
|
121 */
|
|
122 class TemplateParameter
|
|
123 {
|
|
124 public:
|
|
125 Loc loc;
|
|
126 Identifier *ident;
|
|
127
|
|
128 /* True if this is a part of precedent parameter specialization pattern.
|
|
129 *
|
|
130 * template A(T : X!TL, alias X, TL...) {}
|
|
131 * // X and TL are dependent template parameter
|
|
132 *
|
|
133 * A dependent template parameter should return MATCHexact in matchArg()
|
|
134 * to respect the match level of the corresponding precedent parameter.
|
|
135 */
|
|
136 bool dependent;
|
|
137
|
|
138 TemplateParameter(Loc loc, Identifier *ident);
|
|
139
|
|
140 virtual TemplateTypeParameter *isTemplateTypeParameter();
|
|
141 virtual TemplateValueParameter *isTemplateValueParameter();
|
|
142 virtual TemplateAliasParameter *isTemplateAliasParameter();
|
|
143 virtual TemplateThisParameter *isTemplateThisParameter();
|
|
144 virtual TemplateTupleParameter *isTemplateTupleParameter();
|
|
145
|
|
146 virtual TemplateParameter *syntaxCopy() = 0;
|
|
147 virtual bool declareParameter(Scope *sc) = 0;
|
|
148 virtual bool semantic(Scope *sc, TemplateParameters *parameters) = 0;
|
|
149 virtual void print(RootObject *oarg, RootObject *oded) = 0;
|
|
150 virtual RootObject *specialization() = 0;
|
|
151 virtual RootObject *defaultArg(Loc instLoc, Scope *sc) = 0;
|
|
152 virtual bool hasDefaultArg() = 0;
|
|
153
|
|
154 /* Match actual argument against parameter.
|
|
155 */
|
|
156 virtual MATCH matchArg(Loc instLoc, Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
|
157 virtual MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0;
|
|
158
|
|
159 /* Create dummy argument based on parameter.
|
|
160 */
|
|
161 virtual void *dummyArg() = 0;
|
|
162 virtual void accept(Visitor *v) { v->visit(this); }
|
|
163 };
|
|
164
|
|
165 /* Syntax:
|
|
166 * ident : specType = defaultType
|
|
167 */
|
|
168 class TemplateTypeParameter : public TemplateParameter
|
|
169 {
|
|
170 using TemplateParameter::matchArg;
|
|
171 public:
|
|
172 Type *specType; // type parameter: if !=NULL, this is the type specialization
|
|
173 Type *defaultType;
|
|
174
|
|
175 static Type *tdummy;
|
|
176
|
|
177 TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
|
178
|
|
179 TemplateTypeParameter *isTemplateTypeParameter();
|
|
180 TemplateParameter *syntaxCopy();
|
|
181 bool declareParameter(Scope *sc);
|
|
182 bool semantic(Scope *sc, TemplateParameters *parameters);
|
|
183 void print(RootObject *oarg, RootObject *oded);
|
|
184 RootObject *specialization();
|
|
185 RootObject *defaultArg(Loc instLoc, Scope *sc);
|
|
186 bool hasDefaultArg();
|
|
187 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
|
188 void *dummyArg();
|
|
189 void accept(Visitor *v) { v->visit(this); }
|
|
190 };
|
|
191
|
|
192 /* Syntax:
|
|
193 * this ident : specType = defaultType
|
|
194 */
|
|
195 class TemplateThisParameter : public TemplateTypeParameter
|
|
196 {
|
|
197 public:
|
|
198 TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
|
|
199
|
|
200 TemplateThisParameter *isTemplateThisParameter();
|
|
201 TemplateParameter *syntaxCopy();
|
|
202 void accept(Visitor *v) { v->visit(this); }
|
|
203 };
|
|
204
|
|
205 /* Syntax:
|
|
206 * valType ident : specValue = defaultValue
|
|
207 */
|
|
208 class TemplateValueParameter : public TemplateParameter
|
|
209 {
|
|
210 using TemplateParameter::matchArg;
|
|
211 public:
|
|
212 Type *valType;
|
|
213 Expression *specValue;
|
|
214 Expression *defaultValue;
|
|
215
|
|
216 static AA *edummies;
|
|
217
|
|
218 TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
|
|
219
|
|
220 TemplateValueParameter *isTemplateValueParameter();
|
|
221 TemplateParameter *syntaxCopy();
|
|
222 bool declareParameter(Scope *sc);
|
|
223 bool semantic(Scope *sc, TemplateParameters *parameters);
|
|
224 void print(RootObject *oarg, RootObject *oded);
|
|
225 RootObject *specialization();
|
|
226 RootObject *defaultArg(Loc instLoc, Scope *sc);
|
|
227 bool hasDefaultArg();
|
|
228 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
|
229 void *dummyArg();
|
|
230 void accept(Visitor *v) { v->visit(this); }
|
|
231 };
|
|
232
|
|
233 /* Syntax:
|
|
234 * specType ident : specAlias = defaultAlias
|
|
235 */
|
|
236 class TemplateAliasParameter : public TemplateParameter
|
|
237 {
|
|
238 using TemplateParameter::matchArg;
|
|
239 public:
|
|
240 Type *specType;
|
|
241 RootObject *specAlias;
|
|
242 RootObject *defaultAlias;
|
|
243
|
|
244 static Dsymbol *sdummy;
|
|
245
|
|
246 TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, RootObject *specAlias, RootObject *defaultAlias);
|
|
247
|
|
248 TemplateAliasParameter *isTemplateAliasParameter();
|
|
249 TemplateParameter *syntaxCopy();
|
|
250 bool declareParameter(Scope *sc);
|
|
251 bool semantic(Scope *sc, TemplateParameters *parameters);
|
|
252 void print(RootObject *oarg, RootObject *oded);
|
|
253 RootObject *specialization();
|
|
254 RootObject *defaultArg(Loc instLoc, Scope *sc);
|
|
255 bool hasDefaultArg();
|
|
256 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
|
257 void *dummyArg();
|
|
258 void accept(Visitor *v) { v->visit(this); }
|
|
259 };
|
|
260
|
|
261 /* Syntax:
|
|
262 * ident ...
|
|
263 */
|
|
264 class TemplateTupleParameter : public TemplateParameter
|
|
265 {
|
|
266 public:
|
|
267 TemplateTupleParameter(Loc loc, Identifier *ident);
|
|
268
|
|
269 TemplateTupleParameter *isTemplateTupleParameter();
|
|
270 TemplateParameter *syntaxCopy();
|
|
271 bool declareParameter(Scope *sc);
|
|
272 bool semantic(Scope *sc, TemplateParameters *parameters);
|
|
273 void print(RootObject *oarg, RootObject *oded);
|
|
274 RootObject *specialization();
|
|
275 RootObject *defaultArg(Loc instLoc, Scope *sc);
|
|
276 bool hasDefaultArg();
|
|
277 MATCH matchArg(Loc loc, Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
|
278 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
|
279 void *dummyArg();
|
|
280 void accept(Visitor *v) { v->visit(this); }
|
|
281 };
|
|
282
|
|
283 /* Given:
|
|
284 * foo!(args) =>
|
|
285 * name = foo
|
|
286 * tiargs = args
|
|
287 */
|
|
288 class TemplateInstance : public ScopeDsymbol
|
|
289 {
|
|
290 public:
|
|
291 Identifier *name;
|
|
292
|
|
293 // Array of Types/Expressions of template
|
|
294 // instance arguments [int*, char, 10*10]
|
|
295 Objects *tiargs;
|
|
296
|
|
297 // Array of Types/Expressions corresponding
|
|
298 // to TemplateDeclaration.parameters
|
|
299 // [int, char, 100]
|
|
300 Objects tdtypes;
|
|
301
|
|
302 Dsymbol *tempdecl; // referenced by foo.bar.abc
|
|
303 Dsymbol *enclosing; // if referencing local symbols, this is the context
|
|
304 Dsymbol *aliasdecl; // !=NULL if instance is an alias for its sole member
|
|
305 TemplateInstance *inst; // refer to existing instance
|
|
306 ScopeDsymbol *argsym; // argument symbol table
|
|
307 int inuse; // for recursive expansion detection
|
|
308 int nest; // for recursive pretty printing detection
|
|
309 bool semantictiargsdone; // has semanticTiargs() been done?
|
|
310 bool havetempdecl; // if used second constructor
|
|
311 bool gagged; // if the instantiation is done with error gagging
|
|
312 hash_t hash; // cached result of toHash()
|
|
313 Expressions *fargs; // for function template, these are the function arguments
|
|
314
|
|
315 TemplateInstances* deferred;
|
|
316
|
|
317 Module *memberOf; // if !null, then this TemplateInstance appears in memberOf.members[]
|
|
318
|
|
319 // Used to determine the instance needs code generation.
|
|
320 // Note that these are inaccurate until semantic analysis phase completed.
|
|
321 TemplateInstance *tinst; // enclosing template instance
|
|
322 TemplateInstance *tnext; // non-first instantiated instances
|
|
323 Module *minst; // the top module that instantiated this instance
|
|
324
|
|
325 TemplateInstance(Loc loc, Identifier *temp_id);
|
|
326 TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
|
|
327 static Objects *arraySyntaxCopy(Objects *objs);
|
|
328 Dsymbol *syntaxCopy(Dsymbol *);
|
|
329 void semantic(Scope *sc, Expressions *fargs);
|
|
330 void semantic(Scope *sc);
|
|
331 void semantic2(Scope *sc);
|
|
332 void semantic3(Scope *sc);
|
|
333 Dsymbol *toAlias(); // resolve real symbol
|
|
334 const char *kind() const;
|
|
335 bool oneMember(Dsymbol **ps, Identifier *ident);
|
|
336 const char *toChars();
|
|
337 const char* toPrettyCharsHelper();
|
|
338 void printInstantiationTrace();
|
|
339 Identifier *getIdent();
|
|
340 int compare(RootObject *o);
|
|
341 hash_t toHash();
|
|
342
|
|
343 bool needsCodegen();
|
|
344
|
|
345 // Internal
|
|
346 bool findTempDecl(Scope *sc, WithScopeSymbol **pwithsym);
|
|
347 bool updateTempDecl(Scope *sc, Dsymbol *s);
|
|
348 static bool semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
|
|
349 bool semanticTiargs(Scope *sc);
|
|
350 bool findBestMatch(Scope *sc, Expressions *fargs);
|
|
351 bool needsTypeInference(Scope *sc, int flag = 0);
|
|
352 bool hasNestedArgs(Objects *tiargs, bool isstatic);
|
|
353 Dsymbols *appendToModuleMember();
|
|
354 void declareParameters(Scope *sc);
|
|
355 Identifier *genIdent(Objects *args);
|
|
356 void expandMembers(Scope *sc);
|
|
357 void tryExpandMembers(Scope *sc);
|
|
358 void trySemantic3(Scope *sc2);
|
|
359
|
|
360 TemplateInstance *isTemplateInstance() { return this; }
|
|
361 void accept(Visitor *v) { v->visit(this); }
|
|
362 };
|
|
363
|
|
364 class TemplateMixin : public TemplateInstance
|
|
365 {
|
|
366 public:
|
|
367 TypeQualified *tqual;
|
|
368
|
|
369 TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs);
|
|
370 Dsymbol *syntaxCopy(Dsymbol *s);
|
|
371 void semantic(Scope *sc);
|
|
372 void semantic2(Scope *sc);
|
|
373 void semantic3(Scope *sc);
|
|
374 const char *kind() const;
|
|
375 bool oneMember(Dsymbol **ps, Identifier *ident);
|
|
376 int apply(Dsymbol_apply_ft_t fp, void *param);
|
|
377 bool hasPointers();
|
|
378 void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
|
379 const char *toChars();
|
|
380
|
|
381 bool findTempDecl(Scope *sc);
|
|
382
|
|
383 TemplateMixin *isTemplateMixin() { return this; }
|
|
384 void accept(Visitor *v) { v->visit(this); }
|
|
385 };
|
|
386
|
|
387 Expression *isExpression(RootObject *o);
|
|
388 Dsymbol *isDsymbol(RootObject *o);
|
|
389 Type *isType(RootObject *o);
|
|
390 Tuple *isTuple(RootObject *o);
|
|
391 Parameter *isParameter(RootObject *o);
|
|
392 bool arrayObjectIsError(Objects *args);
|
|
393 bool isError(RootObject *o);
|
|
394 Type *getType(RootObject *o);
|
|
395 Dsymbol *getDsymbol(RootObject *o);
|
|
396
|
|
397 RootObject *objectSyntaxCopy(RootObject *o);
|