1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2021 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/D-Programming-Language/dmd/blob/master/src/traits.c
9  */
10 
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13 #include "root/aav.h"
14 #include "root/checkedint.h"
15 
16 #include "errors.h"
17 #include "mtype.h"
18 #include "init.h"
19 #include "expression.h"
20 #include "template.h"
21 #include "utf.h"
22 #include "enum.h"
23 #include "scope.h"
24 #include "hdrgen.h"
25 #include "statement.h"
26 #include "declaration.h"
27 #include "aggregate.h"
28 #include "import.h"
29 #include "id.h"
30 #include "dsymbol.h"
31 #include "module.h"
32 #include "attrib.h"
33 #include "parse.h"
34 #include "root/speller.h"
35 #include "target.h"
36 
37 typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
38 int ScopeDsymbol_foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn = NULL);
39 void freeFieldinit(Scope *sc);
40 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
41 Package *resolveIsPackage(Dsymbol *sym);
42 Expression *typeToExpression(Type *t);
43 Type *decoToType(const char *deco);
44 bool expressionsToString(OutBuffer &buf, Scope *sc, Expressions *exps);
45 
46 
47 /************************************************
48  * Delegate to be passed to overloadApply() that looks
49  * for functions matching a trait.
50  */
51 
52 struct Ptrait
53 {
54     Dsymbol *sym;
55     Expression *e1;
56     Expressions *exps;          // collected results
57     Identifier *ident;          // which trait we're looking for
58     bool includeTemplates;
59     AA **funcTypeHash;
60 };
61 
62 /* Compute the function signature and insert it in the
63  * hashtable, if not present. This is needed so that
64  * traits(getOverlods, F3, "visit") does not count `int visit(int)`
65  * twice in the following example:
66  *
67  * =============================================
68  * interface F1 { int visit(int);}
69  * interface F2 { int visit(int); void visit(); }
70  * interface F3 : F2, F1 {}
71  *==============================================
72  */
insertInterfaceInheritedFunction(Ptrait * p,FuncDeclaration * fd,Expression * e)73 static void insertInterfaceInheritedFunction(Ptrait *p, FuncDeclaration *fd, Expression *e)
74 {
75     Identifier *signature = Identifier::idPool(fd->type->toChars());
76     //printf("%s - %s\n", fd->toChars, signature);
77     if (!dmd_aaGetRvalue(*p->funcTypeHash, (void *)signature))
78     {
79         bool* value = (bool*) dmd_aaGet(p->funcTypeHash, (void *)signature);
80         *value = true;
81         p->exps->push(e);
82     }
83 }
84 
fptraits(void * param,Dsymbol * s)85 static int fptraits(void *param, Dsymbol *s)
86 {
87     Ptrait *p = (Ptrait *)param;
88     if (p->includeTemplates)
89     {
90         p->exps->push(new DsymbolExp(Loc(),s, false));
91         return 0;
92     }
93     FuncDeclaration *fd = s->isFuncDeclaration();
94     if (!fd)
95         return 0;
96 
97     if (p->ident == Id::getVirtualFunctions && !fd->isVirtual())
98         return 0;
99 
100     if (p->ident == Id::getVirtualMethods && !fd->isVirtualMethod())
101         return 0;
102 
103     Expression *e;
104     FuncAliasDeclaration* ad = new FuncAliasDeclaration(fd->ident, fd, false);
105     ad->protection = fd->protection;
106     if (p->e1)
107         e = new DotVarExp(Loc(), p->e1, ad, false);
108     else
109         e = new DsymbolExp(Loc(), ad, false);
110      // if the parent is an interface declaration
111      // we must check for functions with the same signature
112      // in different inherited interfaces
113      if (p->sym && p->sym->isInterfaceDeclaration())
114          insertInterfaceInheritedFunction(p, fd, e);
115      else
116          p->exps->push(e);
117     return 0;
118 }
119 
120 /**
121  * Collects all unit test functions from the given array of symbols.
122  *
123  * This is a helper function used by the implementation of __traits(getUnitTests).
124  *
125  * Input:
126  *      symbols             array of symbols to collect the functions from
127  *      uniqueUnitTests     an associative array (should actually be a set) to
128  *                          keep track of already collected functions. We're
129  *                          using an AA here to avoid doing a linear search of unitTests
130  *
131  * Output:
132  *      unitTests           array of DsymbolExp's of the collected unit test functions
133  *      uniqueUnitTests     updated with symbols from unitTests[ ]
134  */
collectUnitTests(Dsymbols * symbols,AA * uniqueUnitTests,Expressions * unitTests)135 static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions *unitTests)
136 {
137     if (!symbols)
138         return;
139     for (size_t i = 0; i < symbols->length; i++)
140     {
141         Dsymbol *symbol = (*symbols)[i];
142         UnitTestDeclaration *unitTest = symbol->isUnitTestDeclaration();
143         if (unitTest)
144         {
145             if (!dmd_aaGetRvalue(uniqueUnitTests, (void *)unitTest))
146             {
147                 FuncAliasDeclaration* ad = new FuncAliasDeclaration(unitTest->ident, unitTest, false);
148                 ad->protection = unitTest->protection;
149                 Expression* e = new DsymbolExp(Loc(), ad, false);
150                 unitTests->push(e);
151                 bool* value = (bool*) dmd_aaGet(&uniqueUnitTests, (void *)unitTest);
152                 *value = true;
153             }
154         }
155         else
156         {
157             AttribDeclaration *attrDecl = symbol->isAttribDeclaration();
158 
159             if (attrDecl)
160             {
161                 Dsymbols *decl = attrDecl->include(NULL);
162                 collectUnitTests(decl, uniqueUnitTests, unitTests);
163             }
164         }
165     }
166 }
167 
168 /***************************************************
169  * Determine if type t is copyable.
170  * Params:
171  *      t = type to check
172  * Returns:
173  *      true if we can copy it
174  */
isCopyable(Type * t)175 static bool isCopyable(Type *t)
176 {
177     //printf("isCopyable() %s\n", t->toChars());
178     if (TypeStruct *ts = t->isTypeStruct())
179     {
180         if (ts->sym->postblit &&
181             (ts->sym->postblit->storage_class & STCdisable))
182             return false;
183     }
184     return true;
185 }
186 
187 /************************ TraitsExp ************************************/
188 
True(TraitsExp * e)189 static Expression *True(TraitsExp *e)  { return new IntegerExp(e->loc, true, Type::tbool); }
False(TraitsExp * e)190 static Expression *False(TraitsExp *e) { return new IntegerExp(e->loc, false, Type::tbool); }
191 
192 /**************************************
193  * Convert `Expression` or `Type` to corresponding `Dsymbol`,
194  * additionally strip off expression contexts.
195  *
196  * Some symbol related `__traits` ignore arguments expression contexts.
197  * For example:
198  *  struct S { void f() {} }
199  *  S s;
200  *  pragma(msg, __traits(isNested, s.f));
201  *  // s.f is DotVarExp, but __traits(isNested) needs a FuncDeclaration.
202  *
203  * This is used for that common `__traits` behavior.
204  */
getDsymbolWithoutExpCtx(RootObject * oarg)205 static Dsymbol *getDsymbolWithoutExpCtx(RootObject *oarg)
206 {
207     if (Expression *e = isExpression(oarg))
208     {
209         if (e->op == TOKdotvar)
210             return ((DotVarExp *)e)->var;
211         if (e->op == TOKdottd)
212             return ((DotTemplateExp *)e)->td;
213     }
214     return getDsymbol(oarg);
215 }
216 
217 /**
218    Gets the function type from a given AST node
219    if the node is a function of some sort.
220 
221  Params:
222     o = an AST node to check for a `TypeFunction`
223     fdp = optional pointer to a function declararion, to be set
224       if `o` is a function declarartion.
225 
226  Returns:
227     a type node if `o` is a declaration of
228         a delegate, function, function-pointer
229       or a variable of the former.  Otherwise, `null`.
230 */
231 static TypeFunction *toTypeFunction(RootObject *o, FuncDeclaration **fdp = NULL)
232 {
233     Dsymbol *s = getDsymbolWithoutExpCtx(o);
234     Type *t = isType(o);
235     TypeFunction *tf = NULL;
236 
237     if (s)
238     {
239         FuncDeclaration *fd = s->isFuncDeclaration();
240         if (fd)
241         {
242             t = fd->type;
243             if (fdp)
244                 *fdp = fd;
245         }
246         else if (VarDeclaration *vd = s->isVarDeclaration())
247             t = vd->type;
248     }
249     if (t)
250     {
251         if (t->ty == Tfunction)
252             tf = (TypeFunction *)t;
253         else if (t->ty == Tdelegate)
254             tf = (TypeFunction *)t->nextOf();
255         else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction)
256             tf = (TypeFunction *)t->nextOf();
257     }
258 
259     return tf;
260 }
261 
isTypeArithmetic(Type * t)262 static bool isTypeArithmetic(Type *t)       { return t->isintegral() || t->isfloating(); }
isTypeFloating(Type * t)263 static bool isTypeFloating(Type *t)         { return t->isfloating(); }
isTypeIntegral(Type * t)264 static bool isTypeIntegral(Type *t)         { return t->isintegral(); }
isTypeScalar(Type * t)265 static bool isTypeScalar(Type *t)           { return t->isscalar(); }
isTypeUnsigned(Type * t)266 static bool isTypeUnsigned(Type *t)         { return t->isunsigned(); }
isTypeAssociativeArray(Type * t)267 static bool isTypeAssociativeArray(Type *t) { return t->toBasetype()->ty == Taarray; }
isTypeStaticArray(Type * t)268 static bool isTypeStaticArray(Type *t)      { return t->toBasetype()->ty == Tsarray; }
isTypeAbstractClass(Type * t)269 static bool isTypeAbstractClass(Type *t)    { return t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract(); }
isTypeFinalClass(Type * t)270 static bool isTypeFinalClass(Type *t)       { return t->toBasetype()->ty == Tclass && (((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) != 0; }
271 
isTypeX(TraitsExp * e,bool (* fp)(Type * t))272 static Expression *isTypeX(TraitsExp *e, bool (*fp)(Type *t))
273 {
274     if (!e->args || !e->args->length)
275         return False(e);
276     for (size_t i = 0; i < e->args->length; i++)
277     {
278         Type *t = getType((*e->args)[i]);
279         if (!t || !fp(t))
280             return False(e);
281     }
282     return True(e);
283 }
284 
isDsymDeprecated(Dsymbol * s)285 static bool isDsymDeprecated(Dsymbol *s) { return s->isDeprecated(); }
286 
fpisTemplate(void *,Dsymbol * s)287 static int fpisTemplate(void *, Dsymbol *s)
288 {
289     if (s->isTemplateDeclaration())
290         return 1;
291 
292     return 0;
293 }
294 
isTemplate(Dsymbol * s)295 bool isTemplate(Dsymbol *s)
296 {
297     if (!s->toAlias()->isOverloadable())
298         return false;
299 
300     return overloadApply(s, NULL, &fpisTemplate) != 0;
301 }
302 
isDsymX(TraitsExp * e,bool (* fp)(Dsymbol * s))303 static Expression *isDsymX(TraitsExp *e, bool (*fp)(Dsymbol *s))
304 {
305     if (!e->args || !e->args->length)
306         return False(e);
307     for (size_t i = 0; i < e->args->length; i++)
308     {
309         Dsymbol *s = getDsymbolWithoutExpCtx((*e->args)[i]);
310         if (!s || !fp(s))
311             return False(e);
312     }
313     return True(e);
314 }
315 
isFuncAbstractFunction(FuncDeclaration * f)316 static bool isFuncAbstractFunction(FuncDeclaration *f) { return f->isAbstract(); }
isFuncVirtualFunction(FuncDeclaration * f)317 static bool isFuncVirtualFunction(FuncDeclaration *f) { return f->isVirtual(); }
isFuncVirtualMethod(FuncDeclaration * f)318 static bool isFuncVirtualMethod(FuncDeclaration *f) { return f->isVirtualMethod(); }
isFuncFinalFunction(FuncDeclaration * f)319 static bool isFuncFinalFunction(FuncDeclaration *f) { return f->isFinalFunc(); }
isFuncStaticFunction(FuncDeclaration * f)320 static bool isFuncStaticFunction(FuncDeclaration *f) { return !f->needThis() && !f->isNested(); }
isFuncOverrideFunction(FuncDeclaration * f)321 static bool isFuncOverrideFunction(FuncDeclaration *f) { return f->isOverride(); }
322 
isFuncX(TraitsExp * e,bool (* fp)(FuncDeclaration * f))323 static Expression *isFuncX(TraitsExp *e, bool (*fp)(FuncDeclaration *f))
324 {
325     if (!e->args || !e->args->length)
326         return False(e);
327     for (size_t i = 0; i < e->args->length; i++)
328     {
329         Dsymbol *s = getDsymbolWithoutExpCtx((*e->args)[i]);
330         if (!s)
331             return False(e);
332         FuncDeclaration *f = s->isFuncDeclaration();
333         if (!f || !fp(f))
334             return False(e);
335     }
336     return True(e);
337 }
338 
isDeclDisabled(Declaration * d)339 static bool isDeclDisabled(Declaration *d) { return d->isDisabled(); }
isDeclFuture(Declaration * d)340 static bool isDeclFuture(Declaration *d) { return d->isFuture(); }
isDeclRef(Declaration * d)341 static bool isDeclRef(Declaration *d) { return d->isRef(); }
isDeclOut(Declaration * d)342 static bool isDeclOut(Declaration *d) { return d->isOut(); }
isDeclLazy(Declaration * d)343 static bool isDeclLazy(Declaration *d) { return (d->storage_class & STClazy) != 0; }
344 
isDeclX(TraitsExp * e,bool (* fp)(Declaration * d))345 static Expression *isDeclX(TraitsExp *e, bool (*fp)(Declaration *d))
346 {
347     if (!e->args || !e->args->length)
348         return False(e);
349     for (size_t i = 0; i < e->args->length; i++)
350     {
351         Dsymbol *s = getDsymbolWithoutExpCtx((*e->args)[i]);
352         if (!s)
353             return False(e);
354         Declaration *d = s->isDeclaration();
355         if (!d || !fp(d))
356             return False(e);
357     }
358     return True(e);
359 }
360 
isPkgModule(Package * p)361 static bool isPkgModule(Package *p) { return p->isModule() || p->isPackageMod(); }
isPkgPackage(Package * p)362 static bool isPkgPackage(Package *p) { return p->isModule() == NULL; }
363 
isPkgX(TraitsExp * e,bool (* fp)(Package * p))364 static Expression *isPkgX(TraitsExp *e, bool (*fp)(Package *p))
365 {
366     if (!e->args || !e->args->length)
367         return False(e);
368     for (size_t i = 0; i < e->args->length; i++)
369     {
370         Dsymbol *s = getDsymbolWithoutExpCtx((*e->args)[i]);
371         if (!s)
372             return False(e);
373         Package *p = resolveIsPackage(s);
374         if (!p || !fp(p))
375             return False(e);
376     }
377     return True(e);
378 }
379 
380 // callback for TypeFunction::attributesApply
381 struct PushAttributes
382 {
383     Expressions *mods;
384 
fpPushAttributes385     static int fp(void *param, const char *str)
386     {
387         PushAttributes *p = (PushAttributes *)param;
388         p->mods->push(new StringExp(Loc(), const_cast<char *>(str)));
389         return 0;
390     }
391 };
392 
393 StringTable traitsStringTable;
394 
395 struct TraitsInitializer
396 {
397     TraitsInitializer();
398 };
399 
400 static TraitsInitializer traitsinitializer;
401 
TraitsInitializer()402 TraitsInitializer::TraitsInitializer()
403 {
404     const char* traits[] = {
405         "isAbstractClass",
406         "isArithmetic",
407         "isAssociativeArray",
408         "isDisabled",
409         "isDeprecated",
410         "isFuture",
411         "isFinalClass",
412         "isPOD",
413         "isNested",
414         "isFloating",
415         "isIntegral",
416         "isScalar",
417         "isStaticArray",
418         "isUnsigned",
419         "isVirtualFunction",
420         "isVirtualMethod",
421         "isAbstractFunction",
422         "isFinalFunction",
423         "isOverrideFunction",
424         "isStaticFunction",
425         "isModule",
426         "isPackage",
427         "isRef",
428         "isOut",
429         "isLazy",
430         "isReturnOnStack",
431         "hasMember",
432         "identifier",
433         "getProtection",
434         "getVisibility",
435         "parent",
436         "child",
437         "getLinkage",
438         "getMember",
439         "getOverloads",
440         "getVirtualFunctions",
441         "getVirtualMethods",
442         "classInstanceSize",
443         "allMembers",
444         "derivedMembers",
445         "isSame",
446         "compiles",
447         "getAliasThis",
448         "getAttributes",
449         "getFunctionAttributes",
450         "getFunctionVariadicStyle",
451         "getParameterStorageClasses",
452         "getUnitTests",
453         "getVirtualIndex",
454         "getPointerBitmap",
455         "isZeroInit",
456         "getTargetInfo",
457         "getLocation",
458         "hasPostblit",
459         "isCopyable",
460         NULL
461     };
462 
463     traitsStringTable._init(56);
464 
465     for (size_t idx = 0;; idx++)
466     {
467         const char *s = traits[idx];
468         if (!s) break;
469         StringValue *sv = traitsStringTable.insert(s, strlen(s), const_cast<char *>(s));
470         assert(sv);
471     }
472 }
473 
trait_search_fp(void *,const char * seed,int * cost)474 void *trait_search_fp(void *, const char *seed, int* cost)
475 {
476     //printf("trait_search_fp('%s')\n", seed);
477     size_t len = strlen(seed);
478     if (!len)
479         return NULL;
480 
481     *cost = 0;
482     StringValue *sv = traitsStringTable.lookup(seed, len);
483     return sv ? (void*)sv->ptrvalue : NULL;
484 }
485 
486 /**
487  * get an array of size_t values that indicate possible pointer words in memory
488  *  if interpreted as the type given as argument
489  * the first array element is the size of the type for independent interpretation
490  *  of the array
491  * following elements bits represent one word (4/8 bytes depending on the target
492  *  architecture). If set the corresponding memory might contain a pointer/reference.
493  *
494  *  [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...]
495  */
pointerBitmap(TraitsExp * e)496 Expression *pointerBitmap(TraitsExp *e)
497 {
498     if (!e->args || e->args->length != 1)
499     {
500         error(e->loc, "a single type expected for trait pointerBitmap");
501         return new ErrorExp();
502     }
503     Type *t = getType((*e->args)[0]);
504     if (!t)
505     {
506         error(e->loc, "%s is not a type", (*e->args)[0]->toChars());
507         return new ErrorExp();
508     }
509     d_uns64 sz;
510     if (t->ty == Tclass && !((TypeClass*)t)->sym->isInterfaceDeclaration())
511         sz = ((TypeClass*)t)->sym->AggregateDeclaration::size(e->loc);
512     else
513         sz = t->size(e->loc);
514     if (sz == SIZE_INVALID)
515         return new ErrorExp();
516 
517     const d_uns64 sz_size_t = Type::tsize_t->size(e->loc);
518     if (sz > UINT64_MAX - sz_size_t)
519     {
520         error(e->loc, "size overflow for type %s", t->toChars());
521         return new ErrorExp();
522     }
523 
524     d_uns64 bitsPerWord = sz_size_t * 8;
525     d_uns64 cntptr = (sz + sz_size_t - 1) / sz_size_t;
526     d_uns64 cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
527     Array<d_uns64> data;
528     data.setDim((size_t)cntdata);
529     data.zero();
530 
531     class PointerBitmapVisitor : public Visitor
532     {
533     public:
534         PointerBitmapVisitor(Array<d_uns64>* _data, d_uns64 _sz_size_t)
535             : data(_data), offset(0), sz_size_t(_sz_size_t), error(false)
536         {}
537 
538         void setpointer(d_uns64 off)
539         {
540             d_uns64 ptroff = off / sz_size_t;
541             (*data)[(size_t)(ptroff / (8 * sz_size_t))] |= 1LL << (ptroff % (8 * sz_size_t));
542         }
543         virtual void visit(Type *t)
544         {
545             Type *tb = t->toBasetype();
546             if (tb != t)
547                 tb->accept(this);
548         }
549         virtual void visit(TypeError *t) { visit((Type *)t); }
550         virtual void visit(TypeNext *) { assert(0); }
551         virtual void visit(TypeBasic *t)
552         {
553             if (t->ty == Tvoid)
554                 setpointer(offset);
555         }
556         virtual void visit(TypeVector *) { }
557         virtual void visit(TypeArray *) { assert(0); }
558         virtual void visit(TypeSArray *t)
559         {
560             d_uns64 arrayoff = offset;
561             d_uns64 nextsize = t->next->size();
562             if (nextsize == SIZE_INVALID)
563                 error = true;
564             d_uns64 dim = t->dim->toInteger();
565             for (d_uns64 i = 0; i < dim; i++)
566             {
567                 offset = arrayoff + i * nextsize;
568                 t->next->accept(this);
569             }
570             offset = arrayoff;
571         }
572         virtual void visit(TypeDArray *) { setpointer(offset + sz_size_t); } // dynamic array is {length,ptr}
573         virtual void visit(TypeAArray *) { setpointer(offset); }
574         virtual void visit(TypePointer *t)
575         {
576             if (t->nextOf()->ty != Tfunction) // don't mark function pointers
577                 setpointer(offset);
578         }
579         virtual void visit(TypeReference *) { setpointer(offset); }
580         virtual void visit(TypeClass *) { setpointer(offset); }
581         virtual void visit(TypeFunction *) { }
582         virtual void visit(TypeDelegate *) { setpointer(offset); } // delegate is {context, function}
583         virtual void visit(TypeQualified *) { assert(0); } // assume resolved
584         virtual void visit(TypeIdentifier *) { assert(0); }
585         virtual void visit(TypeInstance *) { assert(0); }
586         virtual void visit(TypeTypeof *) { assert(0); }
587         virtual void visit(TypeReturn *) { assert(0); }
588         virtual void visit(TypeEnum *t) { visit((Type *)t); }
589         virtual void visit(TypeTuple *t) { visit((Type *)t); }
590         virtual void visit(TypeSlice *) { assert(0); }
591         virtual void visit(TypeNull *) { } // always a null pointer
592 
593         virtual void visit(TypeStruct *t)
594         {
595             d_uns64 structoff = offset;
596             for (size_t i = 0; i < t->sym->fields.length; i++)
597             {
598                 VarDeclaration *v = t->sym->fields[i];
599                 offset = structoff + v->offset;
600                 if (v->type->ty == Tclass)
601                     setpointer(offset);
602                 else
603                     v->type->accept(this);
604             }
605             offset = structoff;
606         }
607 
608         // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references
609         void visitClass(TypeClass* t)
610         {
611             d_uns64 classoff = offset;
612 
613             // skip vtable-ptr and monitor
614             if (t->sym->baseClass)
615                 visitClass((TypeClass*)t->sym->baseClass->type);
616 
617             for (size_t i = 0; i < t->sym->fields.length; i++)
618             {
619                 VarDeclaration *v = t->sym->fields[i];
620                 offset = classoff + v->offset;
621                 v->type->accept(this);
622             }
623             offset = classoff;
624         }
625 
626         Array<d_uns64>* data;
627         d_uns64 offset;
628         d_uns64 sz_size_t;
629         bool error;
630     };
631 
632     PointerBitmapVisitor pbv(&data, sz_size_t);
633     if (t->ty == Tclass)
634         pbv.visitClass((TypeClass*)t);
635     else
636         t->accept(&pbv);
637     if (pbv.error)
638         return new ErrorExp();
639 
640     Expressions* exps = new Expressions;
641     exps->push(new IntegerExp(e->loc, sz, Type::tsize_t));
642     for (d_uns64 i = 0; i < cntdata; i++)
643         exps->push(new IntegerExp(e->loc, data[(size_t)i], Type::tsize_t));
644 
645     ArrayLiteralExp* ale = new ArrayLiteralExp(e->loc, Type::tsize_t->sarrayOf(cntdata + 1), exps);
646     return ale;
647 }
648 
dimError(TraitsExp * e,int expected,int dim)649 static Expression *dimError(TraitsExp *e, int expected, int dim)
650 {
651     e->error("expected %d arguments for `%s` but had %d", expected, e->ident->toChars(), dim);
652     return new ErrorExp();
653 }
654 
semanticTraits(TraitsExp * e,Scope * sc)655 Expression *semanticTraits(TraitsExp *e, Scope *sc)
656 {
657     if (e->ident != Id::compiles &&
658         e->ident != Id::isSame &&
659         e->ident != Id::identifier &&
660         e->ident != Id::getProtection && e->ident != Id::getVisibility &&
661         e->ident != Id::getAttributes)
662     {
663         // Pretend we're in a deprecated scope so that deprecation messages
664         // aren't triggered when checking if a symbol is deprecated
665         const StorageClass save = sc->stc;
666         if (e->ident == Id::isDeprecated)
667             sc->stc |= STCdeprecated;
668         if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1))
669         {
670             sc->stc = save;
671             return new ErrorExp();
672         }
673         sc->stc = save;
674     }
675     size_t dim = e->args ? e->args->length : 0;
676 
677     if (e->ident == Id::isArithmetic)
678     {
679         return isTypeX(e, &isTypeArithmetic);
680     }
681     else if (e->ident == Id::isFloating)
682     {
683         return isTypeX(e, &isTypeFloating);
684     }
685     else if (e->ident == Id::isIntegral)
686     {
687         return isTypeX(e, &isTypeIntegral);
688     }
689     else if (e->ident == Id::isScalar)
690     {
691         return isTypeX(e, &isTypeScalar);
692     }
693     else if (e->ident == Id::isUnsigned)
694     {
695         return isTypeX(e, &isTypeUnsigned);
696     }
697     else if (e->ident == Id::isAssociativeArray)
698     {
699         return isTypeX(e, &isTypeAssociativeArray);
700     }
701     else if (e->ident == Id::isDeprecated)
702     {
703         return isDsymX(e, &isDsymDeprecated);
704     }
705     else if (e->ident == Id::isFuture)
706     {
707         return isDeclX(e, &isDeclFuture);
708     }
709     else if (e->ident == Id::isStaticArray)
710     {
711         return isTypeX(e, &isTypeStaticArray);
712     }
713     else if (e->ident == Id::isAbstractClass)
714     {
715         return isTypeX(e, &isTypeAbstractClass);
716     }
717     else if (e->ident == Id::isFinalClass)
718     {
719         return isTypeX(e, &isTypeFinalClass);
720     }
721     else if (e->ident == Id::isTemplate)
722     {
723         if (dim != 1)
724             return dimError(e, 1, dim);
725 
726         return isDsymX(e, &isTemplate);
727     }
728     else if (e->ident == Id::isPOD)
729     {
730         if (dim != 1)
731             return dimError(e, 1, dim);
732 
733         RootObject *o = (*e->args)[0];
734         Type *t = isType(o);
735         if (!t)
736         {
737             e->error("type expected as second argument of __traits %s instead of %s",
738                 e->ident->toChars(), o->toChars());
739             return new ErrorExp();
740         }
741 
742         Type *tb = t->baseElemOf();
743         if (StructDeclaration *sd = (tb->ty == Tstruct) ? ((TypeStruct *)tb)->sym : NULL)
744         {
745             return (sd->isPOD()) ? True(e) : False(e);
746         }
747         return True(e);
748     }
749     else if (e->ident == Id::hasPostblit)
750     {
751         if (dim != 1)
752             return dimError(e, 1, dim);
753 
754         RootObject *o = (*e->args)[0];
755         Type *t = isType(o);
756         if (!t)
757         {
758             e->error("type expected as second argument of __traits %s instead of %s",
759                 e->ident->toChars(), o->toChars());
760             return new ErrorExp();
761         }
762 
763         Type *tb = t->baseElemOf();
764         if (StructDeclaration *sd = (tb->ty == Tstruct) ? ((TypeStruct *)tb)->sym : NULL)
765         {
766             return sd->postblit ? True(e) : False(e);
767         }
768         return False(e);
769     }
770     else if (e->ident == Id::isCopyable)
771     {
772         if (dim != 1)
773             return dimError(e, 1, dim);
774 
775         RootObject *o = (*e->args)[0];
776         Type *t = isType(o);
777         if (!t)
778         {
779             e->error("type expected as second argument of __traits %s instead of %s",
780                 e->ident->toChars(), o->toChars());
781             return new ErrorExp();
782         }
783 
784         return isCopyable(t) ? True(e) : False(e);
785     }
786     else if (e->ident == Id::isNested)
787     {
788         if (dim != 1)
789             return dimError(e, 1, dim);
790 
791         RootObject *o = (*e->args)[0];
792         Dsymbol *s = getDsymbolWithoutExpCtx(o);
793         if (!s)
794         {
795         }
796         else if (AggregateDeclaration *a = s->isAggregateDeclaration())
797         {
798             return a->isNested() ? True(e) : False(e);
799         }
800         else if (FuncDeclaration *f = s->isFuncDeclaration())
801         {
802             return f->isNested() ? True(e) : False(e);
803         }
804 
805         e->error("aggregate or function expected instead of `%s`", o->toChars());
806         return new ErrorExp();
807     }
808     else if (e->ident == Id::isDisabled)
809     {
810         if (dim != 1)
811             return dimError(e, 1, dim);
812 
813         return isDeclX(e, &isDeclDisabled);
814     }
815     else if (e->ident == Id::isAbstractFunction)
816     {
817         if (dim != 1)
818             return dimError(e, 1, dim);
819 
820         return isFuncX(e, &isFuncAbstractFunction);
821     }
822     else if (e->ident == Id::isVirtualFunction)
823     {
824         if (dim != 1)
825             return dimError(e, 1, dim);
826 
827         return isFuncX(e, &isFuncVirtualFunction);
828     }
829     else if (e->ident == Id::isVirtualMethod)
830     {
831         if (dim != 1)
832             return dimError(e, 1, dim);
833 
834         return isFuncX(e, &isFuncVirtualMethod);
835     }
836     else if (e->ident == Id::isFinalFunction)
837     {
838         if (dim != 1)
839             return dimError(e, 1, dim);
840 
841         return isFuncX(e, &isFuncFinalFunction);
842     }
843     else if (e->ident == Id::isOverrideFunction)
844     {
845         if (dim != 1)
846             return dimError(e, 1, dim);
847 
848         return isFuncX(e, &isFuncOverrideFunction);
849     }
850     else if (e->ident == Id::isStaticFunction)
851     {
852         if (dim != 1)
853             return dimError(e, 1, dim);
854 
855         return isFuncX(e, &isFuncStaticFunction);
856     }
857     else if (e->ident == Id::isModule)
858     {
859         if (dim != 1)
860             return dimError(e, 1, dim);
861 
862         return isPkgX(e, &isPkgModule);
863     }
864     else if (e->ident == Id::isPackage)
865     {
866         if (dim != 1)
867             return dimError(e, 1, dim);
868 
869         return isPkgX(e, &isPkgPackage);
870     }
871     else if (e->ident == Id::isRef)
872     {
873         if (dim != 1)
874             return dimError(e, 1, dim);
875 
876         return isDeclX(e, &isDeclRef);
877     }
878     else if (e->ident == Id::isOut)
879     {
880         if (dim != 1)
881             return dimError(e, 1, dim);
882 
883         return isDeclX(e, &isDeclOut);
884     }
885     else if (e->ident == Id::isLazy)
886     {
887         if (dim != 1)
888             return dimError(e, 1, dim);
889 
890         return isDeclX(e, &isDeclLazy);
891     }
892     else if (e->ident == Id::identifier)
893     {
894         // Get identifier for symbol as a string literal
895         /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
896          * a symbol should not be folded to a constant.
897          * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
898          */
899         if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2))
900             return new ErrorExp();
901         if (dim != 1)
902             return dimError(e, 1, dim);
903 
904         RootObject *o = (*e->args)[0];
905         Identifier *id = NULL;
906         if (Parameter *po = isParameter(o))
907         {
908             if (!po->ident)
909             {
910                 e->error("argument `%s` has no identifier", po->type->toChars());
911                 return new ErrorExp();
912             }
913             id = po->ident;
914         }
915         else
916         {
917             Dsymbol *s = getDsymbolWithoutExpCtx(o);
918             if (!s || !s->ident)
919             {
920                 e->error("argument %s has no identifier", o->toChars());
921                 return new ErrorExp();
922             }
923             id = s->ident;
924         }
925 
926         StringExp *se = new StringExp(e->loc, const_cast<char *>(id->toChars()));
927         return expressionSemantic(se, sc);
928     }
929     else if (e->ident == Id::getProtection || e->ident == Id::getVisibility)
930     {
931         if (dim != 1)
932             return dimError(e, 1, dim);
933 
934         Scope *sc2 = sc->push();
935         sc2->flags = sc->flags | SCOPEnoaccesscheck | SCOPEignoresymbolvisibility;
936         bool ok = TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1);
937         sc2->pop();
938         if (!ok)
939             return new ErrorExp();
940 
941         RootObject *o = (*e->args)[0];
942         Dsymbol *s = getDsymbolWithoutExpCtx(o);
943         if (!s)
944         {
945             if (!isError(o))
946                 e->error("argument %s has no protection", o->toChars());
947             return new ErrorExp();
948         }
949         if (s->semanticRun == PASSinit)
950             dsymbolSemantic(s, NULL);
951 
952         const char *protName = protectionToChars(s->prot().kind);   // TODO: How about package(names)
953         assert(protName);
954         StringExp *se = new StringExp(e->loc, const_cast<char *>(protName));
955         return expressionSemantic(se, sc);
956     }
957     else if (e->ident == Id::parent)
958     {
959         if (dim != 1)
960             return dimError(e, 1, dim);
961 
962         RootObject *o = (*e->args)[0];
963         Dsymbol *s = getDsymbolWithoutExpCtx(o);
964         if (s)
965         {
966             if (FuncDeclaration *fd = s->isFuncDeclaration())   // Bugzilla 8943
967                 s = fd->toAliasFunc();
968             if (!s->isImport())  // Bugzilla 8922
969                 s = s->toParent();
970         }
971         if (!s || s->isImport())
972         {
973             e->error("argument %s has no parent", o->toChars());
974             return new ErrorExp();
975         }
976 
977         if (FuncDeclaration *f = s->isFuncDeclaration())
978         {
979             if (TemplateDeclaration *td = getFuncTemplateDecl(f))
980             {
981                 if (td->overroot)       // if not start of overloaded list of TemplateDeclaration's
982                     td = td->overroot;  // then get the start
983                 Expression *ex = new TemplateExp(e->loc, td, f);
984                 ex = expressionSemantic(ex, sc);
985                 return ex;
986             }
987 
988             if (FuncLiteralDeclaration *fld = f->isFuncLiteralDeclaration())
989             {
990                 // Directly translate to VarExp instead of FuncExp
991                 Expression *ex = new VarExp(e->loc, fld, true);
992                 return expressionSemantic(ex, sc);
993             }
994         }
995 
996         return resolve(e->loc, sc, s, false);
997     }
998     else if (e->ident == Id::child)
999     {
1000         if (dim != 2)
1001             return dimError(e, 2, dim);
1002 
1003         Expression *ex;
1004         RootObject *op = (*e->args)[0];
1005         if (Dsymbol *symp = getDsymbol(op))
1006             ex = new DsymbolExp(e->loc, symp);
1007         else if (Expression *exp = isExpression(op))
1008             ex = exp;
1009         else
1010         {
1011             e->error("symbol or expression expected as first argument of __traits `child` instead of `%s`", op->toChars());
1012             return new ErrorExp();
1013         }
1014 
1015         ex = expressionSemantic(ex, sc);
1016         RootObject *oc = (*e->args)[1];
1017         Dsymbol *symc = getDsymbol(oc);
1018         if (!symc)
1019         {
1020             e->error("symbol expected as second argument of __traits `child` instead of `%s`", oc->toChars());
1021             return new ErrorExp();
1022         }
1023 
1024         if (Declaration *d = symc->isDeclaration())
1025             ex = new DotVarExp(e->loc, ex, d);
1026         else if (TemplateDeclaration *td = symc->isTemplateDeclaration())
1027             ex = new DotExp(e->loc, ex, new TemplateExp(e->loc, td));
1028         else if (ScopeDsymbol *ti = symc->isScopeDsymbol())
1029             ex = new DotExp(e->loc, ex, new ScopeExp(e->loc, ti));
1030         else
1031             assert(0);
1032 
1033         ex = expressionSemantic(ex, sc);
1034         return ex;
1035     }
1036     else if (e->ident == Id::toType)
1037     {
1038         if (dim != 1)
1039             return dimError(e, 1, dim);
1040 
1041         Expression *ex = isExpression((*e->args)[0]);
1042         if (!ex)
1043         {
1044             e->error("expression expected as second argument of __traits `%s`", e->ident->toChars());
1045             return new ErrorExp();
1046         }
1047         ex = ex->ctfeInterpret();
1048 
1049         StringExp *se = semanticString(sc, ex, "__traits(toType, string)");
1050         if (!se)
1051         {
1052             return new ErrorExp();
1053         }
1054         Type *t = decoToType(se->toUTF8(sc)->toPtr());
1055         if (!t)
1056         {
1057             e->error("cannot determine `%s`", e->toChars());
1058             return new ErrorExp();
1059         }
1060         ex = new TypeExp(e->loc, t);
1061         ex = expressionSemantic(ex, sc);
1062         return ex;
1063     }
1064     else if (e->ident == Id::hasMember ||
1065              e->ident == Id::getMember ||
1066              e->ident == Id::getOverloads ||
1067              e->ident == Id::getVirtualMethods ||
1068              e->ident == Id::getVirtualFunctions)
1069     {
1070         if (dim != 2 && !(dim == 3 && e->ident == Id::getOverloads))
1071             return dimError(e, 2, dim);
1072 
1073         RootObject *o = (*e->args)[0];
1074         Expression *ex = isExpression((*e->args)[1]);
1075         if (!ex)
1076         {
1077             e->error("expression expected as second argument of __traits %s", e->ident->toChars());
1078             return new ErrorExp();
1079         }
1080         ex = ex->ctfeInterpret();
1081 
1082         bool includeTemplates = false;
1083         if (dim == 3 && e->ident == Id::getOverloads)
1084         {
1085             Expression *b = isExpression((*e->args)[2]);
1086             b = b->ctfeInterpret();
1087             if (!b->type->equals(Type::tbool))
1088             {
1089                 e->error("`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b->toChars(), b->type->toChars());
1090                 return new ErrorExp();
1091             }
1092             includeTemplates = b->isBool(true);
1093         }
1094 
1095         StringExp *se = ex->toStringExp();
1096         if (!se || se->len == 0)
1097         {
1098             e->error("string expected as second argument of __traits %s instead of %s", e->ident->toChars(), ex->toChars());
1099             return new ErrorExp();
1100         }
1101         se = se->toUTF8(sc);
1102 
1103         if (se->sz != 1)
1104         {
1105             e->error("string must be chars");
1106             return new ErrorExp();
1107         }
1108         Identifier *id = Identifier::idPool((char *)se->string, se->len);
1109 
1110         /* Prefer dsymbol, because it might need some runtime contexts.
1111          */
1112         Dsymbol *sym = getDsymbol(o);
1113         if (sym)
1114         {
1115             if (e->ident == Id::hasMember)
1116             {
1117                 if (sym->search(e->loc, id) != NULL)
1118                     return True(e);
1119             }
1120             ex = new DsymbolExp(e->loc, sym);
1121             ex = new DotIdExp(e->loc, ex, id);
1122         }
1123         else if (Type *t = isType(o))
1124             ex = typeDotIdExp(e->loc, t, id);
1125         else if (Expression *ex2 = isExpression(o))
1126             ex = new DotIdExp(e->loc, ex2, id);
1127         else
1128         {
1129             e->error("invalid first argument");
1130             return new ErrorExp();
1131         }
1132 
1133         // ignore symbol visibility and disable access checks for these traits
1134         Scope *scx = sc->push();
1135         scx->flags |= SCOPEignoresymbolvisibility | SCOPEnoaccesscheck;
1136 
1137         if (e->ident == Id::hasMember)
1138         {
1139             /* Take any errors as meaning it wasn't found
1140              */
1141             ex = trySemantic(ex, scx);
1142             scx->pop();
1143             return ex ? True(e) : False(e);
1144         }
1145         else if (e->ident == Id::getMember)
1146         {
1147             if (ex->op == TOKdotid)
1148                 // Prevent semantic() from replacing Symbol with its initializer
1149                 ((DotIdExp *)ex)->wantsym = true;
1150             ex = expressionSemantic(ex, scx);
1151             scx->pop();
1152             return ex;
1153         }
1154         else if (e->ident == Id::getVirtualFunctions ||
1155                  e->ident == Id::getVirtualMethods ||
1156                  e->ident == Id::getOverloads)
1157         {
1158             unsigned errors = global.errors;
1159             Expression *eorig = ex;
1160             ex = expressionSemantic(ex, scx);
1161             if (errors < global.errors)
1162                 e->error("%s cannot be resolved", eorig->toChars());
1163             //ex->print();
1164 
1165             /* Create tuple of functions of ex
1166              */
1167             Expressions *exps = new Expressions();
1168             Dsymbol *f;
1169             if (ex->op == TOKvar)
1170             {
1171                 VarExp *ve = (VarExp *)ex;
1172                 f = ve->var->isFuncDeclaration();
1173                 ex = NULL;
1174             }
1175             else if (ex->op == TOKdotvar)
1176             {
1177                 DotVarExp *dve = (DotVarExp *)ex;
1178                 f = dve->var->isFuncDeclaration();
1179                 if (dve->e1->op == TOKdottype || dve->e1->op == TOKthis)
1180                     ex = NULL;
1181                 else
1182                     ex = dve->e1;
1183             }
1184             else if (ex->op == TOKtemplate)
1185             {
1186                 TemplateExp *te = (TemplateExp *)ex;
1187                 TemplateDeclaration *td = te->td;
1188                 f = td;
1189                 if (td && td->funcroot)
1190                     f = td->funcroot;
1191                 ex = NULL;
1192             }
1193             else
1194                 f = NULL;
1195             Ptrait p;
1196             p.sym = sym;
1197             p.exps = exps;
1198             p.e1 = ex;
1199             p.ident = e->ident;
1200             p.includeTemplates = includeTemplates;
1201             AA *funcTypeHash = NULL;
1202             p.funcTypeHash = &funcTypeHash;
1203 
1204             InterfaceDeclaration *ifd = NULL;
1205             if (sym)
1206                 ifd = sym->isInterfaceDeclaration();
1207             // If the symbol passed as a parameter is an
1208             // interface that inherits other interfaces
1209             if (ifd && ifd->interfaces.length)
1210             {
1211                 // check the overloads of each inherited interface individually
1212                 for (size_t i = 0; i < ifd->interfaces.length; i++)
1213                 {
1214                     BaseClass *bc = ifd->interfaces.ptr[i];
1215                     if (Dsymbol *fd = bc->sym->search(e->loc, f->ident))
1216                         overloadApply(fd, &p, &fptraits);
1217                 }
1218             }
1219             else
1220                 overloadApply(f, &p, &fptraits);
1221 
1222             ex = new TupleExp(e->loc, exps);
1223             ex = expressionSemantic(ex, scx);
1224             scx->pop();
1225             return ex;
1226         }
1227         else
1228             assert(0);
1229     }
1230     else if (e->ident == Id::classInstanceSize)
1231     {
1232         if (dim != 1)
1233             return dimError(e, 1, dim);
1234 
1235         RootObject *o = (*e->args)[0];
1236         Dsymbol *s = getDsymbol(o);
1237         ClassDeclaration *cd = s ? s->isClassDeclaration() : NULL;
1238         if (!cd)
1239         {
1240             e->error("first argument is not a class");
1241             return new ErrorExp();
1242         }
1243         if (cd->sizeok != SIZEOKdone)
1244         {
1245             cd->size(cd->loc);
1246         }
1247         if (cd->sizeok != SIZEOKdone)
1248         {
1249             e->error("%s %s is forward referenced", cd->kind(), cd->toChars());
1250             return new ErrorExp();
1251         }
1252 
1253         return new IntegerExp(e->loc, cd->structsize, Type::tsize_t);
1254     }
1255     else if (e->ident == Id::getAliasThis)
1256     {
1257         if (dim != 1)
1258             return dimError(e, 1, dim);
1259 
1260         RootObject *o = (*e->args)[0];
1261         Dsymbol *s = getDsymbol(o);
1262         AggregateDeclaration *ad = s ? s->isAggregateDeclaration() : NULL;
1263         if (!ad)
1264         {
1265             e->error("argument is not an aggregate type");
1266             return new ErrorExp();
1267         }
1268 
1269         Expressions *exps = new Expressions();
1270         if (ad->aliasthis)
1271             exps->push(new StringExp(e->loc, const_cast<char *>(ad->aliasthis->ident->toChars())));
1272         Expression *ex = new TupleExp(e->loc, exps);
1273         ex = expressionSemantic(ex, sc);
1274         return ex;
1275     }
1276     else if (e->ident == Id::getAttributes)
1277     {
1278         /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
1279          * a symbol should not be folded to a constant.
1280          * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
1281          */
1282         if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 3))
1283             return new ErrorExp();
1284 
1285         if (dim != 1)
1286             return dimError(e, 1, dim);
1287 
1288         RootObject *o = (*e->args)[0];
1289         Parameter *po = isParameter(o);
1290         Dsymbol *s = getDsymbolWithoutExpCtx(o);
1291         UserAttributeDeclaration *udad = NULL;
1292         if (po)
1293         {
1294             udad = po->userAttribDecl;
1295         }
1296         else if (s)
1297         {
1298             if (Import *imp = s->isImport())
1299             {
1300                 s = imp->mod;
1301             }
1302             //printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttribDecl, s->_scope);
1303             udad = s->userAttribDecl;
1304         }
1305         else
1306         {
1307             e->error("first argument is not a symbol");
1308             return new ErrorExp();
1309         }
1310 
1311         Expressions *exps = udad ? udad->getAttributes() : new Expressions();
1312         TupleExp *tup = new TupleExp(e->loc, exps);
1313         return expressionSemantic(tup, sc);
1314     }
1315     else if (e->ident == Id::getFunctionAttributes)
1316     {
1317         /* extract all function attributes as a tuple (const/shared/inout/pure/nothrow/etc) except UDAs.
1318          * https://dlang.org/spec/traits.html#getFunctionAttributes
1319          */
1320         if (dim != 1)
1321             return dimError(e, 1, dim);
1322 
1323         TypeFunction *tf = toTypeFunction((*e->args)[0]);
1324 
1325         if (!tf)
1326         {
1327             e->error("first argument is not a function");
1328             return new ErrorExp();
1329         }
1330 
1331         Expressions *mods = new Expressions();
1332         PushAttributes pa;
1333         pa.mods = mods;
1334         tf->modifiersApply(&pa, &PushAttributes::fp);
1335         tf->attributesApply(&pa, &PushAttributes::fp, TRUSTformatSystem);
1336 
1337         TupleExp *tup = new TupleExp(e->loc, mods);
1338         return expressionSemantic(tup, sc);
1339     }
1340     else if (e->ident == Id::isReturnOnStack)
1341     {
1342         /* Extract as a boolean if function return value is on the stack
1343          * https://dlang.org/spec/traits.html#isReturnOnStack
1344          */
1345         if (dim != 1)
1346             return dimError(e, 1, dim);
1347 
1348         RootObject *o = (*e->args)[0];
1349         FuncDeclaration *fd = NULL;
1350         TypeFunction *tf = toTypeFunction(o, &fd);
1351 
1352         if (!tf)
1353         {
1354             e->error("argument to `__traits(isReturnOnStack, %s)` is not a function", o->toChars());
1355             return new ErrorExp();
1356         }
1357 
1358         bool value = target.isReturnOnStack(tf, fd && fd->needThis());
1359         return new IntegerExp(e->loc, value, Type::tbool);
1360     }
1361     else if (e->ident == Id::getFunctionVariadicStyle)
1362     {
1363         /* Accept a symbol or a type. Returns one of the following:
1364          *  "none"      not a variadic function
1365          *  "argptr"    extern(D) void dstyle(...), use `__argptr` and `__arguments`
1366          *  "stdarg"    extern(C) void cstyle(int, ...), use core.stdc.stdarg
1367          *  "typesafe"  void typesafe(T[] ...)
1368          */
1369         // get symbol linkage as a string
1370         if (dim != 1)
1371             return dimError(e, 1, dim);
1372 
1373         LINK link;
1374         VarArg varargs;
1375         RootObject *o = (*e->args)[0];
1376         FuncDeclaration *fd = NULL;
1377         TypeFunction *tf = toTypeFunction(o, &fd);
1378 
1379         if (tf)
1380         {
1381             link = tf->linkage;
1382             varargs = tf->parameterList.varargs;
1383         }
1384         else
1385         {
1386             if (!fd)
1387             {
1388                 e->error("argument to `__traits(getFunctionVariadicStyle, %s)` is not a function", o->toChars());
1389                 return new ErrorExp();
1390             }
1391             link = fd->linkage;
1392             varargs = fd->getParameterList().varargs;
1393         }
1394         const char *style;
1395         switch (varargs)
1396         {
1397             case 0: style = "none";                      break;
1398             case 1: style = (link == LINKd) ? "argptr"
1399                                             : "stdarg";  break;
1400             case 2:     style = "typesafe";              break;
1401             default:
1402                 assert(0);
1403         }
1404         StringExp *se = new StringExp(e->loc, const_cast<char*>(style));
1405         return expressionSemantic(se, sc);
1406     }
1407     else if (e->ident == Id::getParameterStorageClasses)
1408     {
1409         /* Accept a function symbol or a type, followed by a parameter index.
1410          * Returns a tuple of strings of the parameter's storage classes.
1411          */
1412         // get symbol linkage as a string
1413         if (dim != 2)
1414             return dimError(e, 2, dim);
1415 
1416         RootObject *o = (*e->args)[0];
1417         RootObject *o1 = (*e->args)[1];
1418 
1419         FuncDeclaration *fd = NULL;
1420         TypeFunction *tf = toTypeFunction(o, &fd);
1421 
1422         ParameterList fparams;
1423         if (tf)
1424         {
1425             fparams = tf->parameterList;
1426         }
1427         else
1428         {
1429             if (!fd)
1430             {
1431                 e->error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function",
1432                     o->toChars(), o1->toChars());
1433                 return new ErrorExp();
1434             }
1435             fparams = fd->getParameterList();
1436         }
1437 
1438         StorageClass stc;
1439 
1440         // Set stc to storage class of the ith parameter
1441         Expression *ex = isExpression((*e->args)[1]);
1442         if (!ex)
1443         {
1444             e->error("expression expected as second argument of `__traits(getParameterStorageClasses, %s, %s)`",
1445                 o->toChars(), o1->toChars());
1446             return new ErrorExp();
1447         }
1448         ex = ex->ctfeInterpret();
1449         uinteger_t ii = ex->toUInteger();
1450         if (ii >= fparams.length())
1451         {
1452             e->error("parameter index must be in range 0..%u not %s", (unsigned)fparams.length(), ex->toChars());
1453             return new ErrorExp();
1454         }
1455 
1456         unsigned n = (unsigned)ii;
1457         Parameter *p = fparams[n];
1458         stc = p->storageClass;
1459 
1460         // This mirrors hdrgen.visit(Parameter p)
1461         if (p->type && p->type->mod & MODshared)
1462             stc &= ~STCshared;
1463 
1464         Expressions *exps = new Expressions;
1465 
1466         if (stc & STCauto)
1467             exps->push(new StringExp(e->loc, const_cast<char *>("auto")));
1468         if (stc & STCreturn)
1469             exps->push(new StringExp(e->loc, const_cast<char *>("return")));
1470 
1471         if (stc & STCout)
1472             exps->push(new StringExp(e->loc, const_cast<char *>("out")));
1473         else if (stc & STCref)
1474             exps->push(new StringExp(e->loc, const_cast<char *>("ref")));
1475         else if (stc & STCin)
1476             exps->push(new StringExp(e->loc, const_cast<char *>("in")));
1477         else if (stc & STClazy)
1478             exps->push(new StringExp(e->loc, const_cast<char *>("lazy")));
1479         else if (stc & STCalias)
1480             exps->push(new StringExp(e->loc, const_cast<char *>("alias")));
1481 
1482         if (stc & STCconst)
1483             exps->push(new StringExp(e->loc, const_cast<char *>("const")));
1484         if (stc & STCimmutable)
1485             exps->push(new StringExp(e->loc, const_cast<char *>("immutable")));
1486         if (stc & STCwild)
1487             exps->push(new StringExp(e->loc, const_cast<char *>("inout")));
1488         if (stc & STCshared)
1489             exps->push(new StringExp(e->loc, const_cast<char *>("shared")));
1490         if (stc & STCscope && !(stc & STCscopeinferred))
1491             exps->push(new StringExp(e->loc, const_cast<char *>("scope")));
1492 
1493         TupleExp *tup = new TupleExp(e->loc, exps);
1494         return expressionSemantic(tup, sc);
1495     }
1496     else if (e->ident == Id::getLinkage)
1497     {
1498         // get symbol linkage as a string
1499         if (dim != 1)
1500             return dimError(e, 1, dim);
1501 
1502         LINK link;
1503         RootObject *o = (*e->args)[0];
1504 
1505         TypeFunction *tf = toTypeFunction(o);
1506 
1507         if (tf)
1508             link = tf->linkage;
1509         else
1510         {
1511             Dsymbol *s = getDsymbol(o);
1512             Declaration *d = NULL;
1513             AggregateDeclaration *ad = NULL;
1514             if (!s || ((d = s->isDeclaration()) == NULL
1515                        && (ad = s->isAggregateDeclaration()) == NULL))
1516             {
1517                 e->error("argument to `__traits(getLinkage, %s)` is not a declaration", o->toChars());
1518                 return new ErrorExp();
1519             }
1520             if (d != NULL)
1521                 link = d->linkage;
1522             else
1523             {
1524                 switch (ad->classKind)
1525                 {
1526                     case ClassKind::d:
1527                         link = LINKd;
1528                         break;
1529                     case ClassKind::cpp:
1530                         link = LINKcpp;
1531                         break;
1532                     case ClassKind::objc:
1533                         link = LINKobjc;
1534                         break;
1535                     default:
1536                         assert(0);
1537                 }
1538             }
1539         }
1540         const char *linkage = linkageToChars(link);
1541         StringExp *se = new StringExp(e->loc, const_cast<char *>(linkage));
1542         return expressionSemantic(se, sc);
1543     }
1544     else if (e->ident == Id::allMembers ||
1545              e->ident == Id::derivedMembers)
1546     {
1547         if (dim != 1)
1548             return dimError(e, 1, dim);
1549 
1550         RootObject *o = (*e->args)[0];
1551         Dsymbol *s = getDsymbol(o);
1552         if (!s)
1553         {
1554             e->error("argument has no members");
1555             return new ErrorExp();
1556         }
1557         if (Import *imp = s->isImport())
1558         {
1559             // Bugzilla 9692
1560             s = imp->mod;
1561         }
1562 
1563         // https://issues.dlang.org/show_bug.cgi?id=16044
1564         if (Package *p = s->isPackage())
1565         {
1566             if (Module *pm = p->isPackageMod())
1567                 s = pm;
1568         }
1569 
1570         ScopeDsymbol *sds = s->isScopeDsymbol();
1571         if (!sds || sds->isTemplateDeclaration())
1572         {
1573             e->error("%s %s has no members", s->kind(), s->toChars());
1574             return new ErrorExp();
1575         }
1576 
1577         // use a struct as local function
1578         struct PushIdentsDg
1579         {
1580             ScopeDsymbol *sds;
1581             Identifiers *idents;
1582 
1583             static int dg(void *ctx, size_t, Dsymbol *sm)
1584             {
1585                 if (!sm)
1586                     return 1;
1587 
1588                 // skip local symbols, such as static foreach loop variables
1589                 if (Declaration *decl = sm->isDeclaration())
1590                 {
1591                     if (decl->storage_class & STClocal)
1592                     {
1593                         return 0;
1594                     }
1595                 }
1596 
1597                 // https://issues.dlang.org/show_bug.cgi?id=20915
1598                 // skip version and debug identifiers
1599                 if (sm->isVersionSymbol() || sm->isDebugSymbol())
1600                     return 0;
1601 
1602                 //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
1603                 if (sm->ident)
1604                 {
1605                     // https://issues.dlang.org/show_bug.cgi?id=10096
1606                     // https://issues.dlang.org/show_bug.cgi?id=10100
1607                     // Skip over internal members in __traits(allMembers)
1608                     if ((sm->isCtorDeclaration() && sm->ident != Id::ctor) ||
1609                         (sm->isDtorDeclaration() && sm->ident != Id::dtor) ||
1610                         (sm->isPostBlitDeclaration() && sm->ident != Id::postblit) ||
1611                         sm->isInvariantDeclaration() ||
1612                         sm->isUnitTestDeclaration())
1613                     {
1614                         return 0;
1615                     }
1616 
1617                     if (sm->ident == Id::empty)
1618                     {
1619                         return 0;
1620                     }
1621                     if (sm->isTypeInfoDeclaration()) // Bugzilla 15177
1622                         return 0;
1623                     PushIdentsDg *pid = (PushIdentsDg *)ctx;
1624                     if (!pid->sds->isModule() && sm->isImport()) // Bugzilla 17057
1625                         return 0;
1626 
1627                     //printf("\t%s\n", sm->ident->toChars());
1628                     Identifiers *idents = pid->idents;
1629 
1630                     /* Skip if already present in idents[]
1631                      */
1632                     for (size_t j = 0; j < idents->length; j++)
1633                     {
1634                         Identifier *id = (*idents)[j];
1635                         if (id == sm->ident)
1636                             return 0;
1637                     }
1638 
1639                     idents->push(sm->ident);
1640                 }
1641                 else
1642                 {
1643                     EnumDeclaration *ed = sm->isEnumDeclaration();
1644                     if (ed)
1645                     {
1646                         ScopeDsymbol_foreach(NULL, ed->members, &PushIdentsDg::dg, ctx);
1647                     }
1648                 }
1649                 return 0;
1650             }
1651         };
1652 
1653         Identifiers *idents = new Identifiers;
1654         PushIdentsDg ctx;
1655         ctx.sds = sds;
1656         ctx.idents = idents;
1657         ScopeDsymbol_foreach(sc, sds->members, &PushIdentsDg::dg, &ctx);
1658         ClassDeclaration *cd = sds->isClassDeclaration();
1659         if (cd && e->ident == Id::allMembers)
1660         {
1661             if (cd->semanticRun < PASSsemanticdone)
1662                 dsymbolSemantic(cd, NULL);    // Bugzilla 13668: Try to resolve forward reference
1663 
1664             struct PushBaseMembers
1665             {
1666                 static void dg(ClassDeclaration *cd, PushIdentsDg *ctx)
1667                 {
1668                     for (size_t i = 0; i < cd->baseclasses->length; i++)
1669                     {
1670                         ClassDeclaration *cb = (*cd->baseclasses)[i]->sym;
1671                         assert(cb);
1672                         ScopeDsymbol_foreach(NULL, cb->members, &PushIdentsDg::dg, ctx);
1673                         if (cb->baseclasses->length)
1674                             dg(cb, ctx);
1675                     }
1676                 }
1677             };
1678             PushBaseMembers::dg(cd, &ctx);
1679         }
1680 
1681         // Turn Identifiers into StringExps reusing the allocated array
1682         assert(sizeof(Expressions) == sizeof(Identifiers));
1683         Expressions *exps = (Expressions *)idents;
1684         for (size_t i = 0; i < idents->length; i++)
1685         {
1686             Identifier *id = (*idents)[i];
1687             StringExp *se = new StringExp(e->loc, const_cast<char *>(id->toChars()));
1688             (*exps)[i] = se;
1689         }
1690 
1691         /* Making this a tuple is more flexible, as it can be statically unrolled.
1692          * To make an array literal, enclose __traits in [ ]:
1693          *   [ __traits(allMembers, ...) ]
1694          */
1695         Expression *ex = new TupleExp(e->loc, exps);
1696         ex = expressionSemantic(ex, sc);
1697         return ex;
1698     }
1699     else if (e->ident == Id::compiles)
1700     {
1701         /* Determine if all the objects - types, expressions, or symbols -
1702          * compile without error
1703          */
1704         if (!dim)
1705             return False(e);
1706 
1707         for (size_t i = 0; i < dim; i++)
1708         {
1709             unsigned errors = global.startGagging();
1710             Scope *sc2 = sc->push();
1711             sc2->tinst = NULL;
1712             sc2->minst = NULL;
1713             sc2->flags = (sc->flags & ~(SCOPEctfe | SCOPEcondition)) | SCOPEcompile | SCOPEfullinst;
1714             bool err = false;
1715 
1716             RootObject *o = (*e->args)[i];
1717             Type *t = isType(o);
1718             while (t)
1719             {
1720                 if (TypeMixin *tm = t->isTypeMixin())
1721                 {
1722                     /* The mixin string could be a type or an expression.
1723                      * Have to try compiling it to see.
1724                      */
1725                     OutBuffer buf;
1726                     if (expressionsToString(buf, sc, tm->exps))
1727                     {
1728                         err = true;
1729                         break;
1730                     }
1731                     const size_t len = buf.length();
1732                     const char *str = buf.extractChars();
1733                     Parser p(e->loc, sc->_module, (const utf8_t *)str, len, false);
1734                     p.nextToken();
1735                     //printf("p.loc.linnum = %d\n", p.loc.linnum);
1736 
1737                     o = p.parseTypeOrAssignExp(TOKeof);
1738                     if (p.errors || p.token.value != TOKeof)
1739                     {
1740                         err = true;
1741                         break;
1742                     }
1743                     t = isType(o);
1744                 }
1745                 else
1746                     break;
1747             }
1748 
1749             if (!err)
1750             {
1751                 Expression *ex = t ? typeToExpression(t) : isExpression(o);
1752                 if (!ex && t)
1753                 {
1754                     Dsymbol *s;
1755                     t->resolve(e->loc, sc2, &ex, &t, &s);
1756                     if (t)
1757                     {
1758                         typeSemantic(t, e->loc, sc2);
1759                         if (t->ty == Terror)
1760                             err = true;
1761                     }
1762                     else if (s && s->errors)
1763                         err = true;
1764                 }
1765                 if (ex)
1766                 {
1767                     ex = expressionSemantic(ex, sc2);
1768                     ex = resolvePropertiesOnly(sc2, ex);
1769                     ex = ex->optimize(WANTvalue);
1770                     if (sc2->func && sc2->func->type->ty == Tfunction)
1771                     {
1772                         TypeFunction *tf = (TypeFunction *)sc2->func->type;
1773                         canThrow(ex, sc2->func, tf->isnothrow);
1774                     }
1775                     ex = checkGC(sc2, ex);
1776                     if (ex->op == TOKerror)
1777                         err = true;
1778                 }
1779             }
1780 
1781             // Carefully detach the scope from the parent and throw it away as
1782             // we only need it to evaluate the expression
1783             // https://issues.dlang.org/show_bug.cgi?id=15428
1784             freeFieldinit(sc2);
1785             sc2->enclosing = NULL;
1786             sc2->pop();
1787 
1788             if (global.endGagging(errors) || err)
1789             {
1790                 return False(e);
1791             }
1792         }
1793         return True(e);
1794     }
1795     else if (e->ident == Id::isSame)
1796     {
1797         /* Determine if two symbols are the same
1798          */
1799         if (dim != 2)
1800             return dimError(e, 2, dim);
1801 
1802         if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0))
1803             return new ErrorExp();
1804 
1805         RootObject *o1 = (*e->args)[0];
1806         RootObject *o2 = (*e->args)[1];
1807 
1808         // issue 12001, allow isSame, <BasicType>, <BasicType>
1809         Type *t1 = isType(o1);
1810         Type *t2 = isType(o2);
1811         if (t1 && t2 && t1->equals(t2))
1812             return True(e);
1813 
1814         Dsymbol *s1 = getDsymbol(o1);
1815         Dsymbol *s2 = getDsymbol(o2);
1816         //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars());
1817         if (!s1 && !s2)
1818         {
1819             Expression *ea1 = isExpression(o1);
1820             Expression *ea2 = isExpression(o2);
1821             if (ea1 && ea2)
1822             {
1823                 if (ea1->equals(ea2))
1824                     return True(e);
1825             }
1826         }
1827         if (!s1 || !s2)
1828             return False(e);
1829         s1 = s1->toAlias();
1830         s2 = s2->toAlias();
1831 
1832         if (s1->isFuncAliasDeclaration())
1833             s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc();
1834         if (s2->isFuncAliasDeclaration())
1835             s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc();
1836 
1837         return (s1 == s2) ? True(e) : False(e);
1838     }
1839     else if (e->ident == Id::getUnitTests)
1840     {
1841         if (dim != 1)
1842             return dimError(e, 1, dim);
1843 
1844         RootObject *o = (*e->args)[0];
1845         Dsymbol *s = getDsymbolWithoutExpCtx(o);
1846         if (!s)
1847         {
1848             e->error("argument %s to __traits(getUnitTests) must be a module or aggregate",
1849                 o->toChars());
1850             return new ErrorExp();
1851         }
1852         if (Import *imp = s->isImport())  // Bugzilla 10990
1853             s = imp->mod;
1854 
1855         ScopeDsymbol* sds = s->isScopeDsymbol();
1856         if (!sds)
1857         {
1858             e->error("argument %s to __traits(getUnitTests) must be a module or aggregate, not a %s",
1859                 s->toChars(), s->kind());
1860             return new ErrorExp();
1861         }
1862 
1863         Expressions *exps = new Expressions();
1864         if (global.params.useUnitTests)
1865         {
1866             // Should actually be a set
1867             AA* uniqueUnitTests = NULL;
1868             collectUnitTests(sds->members, uniqueUnitTests, exps);
1869         }
1870         TupleExp *te= new TupleExp(e->loc, exps);
1871         return expressionSemantic(te, sc);
1872     }
1873     else if (e->ident == Id::getVirtualIndex)
1874     {
1875         if (dim != 1)
1876             return dimError(e, 1, dim);
1877 
1878         RootObject *o = (*e->args)[0];
1879         Dsymbol *s = getDsymbolWithoutExpCtx(o);
1880 
1881         FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
1882         if (!fd)
1883         {
1884             e->error("first argument to __traits(getVirtualIndex) must be a function");
1885             return new ErrorExp();
1886         }
1887 
1888         fd = fd->toAliasFunc(); // Neccessary to support multiple overloads.
1889         return new IntegerExp(e->loc, fd->vtblIndex, Type::tptrdiff_t);
1890     }
1891     else if (e->ident == Id::getPointerBitmap)
1892     {
1893         return pointerBitmap(e);
1894     }
1895     else if (e->ident == Id::isZeroInit)
1896     {
1897         if (dim != 1)
1898             return dimError(e, 1, dim);
1899 
1900         RootObject *o = (*e->args)[0];
1901         Type *t = isType(o);
1902         if (!t)
1903         {
1904             e->error("type expected as second argument of __traits `%s` instead of `%s`",
1905                 e->ident->toChars(), o->toChars());
1906             return new ErrorExp();
1907         }
1908 
1909         Type *tb = t->baseElemOf();
1910         return tb->isZeroInit(e->loc) ? True(e) : False(e);
1911     }
1912     else if (e->ident == Id::getTargetInfo)
1913     {
1914         if (dim != 1)
1915             return dimError(e, 1, dim);
1916 
1917         Expression *ex = isExpression((*e->args)[0]);
1918         StringExp *se = ex ? ex->ctfeInterpret()->toStringExp() : NULL;
1919         if (!ex || !se || se->len == 0)
1920         {
1921             e->error("string expected as argument of __traits `%s` instead of `%s`", e->ident->toChars(), ex->toChars());
1922             return new ErrorExp();
1923         }
1924         se = se->toUTF8(sc);
1925 
1926         Expression *r = target.getTargetInfo(se->toPtr(), e->loc);
1927         if (!r)
1928         {
1929             e->error("`getTargetInfo` key `\"%s\"` not supported by this implementation", se->toPtr());
1930             return new ErrorExp();
1931         }
1932         return expressionSemantic(r, sc);
1933     }
1934     else if (e->ident == Id::getLocation)
1935     {
1936         if (dim != 1)
1937             return dimError(e, 1, dim);
1938         RootObject *arg0 = (*e->args)[0];
1939         Dsymbol *s = getDsymbolWithoutExpCtx(arg0);
1940         if (!s || !s->loc.filename)
1941         {
1942             e->error("can only get the location of a symbol, not `%s`", arg0->toChars());
1943             return new ErrorExp();
1944         }
1945 
1946         const FuncDeclaration *fd = s->isFuncDeclaration();
1947         if (fd && fd->overnext)
1948         {
1949             e->error("cannot get location of an overload set, "
1950                      "use `__traits(getOverloads, ..., \"%s\"%s)[N]` "
1951                      "to get the Nth overload",
1952                      arg0->toChars(), "");
1953             return new ErrorExp();
1954         }
1955 
1956         Expressions *exps = new Expressions();
1957         exps->setDim(3);
1958         (*exps)[0] = new StringExp(e->loc, const_cast<char *>(s->loc.filename), strlen(s->loc.filename));
1959         (*exps)[1] = new IntegerExp(e->loc, s->loc.linnum, Type::tint32);
1960         (*exps)[2] = new IntegerExp(e->loc, s->loc.charnum, Type::tint32);
1961         TupleExp *tup = new TupleExp(e->loc, exps);
1962         return expressionSemantic(tup, sc);
1963     }
1964 
1965     if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
1966         e->error("unrecognized trait `%s`, did you mean `%s`?", e->ident->toChars(), sub);
1967     else
1968         e->error("unrecognized trait `%s`", e->ident->toChars());
1969     return new ErrorExp();
1970 
1971     e->error("wrong number of arguments %d", (int)dim);
1972     return new ErrorExp();
1973 }
1974