xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/template.h (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
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()
dyncast()44     int dyncast() const { return DYNCAST_TUPLE; }
45 
toChars()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 
isTemplateDeclaration()103     TemplateDeclaration *isTemplateDeclaration() { return this; }
104 
105     TemplateTupleParameter *isVariadic();
106     bool isOverloadable();
107 
accept(Visitor * v)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;
accept(Visitor * v)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();
accept(Visitor * v)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();
accept(Visitor * v)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();
accept(Visitor * v)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();
accept(Visitor * v)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();
accept(Visitor * v)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 
isTemplateInstance()360     TemplateInstance *isTemplateInstance() { return this; }
accept(Visitor * v)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 
isTemplateMixin()383     TemplateMixin *isTemplateMixin() { return this; }
accept(Visitor * v)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);
398