5fd4b486a9bd94483fc7e0ace9903b3b4dd7eaad
[gcc.git] / gcc / d / dmd / traits.c
1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2020 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 *trySemantic(Expression *e, Scope *sc);
43 Expression *semantic(Expression *e, Scope *sc);
44 Expression *typeToExpression(Type *t);
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 */
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
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 */
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 */
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
189 static Expression *True(TraitsExp *e) { return new IntegerExp(e->loc, true, Type::tbool); }
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 */
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
262 static bool isTypeArithmetic(Type *t) { return t->isintegral() || t->isfloating(); }
263 static bool isTypeFloating(Type *t) { return t->isfloating(); }
264 static bool isTypeIntegral(Type *t) { return t->isintegral(); }
265 static bool isTypeScalar(Type *t) { return t->isscalar(); }
266 static bool isTypeUnsigned(Type *t) { return t->isunsigned(); }
267 static bool isTypeAssociativeArray(Type *t) { return t->toBasetype()->ty == Taarray; }
268 static bool isTypeStaticArray(Type *t) { return t->toBasetype()->ty == Tsarray; }
269 static bool isTypeAbstractClass(Type *t) { return t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract(); }
270 static bool isTypeFinalClass(Type *t) { return t->toBasetype()->ty == Tclass && (((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) != 0; }
271
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
285 static bool isDsymDeprecated(Dsymbol *s) { return s->isDeprecated(); }
286
287 static int fpisTemplate(void *, Dsymbol *s)
288 {
289 if (s->isTemplateDeclaration())
290 return 1;
291
292 return 0;
293 }
294
295 bool isTemplate(Dsymbol *s)
296 {
297 if (!s->toAlias()->isOverloadable())
298 return false;
299
300 return overloadApply(s, NULL, &fpisTemplate) != 0;
301 }
302
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
316 static bool isFuncAbstractFunction(FuncDeclaration *f) { return f->isAbstract(); }
317 static bool isFuncVirtualFunction(FuncDeclaration *f) { return f->isVirtual(); }
318 static bool isFuncVirtualMethod(FuncDeclaration *f) { return f->isVirtualMethod(); }
319 static bool isFuncFinalFunction(FuncDeclaration *f) { return f->isFinalFunc(); }
320 static bool isFuncStaticFunction(FuncDeclaration *f) { return !f->needThis() && !f->isNested(); }
321 static bool isFuncOverrideFunction(FuncDeclaration *f) { return f->isOverride(); }
322
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
339 static bool isDeclDisabled(Declaration *d) { return d->isDisabled(); }
340 static bool isDeclFuture(Declaration *d) { return d->isFuture(); }
341 static bool isDeclRef(Declaration *d) { return d->isRef(); }
342 static bool isDeclOut(Declaration *d) { return d->isOut(); }
343 static bool isDeclLazy(Declaration *d) { return (d->storage_class & STClazy) != 0; }
344
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
361 static bool isPkgModule(Package *p) { return p->isModule() || p->isPackageMod(); }
362 static bool isPkgPackage(Package *p) { return p->isModule() == NULL; }
363
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
385 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
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 "parameters",
448 "getAliasThis",
449 "getAttributes",
450 "getFunctionAttributes",
451 "getFunctionVariadicStyle",
452 "getParameterStorageClasses",
453 "getUnitTests",
454 "getVirtualIndex",
455 "getPointerBitmap",
456 "isZeroInit",
457 "getTargetInfo",
458 "getLocation",
459 "hasPostblit",
460 "isCopyable",
461 NULL
462 };
463
464 traitsStringTable._init(56);
465
466 for (size_t idx = 0;; idx++)
467 {
468 const char *s = traits[idx];
469 if (!s) break;
470 StringValue *sv = traitsStringTable.insert(s, strlen(s), const_cast<char *>(s));
471 assert(sv);
472 }
473 }
474
475 void *trait_search_fp(void *, const char *seed, int* cost)
476 {
477 //printf("trait_search_fp('%s')\n", seed);
478 size_t len = strlen(seed);
479 if (!len)
480 return NULL;
481
482 *cost = 0;
483 StringValue *sv = traitsStringTable.lookup(seed, len);
484 return sv ? (void*)sv->ptrvalue : NULL;
485 }
486
487 /**
488 * get an array of size_t values that indicate possible pointer words in memory
489 * if interpreted as the type given as argument
490 * the first array element is the size of the type for independent interpretation
491 * of the array
492 * following elements bits represent one word (4/8 bytes depending on the target
493 * architecture). If set the corresponding memory might contain a pointer/reference.
494 *
495 * [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...]
496 */
497 Expression *pointerBitmap(TraitsExp *e)
498 {
499 if (!e->args || e->args->length != 1)
500 {
501 error(e->loc, "a single type expected for trait pointerBitmap");
502 return new ErrorExp();
503 }
504 Type *t = getType((*e->args)[0]);
505 if (!t)
506 {
507 error(e->loc, "%s is not a type", (*e->args)[0]->toChars());
508 return new ErrorExp();
509 }
510 d_uns64 sz;
511 if (t->ty == Tclass && !((TypeClass*)t)->sym->isInterfaceDeclaration())
512 sz = ((TypeClass*)t)->sym->AggregateDeclaration::size(e->loc);
513 else
514 sz = t->size(e->loc);
515 if (sz == SIZE_INVALID)
516 return new ErrorExp();
517
518 const d_uns64 sz_size_t = Type::tsize_t->size(e->loc);
519 if (sz > UINT64_MAX - sz_size_t)
520 {
521 error(e->loc, "size overflow for type %s", t->toChars());
522 return new ErrorExp();
523 }
524
525 d_uns64 bitsPerWord = sz_size_t * 8;
526 d_uns64 cntptr = (sz + sz_size_t - 1) / sz_size_t;
527 d_uns64 cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
528 Array<d_uns64> data;
529 data.setDim((size_t)cntdata);
530 data.zero();
531
532 class PointerBitmapVisitor : public Visitor
533 {
534 public:
535 PointerBitmapVisitor(Array<d_uns64>* _data, d_uns64 _sz_size_t)
536 : data(_data), offset(0), sz_size_t(_sz_size_t), error(false)
537 {}
538
539 void setpointer(d_uns64 off)
540 {
541 d_uns64 ptroff = off / sz_size_t;
542 (*data)[(size_t)(ptroff / (8 * sz_size_t))] |= 1LL << (ptroff % (8 * sz_size_t));
543 }
544 virtual void visit(Type *t)
545 {
546 Type *tb = t->toBasetype();
547 if (tb != t)
548 tb->accept(this);
549 }
550 virtual void visit(TypeError *t) { visit((Type *)t); }
551 virtual void visit(TypeNext *) { assert(0); }
552 virtual void visit(TypeBasic *t)
553 {
554 if (t->ty == Tvoid)
555 setpointer(offset);
556 }
557 virtual void visit(TypeVector *) { }
558 virtual void visit(TypeArray *) { assert(0); }
559 virtual void visit(TypeSArray *t)
560 {
561 d_uns64 arrayoff = offset;
562 d_uns64 nextsize = t->next->size();
563 if (nextsize == SIZE_INVALID)
564 error = true;
565 d_uns64 dim = t->dim->toInteger();
566 for (d_uns64 i = 0; i < dim; i++)
567 {
568 offset = arrayoff + i * nextsize;
569 t->next->accept(this);
570 }
571 offset = arrayoff;
572 }
573 virtual void visit(TypeDArray *) { setpointer(offset + sz_size_t); } // dynamic array is {length,ptr}
574 virtual void visit(TypeAArray *) { setpointer(offset); }
575 virtual void visit(TypePointer *t)
576 {
577 if (t->nextOf()->ty != Tfunction) // don't mark function pointers
578 setpointer(offset);
579 }
580 virtual void visit(TypeReference *) { setpointer(offset); }
581 virtual void visit(TypeClass *) { setpointer(offset); }
582 virtual void visit(TypeFunction *) { }
583 virtual void visit(TypeDelegate *) { setpointer(offset); } // delegate is {context, function}
584 virtual void visit(TypeQualified *) { assert(0); } // assume resolved
585 virtual void visit(TypeIdentifier *) { assert(0); }
586 virtual void visit(TypeInstance *) { assert(0); }
587 virtual void visit(TypeTypeof *) { assert(0); }
588 virtual void visit(TypeReturn *) { assert(0); }
589 virtual void visit(TypeEnum *t) { visit((Type *)t); }
590 virtual void visit(TypeTuple *t) { visit((Type *)t); }
591 virtual void visit(TypeSlice *) { assert(0); }
592 virtual void visit(TypeNull *) { } // always a null pointer
593
594 virtual void visit(TypeStruct *t)
595 {
596 d_uns64 structoff = offset;
597 for (size_t i = 0; i < t->sym->fields.length; i++)
598 {
599 VarDeclaration *v = t->sym->fields[i];
600 offset = structoff + v->offset;
601 if (v->type->ty == Tclass)
602 setpointer(offset);
603 else
604 v->type->accept(this);
605 }
606 offset = structoff;
607 }
608
609 // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references
610 void visitClass(TypeClass* t)
611 {
612 d_uns64 classoff = offset;
613
614 // skip vtable-ptr and monitor
615 if (t->sym->baseClass)
616 visitClass((TypeClass*)t->sym->baseClass->type);
617
618 for (size_t i = 0; i < t->sym->fields.length; i++)
619 {
620 VarDeclaration *v = t->sym->fields[i];
621 offset = classoff + v->offset;
622 v->type->accept(this);
623 }
624 offset = classoff;
625 }
626
627 Array<d_uns64>* data;
628 d_uns64 offset;
629 d_uns64 sz_size_t;
630 bool error;
631 };
632
633 PointerBitmapVisitor pbv(&data, sz_size_t);
634 if (t->ty == Tclass)
635 pbv.visitClass((TypeClass*)t);
636 else
637 t->accept(&pbv);
638 if (pbv.error)
639 return new ErrorExp();
640
641 Expressions* exps = new Expressions;
642 exps->push(new IntegerExp(e->loc, sz, Type::tsize_t));
643 for (d_uns64 i = 0; i < cntdata; i++)
644 exps->push(new IntegerExp(e->loc, data[(size_t)i], Type::tsize_t));
645
646 ArrayLiteralExp* ale = new ArrayLiteralExp(e->loc, Type::tsize_t->sarrayOf(cntdata + 1), exps);
647 return ale;
648 }
649
650 static Expression *dimError(TraitsExp *e, int expected, int dim)
651 {
652 e->error("expected %d arguments for `%s` but had %d", expected, e->ident->toChars(), dim);
653 return new ErrorExp();
654 }
655
656 Expression *semanticTraits(TraitsExp *e, Scope *sc)
657 {
658 if (e->ident != Id::compiles &&
659 e->ident != Id::isSame &&
660 e->ident != Id::identifier &&
661 e->ident != Id::getProtection && e->ident != Id::getVisibility &&
662 e->ident != Id::getAttributes)
663 {
664 // Pretend we're in a deprecated scope so that deprecation messages
665 // aren't triggered when checking if a symbol is deprecated
666 const StorageClass save = sc->stc;
667 if (e->ident == Id::isDeprecated)
668 sc->stc |= STCdeprecated;
669 if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1))
670 {
671 sc->stc = save;
672 return new ErrorExp();
673 }
674 sc->stc = save;
675 }
676 size_t dim = e->args ? e->args->length : 0;
677
678 if (e->ident == Id::isArithmetic)
679 {
680 return isTypeX(e, &isTypeArithmetic);
681 }
682 else if (e->ident == Id::isFloating)
683 {
684 return isTypeX(e, &isTypeFloating);
685 }
686 else if (e->ident == Id::isIntegral)
687 {
688 return isTypeX(e, &isTypeIntegral);
689 }
690 else if (e->ident == Id::isScalar)
691 {
692 return isTypeX(e, &isTypeScalar);
693 }
694 else if (e->ident == Id::isUnsigned)
695 {
696 return isTypeX(e, &isTypeUnsigned);
697 }
698 else if (e->ident == Id::isAssociativeArray)
699 {
700 return isTypeX(e, &isTypeAssociativeArray);
701 }
702 else if (e->ident == Id::isDeprecated)
703 {
704 return isDsymX(e, &isDsymDeprecated);
705 }
706 else if (e->ident == Id::isFuture)
707 {
708 return isDeclX(e, &isDeclFuture);
709 }
710 else if (e->ident == Id::isStaticArray)
711 {
712 return isTypeX(e, &isTypeStaticArray);
713 }
714 else if (e->ident == Id::isAbstractClass)
715 {
716 return isTypeX(e, &isTypeAbstractClass);
717 }
718 else if (e->ident == Id::isFinalClass)
719 {
720 return isTypeX(e, &isTypeFinalClass);
721 }
722 else if (e->ident == Id::isTemplate)
723 {
724 if (dim != 1)
725 return dimError(e, 1, dim);
726
727 return isDsymX(e, &isTemplate);
728 }
729 else if (e->ident == Id::isPOD)
730 {
731 if (dim != 1)
732 return dimError(e, 1, dim);
733
734 RootObject *o = (*e->args)[0];
735 Type *t = isType(o);
736 if (!t)
737 {
738 e->error("type expected as second argument of __traits %s instead of %s",
739 e->ident->toChars(), o->toChars());
740 return new ErrorExp();
741 }
742
743 Type *tb = t->baseElemOf();
744 if (StructDeclaration *sd = (tb->ty == Tstruct) ? ((TypeStruct *)tb)->sym : NULL)
745 {
746 return (sd->isPOD()) ? True(e) : False(e);
747 }
748 return True(e);
749 }
750 else if (e->ident == Id::hasPostblit)
751 {
752 if (dim != 1)
753 return dimError(e, 1, dim);
754
755 RootObject *o = (*e->args)[0];
756 Type *t = isType(o);
757 if (!t)
758 {
759 e->error("type expected as second argument of __traits %s instead of %s",
760 e->ident->toChars(), o->toChars());
761 return new ErrorExp();
762 }
763
764 Type *tb = t->baseElemOf();
765 if (StructDeclaration *sd = (tb->ty == Tstruct) ? ((TypeStruct *)tb)->sym : NULL)
766 {
767 return sd->postblit ? True(e) : False(e);
768 }
769 return False(e);
770 }
771 else if (e->ident == Id::isCopyable)
772 {
773 if (dim != 1)
774 return dimError(e, 1, dim);
775
776 RootObject *o = (*e->args)[0];
777 Type *t = isType(o);
778 if (!t)
779 {
780 e->error("type expected as second argument of __traits %s instead of %s",
781 e->ident->toChars(), o->toChars());
782 return new ErrorExp();
783 }
784
785 return isCopyable(t) ? True(e) : False(e);
786 }
787 else if (e->ident == Id::isNested)
788 {
789 if (dim != 1)
790 return dimError(e, 1, dim);
791
792 RootObject *o = (*e->args)[0];
793 Dsymbol *s = getDsymbolWithoutExpCtx(o);
794 if (!s)
795 {
796 }
797 else if (AggregateDeclaration *a = s->isAggregateDeclaration())
798 {
799 return a->isNested() ? True(e) : False(e);
800 }
801 else if (FuncDeclaration *f = s->isFuncDeclaration())
802 {
803 return f->isNested() ? True(e) : False(e);
804 }
805
806 e->error("aggregate or function expected instead of '%s'", o->toChars());
807 return new ErrorExp();
808 }
809 else if (e->ident == Id::isDisabled)
810 {
811 if (dim != 1)
812 return dimError(e, 1, dim);
813
814 return isDeclX(e, &isDeclDisabled);
815 }
816 else if (e->ident == Id::isAbstractFunction)
817 {
818 if (dim != 1)
819 return dimError(e, 1, dim);
820
821 return isFuncX(e, &isFuncAbstractFunction);
822 }
823 else if (e->ident == Id::isVirtualFunction)
824 {
825 if (dim != 1)
826 return dimError(e, 1, dim);
827
828 return isFuncX(e, &isFuncVirtualFunction);
829 }
830 else if (e->ident == Id::isVirtualMethod)
831 {
832 if (dim != 1)
833 return dimError(e, 1, dim);
834
835 return isFuncX(e, &isFuncVirtualMethod);
836 }
837 else if (e->ident == Id::isFinalFunction)
838 {
839 if (dim != 1)
840 return dimError(e, 1, dim);
841
842 return isFuncX(e, &isFuncFinalFunction);
843 }
844 else if (e->ident == Id::isOverrideFunction)
845 {
846 if (dim != 1)
847 return dimError(e, 1, dim);
848
849 return isFuncX(e, &isFuncOverrideFunction);
850 }
851 else if (e->ident == Id::isStaticFunction)
852 {
853 if (dim != 1)
854 return dimError(e, 1, dim);
855
856 return isFuncX(e, &isFuncStaticFunction);
857 }
858 else if (e->ident == Id::isModule)
859 {
860 if (dim != 1)
861 return dimError(e, 1, dim);
862
863 return isPkgX(e, &isPkgModule);
864 }
865 else if (e->ident == Id::isPackage)
866 {
867 if (dim != 1)
868 return dimError(e, 1, dim);
869
870 return isPkgX(e, &isPkgPackage);
871 }
872 else if (e->ident == Id::isRef)
873 {
874 if (dim != 1)
875 return dimError(e, 1, dim);
876
877 return isDeclX(e, &isDeclRef);
878 }
879 else if (e->ident == Id::isOut)
880 {
881 if (dim != 1)
882 return dimError(e, 1, dim);
883
884 return isDeclX(e, &isDeclOut);
885 }
886 else if (e->ident == Id::isLazy)
887 {
888 if (dim != 1)
889 return dimError(e, 1, dim);
890
891 return isDeclX(e, &isDeclLazy);
892 }
893 else if (e->ident == Id::identifier)
894 {
895 // Get identifier for symbol as a string literal
896 /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
897 * a symbol should not be folded to a constant.
898 * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
899 */
900 if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2))
901 return new ErrorExp();
902 if (dim != 1)
903 return dimError(e, 1, dim);
904
905 RootObject *o = (*e->args)[0];
906 Identifier *id = NULL;
907 if (Parameter *po = isParameter(o))
908 {
909 if (!po->ident)
910 {
911 e->error("argument `%s` has no identifier", po->type->toChars());
912 return new ErrorExp();
913 }
914 id = po->ident;
915 }
916 else
917 {
918 Dsymbol *s = getDsymbolWithoutExpCtx(o);
919 if (!s || !s->ident)
920 {
921 e->error("argument %s has no identifier", o->toChars());
922 return new ErrorExp();
923 }
924 id = s->ident;
925 }
926
927 StringExp *se = new StringExp(e->loc, const_cast<char *>(id->toChars()));
928 return semantic(se, sc);
929 }
930 else if (e->ident == Id::getProtection || e->ident == Id::getVisibility)
931 {
932 if (dim != 1)
933 return dimError(e, 1, dim);
934
935 Scope *sc2 = sc->push();
936 sc2->flags = sc->flags | SCOPEnoaccesscheck | SCOPEignoresymbolvisibility;
937 bool ok = TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1);
938 sc2->pop();
939 if (!ok)
940 return new ErrorExp();
941
942 RootObject *o = (*e->args)[0];
943 Dsymbol *s = getDsymbolWithoutExpCtx(o);
944 if (!s)
945 {
946 if (!isError(o))
947 e->error("argument %s has no protection", o->toChars());
948 return new ErrorExp();
949 }
950 if (s->semanticRun == PASSinit)
951 s->semantic(NULL);
952
953 const char *protName = protectionToChars(s->prot().kind); // TODO: How about package(names)
954 assert(protName);
955 StringExp *se = new StringExp(e->loc, const_cast<char *>(protName));
956 return semantic(se, sc);
957 }
958 else if (e->ident == Id::parent)
959 {
960 if (dim != 1)
961 return dimError(e, 1, dim);
962
963 RootObject *o = (*e->args)[0];
964 Dsymbol *s = getDsymbolWithoutExpCtx(o);
965 if (s)
966 {
967 if (FuncDeclaration *fd = s->isFuncDeclaration()) // Bugzilla 8943
968 s = fd->toAliasFunc();
969 if (!s->isImport()) // Bugzilla 8922
970 s = s->toParent();
971 }
972 if (!s || s->isImport())
973 {
974 e->error("argument %s has no parent", o->toChars());
975 return new ErrorExp();
976 }
977
978 if (FuncDeclaration *f = s->isFuncDeclaration())
979 {
980 if (TemplateDeclaration *td = getFuncTemplateDecl(f))
981 {
982 if (td->overroot) // if not start of overloaded list of TemplateDeclaration's
983 td = td->overroot; // then get the start
984 Expression *ex = new TemplateExp(e->loc, td, f);
985 ex = semantic(ex, sc);
986 return ex;
987 }
988
989 if (FuncLiteralDeclaration *fld = f->isFuncLiteralDeclaration())
990 {
991 // Directly translate to VarExp instead of FuncExp
992 Expression *ex = new VarExp(e->loc, fld, true);
993 return semantic(ex, sc);
994 }
995 }
996
997 return resolve(e->loc, sc, s, false);
998 }
999 else if (e->ident == Id::child)
1000 {
1001 if (dim != 2)
1002 return dimError(e, 2, dim);
1003
1004 Expression *ex;
1005 RootObject *op = (*e->args)[0];
1006 if (Dsymbol *symp = getDsymbol(op))
1007 ex = new DsymbolExp(e->loc, symp);
1008 else if (Expression *exp = isExpression(op))
1009 ex = exp;
1010 else
1011 {
1012 e->error("symbol or expression expected as first argument of __traits `child` instead of `%s`", op->toChars());
1013 return new ErrorExp();
1014 }
1015
1016 ex = semantic(ex, sc);
1017 RootObject *oc = (*e->args)[1];
1018 Dsymbol *symc = getDsymbol(oc);
1019 if (!symc)
1020 {
1021 e->error("symbol expected as second argument of __traits `child` instead of `%s`", oc->toChars());
1022 return new ErrorExp();
1023 }
1024
1025 if (Declaration *d = symc->isDeclaration())
1026 ex = new DotVarExp(e->loc, ex, d);
1027 else if (TemplateDeclaration *td = symc->isTemplateDeclaration())
1028 ex = new DotExp(e->loc, ex, new TemplateExp(e->loc, td));
1029 else if (ScopeDsymbol *ti = symc->isScopeDsymbol())
1030 ex = new DotExp(e->loc, ex, new ScopeExp(e->loc, ti));
1031 else
1032 assert(0);
1033
1034 ex = semantic(ex, sc);
1035 return ex;
1036 }
1037 else if (e->ident == Id::hasMember ||
1038 e->ident == Id::getMember ||
1039 e->ident == Id::getOverloads ||
1040 e->ident == Id::getVirtualMethods ||
1041 e->ident == Id::getVirtualFunctions)
1042 {
1043 if (dim != 2 && !(dim == 3 && e->ident == Id::getOverloads))
1044 return dimError(e, 2, dim);
1045
1046 RootObject *o = (*e->args)[0];
1047 Expression *ex = isExpression((*e->args)[1]);
1048 if (!ex)
1049 {
1050 e->error("expression expected as second argument of __traits %s", e->ident->toChars());
1051 return new ErrorExp();
1052 }
1053 ex = ex->ctfeInterpret();
1054
1055 bool includeTemplates = false;
1056 if (dim == 3 && e->ident == Id::getOverloads)
1057 {
1058 Expression *b = isExpression((*e->args)[2]);
1059 b = b->ctfeInterpret();
1060 if (!b->type->equals(Type::tbool))
1061 {
1062 e->error("`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b->toChars(), b->type->toChars());
1063 return new ErrorExp();
1064 }
1065 includeTemplates = b->isBool(true);
1066 }
1067
1068 StringExp *se = ex->toStringExp();
1069 if (!se || se->len == 0)
1070 {
1071 e->error("string expected as second argument of __traits %s instead of %s", e->ident->toChars(), ex->toChars());
1072 return new ErrorExp();
1073 }
1074 se = se->toUTF8(sc);
1075
1076 if (se->sz != 1)
1077 {
1078 e->error("string must be chars");
1079 return new ErrorExp();
1080 }
1081 Identifier *id = Identifier::idPool((char *)se->string, se->len);
1082
1083 /* Prefer dsymbol, because it might need some runtime contexts.
1084 */
1085 Dsymbol *sym = getDsymbol(o);
1086 if (sym)
1087 {
1088 if (e->ident == Id::hasMember)
1089 {
1090 if (sym->search(e->loc, id) != NULL)
1091 return True(e);
1092 }
1093 ex = new DsymbolExp(e->loc, sym);
1094 ex = new DotIdExp(e->loc, ex, id);
1095 }
1096 else if (Type *t = isType(o))
1097 ex = typeDotIdExp(e->loc, t, id);
1098 else if (Expression *ex2 = isExpression(o))
1099 ex = new DotIdExp(e->loc, ex2, id);
1100 else
1101 {
1102 e->error("invalid first argument");
1103 return new ErrorExp();
1104 }
1105
1106 if (e->ident == Id::hasMember)
1107 {
1108 /* Take any errors as meaning it wasn't found
1109 */
1110 Scope *scx = sc->push();
1111 scx->flags |= SCOPEignoresymbolvisibility;
1112 ex = trySemantic(ex, scx);
1113 scx->pop();
1114 return ex ? True(e) : False(e);
1115 }
1116 else if (e->ident == Id::getMember)
1117 {
1118 if (ex->op == TOKdotid)
1119 // Prevent semantic() from replacing Symbol with its initializer
1120 ((DotIdExp *)ex)->wantsym = true;
1121 Scope *scx = sc->push();
1122 scx->flags |= SCOPEignoresymbolvisibility;
1123 ex = semantic(ex, scx);
1124 scx->pop();
1125 return ex;
1126 }
1127 else if (e->ident == Id::getVirtualFunctions ||
1128 e->ident == Id::getVirtualMethods ||
1129 e->ident == Id::getOverloads)
1130 {
1131 unsigned errors = global.errors;
1132 Expression *eorig = ex;
1133 Scope *scx = sc->push();
1134 scx->flags |= SCOPEignoresymbolvisibility;
1135 ex = semantic(ex, scx);
1136 if (errors < global.errors)
1137 e->error("%s cannot be resolved", eorig->toChars());
1138 //ex->print();
1139
1140 /* Create tuple of functions of ex
1141 */
1142 Expressions *exps = new Expressions();
1143 Dsymbol *f;
1144 if (ex->op == TOKvar)
1145 {
1146 VarExp *ve = (VarExp *)ex;
1147 f = ve->var->isFuncDeclaration();
1148 ex = NULL;
1149 }
1150 else if (ex->op == TOKdotvar)
1151 {
1152 DotVarExp *dve = (DotVarExp *)ex;
1153 f = dve->var->isFuncDeclaration();
1154 if (dve->e1->op == TOKdottype || dve->e1->op == TOKthis)
1155 ex = NULL;
1156 else
1157 ex = dve->e1;
1158 }
1159 else if (ex->op == TOKtemplate)
1160 {
1161 TemplateExp *te = (TemplateExp *)ex;
1162 TemplateDeclaration *td = te->td;
1163 f = td;
1164 if (td && td->funcroot)
1165 f = td->funcroot;
1166 ex = NULL;
1167 }
1168 else
1169 f = NULL;
1170 Ptrait p;
1171 p.sym = sym;
1172 p.exps = exps;
1173 p.e1 = ex;
1174 p.ident = e->ident;
1175 p.includeTemplates = includeTemplates;
1176 AA *funcTypeHash = NULL;
1177 p.funcTypeHash = &funcTypeHash;
1178
1179 InterfaceDeclaration *ifd = NULL;
1180 if (sym)
1181 ifd = sym->isInterfaceDeclaration();
1182 // If the symbol passed as a parameter is an
1183 // interface that inherits other interfaces
1184 if (ifd && ifd->interfaces.length)
1185 {
1186 // check the overloads of each inherited interface individually
1187 for (size_t i = 0; i < ifd->interfaces.length; i++)
1188 {
1189 BaseClass *bc = ifd->interfaces.ptr[i];
1190 if (Dsymbol *fd = bc->sym->search(e->loc, f->ident))
1191 overloadApply(fd, &p, &fptraits);
1192 }
1193 }
1194 else
1195 overloadApply(f, &p, &fptraits);
1196
1197 ex = new TupleExp(e->loc, exps);
1198 ex = semantic(ex, scx);
1199 scx->pop();
1200 return ex;
1201 }
1202 else
1203 assert(0);
1204 }
1205 else if (e->ident == Id::classInstanceSize)
1206 {
1207 if (dim != 1)
1208 return dimError(e, 1, dim);
1209
1210 RootObject *o = (*e->args)[0];
1211 Dsymbol *s = getDsymbol(o);
1212 ClassDeclaration *cd = s ? s->isClassDeclaration() : NULL;
1213 if (!cd)
1214 {
1215 e->error("first argument is not a class");
1216 return new ErrorExp();
1217 }
1218 if (cd->sizeok != SIZEOKdone)
1219 {
1220 cd->size(cd->loc);
1221 }
1222 if (cd->sizeok != SIZEOKdone)
1223 {
1224 e->error("%s %s is forward referenced", cd->kind(), cd->toChars());
1225 return new ErrorExp();
1226 }
1227
1228 return new IntegerExp(e->loc, cd->structsize, Type::tsize_t);
1229 }
1230 else if (e->ident == Id::getAliasThis)
1231 {
1232 if (dim != 1)
1233 return dimError(e, 1, dim);
1234
1235 RootObject *o = (*e->args)[0];
1236 Dsymbol *s = getDsymbol(o);
1237 AggregateDeclaration *ad = s ? s->isAggregateDeclaration() : NULL;
1238 if (!ad)
1239 {
1240 e->error("argument is not an aggregate type");
1241 return new ErrorExp();
1242 }
1243
1244 Expressions *exps = new Expressions();
1245 if (ad->aliasthis)
1246 exps->push(new StringExp(e->loc, const_cast<char *>(ad->aliasthis->ident->toChars())));
1247 Expression *ex = new TupleExp(e->loc, exps);
1248 ex = semantic(ex, sc);
1249 return ex;
1250 }
1251 else if (e->ident == Id::getAttributes)
1252 {
1253 /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
1254 * a symbol should not be folded to a constant.
1255 * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
1256 */
1257 if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 3))
1258 return new ErrorExp();
1259
1260 if (dim != 1)
1261 return dimError(e, 1, dim);
1262
1263 RootObject *o = (*e->args)[0];
1264 Parameter *po = isParameter(o);
1265 Dsymbol *s = getDsymbolWithoutExpCtx(o);
1266 UserAttributeDeclaration *udad = NULL;
1267 if (po)
1268 {
1269 udad = po->userAttribDecl;
1270 }
1271 else if (s)
1272 {
1273 if (Import *imp = s->isImport())
1274 {
1275 s = imp->mod;
1276 }
1277 //printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttribDecl, s->_scope);
1278 udad = s->userAttribDecl;
1279 }
1280 else
1281 {
1282 e->error("first argument is not a symbol");
1283 return new ErrorExp();
1284 }
1285
1286 Expressions *exps = udad ? udad->getAttributes() : new Expressions();
1287 TupleExp *tup = new TupleExp(e->loc, exps);
1288 return semantic(tup, sc);
1289 }
1290 else if (e->ident == Id::getFunctionAttributes)
1291 {
1292 /* extract all function attributes as a tuple (const/shared/inout/pure/nothrow/etc) except UDAs.
1293 * https://dlang.org/spec/traits.html#getFunctionAttributes
1294 */
1295 if (dim != 1)
1296 return dimError(e, 1, dim);
1297
1298 TypeFunction *tf = toTypeFunction((*e->args)[0]);
1299
1300 if (!tf)
1301 {
1302 e->error("first argument is not a function");
1303 return new ErrorExp();
1304 }
1305
1306 Expressions *mods = new Expressions();
1307 PushAttributes pa;
1308 pa.mods = mods;
1309 tf->modifiersApply(&pa, &PushAttributes::fp);
1310 tf->attributesApply(&pa, &PushAttributes::fp, TRUSTformatSystem);
1311
1312 TupleExp *tup = new TupleExp(e->loc, mods);
1313 return semantic(tup, sc);
1314 }
1315 else if (e->ident == Id::isReturnOnStack)
1316 {
1317 /* Extract as a boolean if function return value is on the stack
1318 * https://dlang.org/spec/traits.html#isReturnOnStack
1319 */
1320 if (dim != 1)
1321 return dimError(e, 1, dim);
1322
1323 RootObject *o = (*e->args)[0];
1324 FuncDeclaration *fd = NULL;
1325 TypeFunction *tf = toTypeFunction(o, &fd);
1326
1327 if (!tf)
1328 {
1329 e->error("argument to `__traits(isReturnOnStack, %s)` is not a function", o->toChars());
1330 return new ErrorExp();
1331 }
1332
1333 bool value = target.isReturnOnStack(tf, fd && fd->needThis());
1334 return new IntegerExp(e->loc, value, Type::tbool);
1335 }
1336 else if (e->ident == Id::getFunctionVariadicStyle)
1337 {
1338 /* Accept a symbol or a type. Returns one of the following:
1339 * "none" not a variadic function
1340 * "argptr" extern(D) void dstyle(...), use `__argptr` and `__arguments`
1341 * "stdarg" extern(C) void cstyle(int, ...), use core.stdc.stdarg
1342 * "typesafe" void typesafe(T[] ...)
1343 */
1344 // get symbol linkage as a string
1345 if (dim != 1)
1346 return dimError(e, 1, dim);
1347
1348 LINK link;
1349 VarArg varargs;
1350 RootObject *o = (*e->args)[0];
1351 FuncDeclaration *fd = NULL;
1352 TypeFunction *tf = toTypeFunction(o, &fd);
1353
1354 if (tf)
1355 {
1356 link = tf->linkage;
1357 varargs = tf->parameterList.varargs;
1358 }
1359 else
1360 {
1361 if (!fd)
1362 {
1363 e->error("argument to `__traits(getFunctionVariadicStyle, %s)` is not a function", o->toChars());
1364 return new ErrorExp();
1365 }
1366 link = fd->linkage;
1367 varargs = fd->getParameterList().varargs;
1368 }
1369 const char *style;
1370 switch (varargs)
1371 {
1372 case 0: style = "none"; break;
1373 case 1: style = (link == LINKd) ? "argptr"
1374 : "stdarg"; break;
1375 case 2: style = "typesafe"; break;
1376 default:
1377 assert(0);
1378 }
1379 StringExp *se = new StringExp(e->loc, const_cast<char*>(style));
1380 return semantic(se, sc);
1381 }
1382 else if (e->ident == Id::getParameterStorageClasses)
1383 {
1384 /* Accept a function symbol or a type, followed by a parameter index.
1385 * Returns a tuple of strings of the parameter's storage classes.
1386 */
1387 // get symbol linkage as a string
1388 if (dim != 2)
1389 return dimError(e, 2, dim);
1390
1391 RootObject *o = (*e->args)[0];
1392 RootObject *o1 = (*e->args)[1];
1393
1394 FuncDeclaration *fd = NULL;
1395 TypeFunction *tf = toTypeFunction(o, &fd);
1396
1397 ParameterList fparams;
1398 if (tf)
1399 {
1400 fparams = tf->parameterList;
1401 }
1402 else
1403 {
1404 if (!fd)
1405 {
1406 e->error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function",
1407 o->toChars(), o1->toChars());
1408 return new ErrorExp();
1409 }
1410 fparams = fd->getParameterList();
1411 }
1412
1413 StorageClass stc;
1414
1415 // Set stc to storage class of the ith parameter
1416 Expression *ex = isExpression((*e->args)[1]);
1417 if (!ex)
1418 {
1419 e->error("expression expected as second argument of `__traits(getParameterStorageClasses, %s, %s)`",
1420 o->toChars(), o1->toChars());
1421 return new ErrorExp();
1422 }
1423 ex = ex->ctfeInterpret();
1424 uinteger_t ii = ex->toUInteger();
1425 if (ii >= fparams.length())
1426 {
1427 e->error("parameter index must be in range 0..%u not %s", (unsigned)fparams.length(), ex->toChars());
1428 return new ErrorExp();
1429 }
1430
1431 unsigned n = (unsigned)ii;
1432 Parameter *p = fparams[n];
1433 stc = p->storageClass;
1434
1435 // This mirrors hdrgen.visit(Parameter p)
1436 if (p->type && p->type->mod & MODshared)
1437 stc &= ~STCshared;
1438
1439 Expressions *exps = new Expressions;
1440
1441 if (stc & STCauto)
1442 exps->push(new StringExp(e->loc, const_cast<char *>("auto")));
1443 if (stc & STCreturn)
1444 exps->push(new StringExp(e->loc, const_cast<char *>("return")));
1445
1446 if (stc & STCout)
1447 exps->push(new StringExp(e->loc, const_cast<char *>("out")));
1448 else if (stc & STCref)
1449 exps->push(new StringExp(e->loc, const_cast<char *>("ref")));
1450 else if (stc & STCin)
1451 exps->push(new StringExp(e->loc, const_cast<char *>("in")));
1452 else if (stc & STClazy)
1453 exps->push(new StringExp(e->loc, const_cast<char *>("lazy")));
1454 else if (stc & STCalias)
1455 exps->push(new StringExp(e->loc, const_cast<char *>("alias")));
1456
1457 if (stc & STCconst)
1458 exps->push(new StringExp(e->loc, const_cast<char *>("const")));
1459 if (stc & STCimmutable)
1460 exps->push(new StringExp(e->loc, const_cast<char *>("immutable")));
1461 if (stc & STCwild)
1462 exps->push(new StringExp(e->loc, const_cast<char *>("inout")));
1463 if (stc & STCshared)
1464 exps->push(new StringExp(e->loc, const_cast<char *>("shared")));
1465 if (stc & STCscope && !(stc & STCscopeinferred))
1466 exps->push(new StringExp(e->loc, const_cast<char *>("scope")));
1467
1468 TupleExp *tup = new TupleExp(e->loc, exps);
1469 return semantic(tup, sc);
1470 }
1471 else if (e->ident == Id::getLinkage)
1472 {
1473 // get symbol linkage as a string
1474 if (dim != 1)
1475 return dimError(e, 1, dim);
1476
1477 LINK link;
1478 RootObject *o = (*e->args)[0];
1479
1480 TypeFunction *tf = toTypeFunction(o);
1481
1482 if (tf)
1483 link = tf->linkage;
1484 else
1485 {
1486 Dsymbol *s = getDsymbol(o);
1487 Declaration *d = NULL;
1488 AggregateDeclaration *ad = NULL;
1489 if (!s || ((d = s->isDeclaration()) == NULL
1490 && (ad = s->isAggregateDeclaration()) == NULL))
1491 {
1492 e->error("argument to `__traits(getLinkage, %s)` is not a declaration", o->toChars());
1493 return new ErrorExp();
1494 }
1495 if (d != NULL)
1496 link = d->linkage;
1497 else
1498 {
1499 switch (ad->classKind)
1500 {
1501 case ClassKind::d:
1502 link = LINKd;
1503 break;
1504 case ClassKind::cpp:
1505 link = LINKcpp;
1506 break;
1507 case ClassKind::objc:
1508 link = LINKobjc;
1509 break;
1510 default:
1511 assert(0);
1512 }
1513 }
1514 }
1515 const char *linkage = linkageToChars(link);
1516 StringExp *se = new StringExp(e->loc, const_cast<char *>(linkage));
1517 return semantic(se, sc);
1518 }
1519 else if (e->ident == Id::allMembers ||
1520 e->ident == Id::derivedMembers)
1521 {
1522 if (dim != 1)
1523 return dimError(e, 1, dim);
1524
1525 RootObject *o = (*e->args)[0];
1526 Dsymbol *s = getDsymbol(o);
1527 if (!s)
1528 {
1529 e->error("argument has no members");
1530 return new ErrorExp();
1531 }
1532 if (Import *imp = s->isImport())
1533 {
1534 // Bugzilla 9692
1535 s = imp->mod;
1536 }
1537
1538 ScopeDsymbol *sds = s->isScopeDsymbol();
1539 if (!sds || sds->isTemplateDeclaration())
1540 {
1541 e->error("%s %s has no members", s->kind(), s->toChars());
1542 return new ErrorExp();
1543 }
1544
1545 // use a struct as local function
1546 struct PushIdentsDg
1547 {
1548 ScopeDsymbol *sds;
1549 Identifiers *idents;
1550
1551 static int dg(void *ctx, size_t, Dsymbol *sm)
1552 {
1553 if (!sm)
1554 return 1;
1555
1556 // skip local symbols, such as static foreach loop variables
1557 if (Declaration *decl = sm->isDeclaration())
1558 {
1559 if (decl->storage_class & STClocal)
1560 {
1561 return 0;
1562 }
1563 }
1564
1565 //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
1566 if (sm->ident)
1567 {
1568 // https://issues.dlang.org/show_bug.cgi?id=10096
1569 // https://issues.dlang.org/show_bug.cgi?id=10100
1570 // Skip over internal members in __traits(allMembers)
1571 if ((sm->isCtorDeclaration() && sm->ident != Id::ctor) ||
1572 (sm->isDtorDeclaration() && sm->ident != Id::dtor) ||
1573 (sm->isPostBlitDeclaration() && sm->ident != Id::postblit) ||
1574 sm->isInvariantDeclaration() ||
1575 sm->isUnitTestDeclaration())
1576 {
1577 return 0;
1578 }
1579
1580 if (sm->ident == Id::empty)
1581 {
1582 return 0;
1583 }
1584 if (sm->isTypeInfoDeclaration()) // Bugzilla 15177
1585 return 0;
1586 PushIdentsDg *pid = (PushIdentsDg *)ctx;
1587 if (!pid->sds->isModule() && sm->isImport()) // Bugzilla 17057
1588 return 0;
1589
1590 //printf("\t%s\n", sm->ident->toChars());
1591 Identifiers *idents = pid->idents;
1592
1593 /* Skip if already present in idents[]
1594 */
1595 for (size_t j = 0; j < idents->length; j++)
1596 {
1597 Identifier *id = (*idents)[j];
1598 if (id == sm->ident)
1599 return 0;
1600 }
1601
1602 idents->push(sm->ident);
1603 }
1604 else
1605 {
1606 EnumDeclaration *ed = sm->isEnumDeclaration();
1607 if (ed)
1608 {
1609 ScopeDsymbol_foreach(NULL, ed->members, &PushIdentsDg::dg, ctx);
1610 }
1611 }
1612 return 0;
1613 }
1614 };
1615
1616 Identifiers *idents = new Identifiers;
1617 PushIdentsDg ctx;
1618 ctx.sds = sds;
1619 ctx.idents = idents;
1620 ScopeDsymbol_foreach(sc, sds->members, &PushIdentsDg::dg, &ctx);
1621 ClassDeclaration *cd = sds->isClassDeclaration();
1622 if (cd && e->ident == Id::allMembers)
1623 {
1624 if (cd->semanticRun < PASSsemanticdone)
1625 cd->semantic(NULL); // Bugzilla 13668: Try to resolve forward reference
1626
1627 struct PushBaseMembers
1628 {
1629 static void dg(ClassDeclaration *cd, PushIdentsDg *ctx)
1630 {
1631 for (size_t i = 0; i < cd->baseclasses->length; i++)
1632 {
1633 ClassDeclaration *cb = (*cd->baseclasses)[i]->sym;
1634 assert(cb);
1635 ScopeDsymbol_foreach(NULL, cb->members, &PushIdentsDg::dg, ctx);
1636 if (cb->baseclasses->length)
1637 dg(cb, ctx);
1638 }
1639 }
1640 };
1641 PushBaseMembers::dg(cd, &ctx);
1642 }
1643
1644 // Turn Identifiers into StringExps reusing the allocated array
1645 assert(sizeof(Expressions) == sizeof(Identifiers));
1646 Expressions *exps = (Expressions *)idents;
1647 for (size_t i = 0; i < idents->length; i++)
1648 {
1649 Identifier *id = (*idents)[i];
1650 StringExp *se = new StringExp(e->loc, const_cast<char *>(id->toChars()));
1651 (*exps)[i] = se;
1652 }
1653
1654 /* Making this a tuple is more flexible, as it can be statically unrolled.
1655 * To make an array literal, enclose __traits in [ ]:
1656 * [ __traits(allMembers, ...) ]
1657 */
1658 Expression *ex = new TupleExp(e->loc, exps);
1659 ex = semantic(ex, sc);
1660 return ex;
1661 }
1662 else if (e->ident == Id::compiles)
1663 {
1664 /* Determine if all the objects - types, expressions, or symbols -
1665 * compile without error
1666 */
1667 if (!dim)
1668 return False(e);
1669
1670 for (size_t i = 0; i < dim; i++)
1671 {
1672 unsigned errors = global.startGagging();
1673 Scope *sc2 = sc->push();
1674 sc2->tinst = NULL;
1675 sc2->minst = NULL;
1676 sc2->flags = (sc->flags & ~(SCOPEctfe | SCOPEcondition)) | SCOPEcompile | SCOPEfullinst;
1677 bool err = false;
1678
1679 RootObject *o = (*e->args)[i];
1680 Type *t = isType(o);
1681 Expression *ex = t ? typeToExpression(t) : isExpression(o);
1682 if (!ex && t)
1683 {
1684 Dsymbol *s;
1685 t->resolve(e->loc, sc2, &ex, &t, &s);
1686 if (t)
1687 {
1688 t->semantic(e->loc, sc2);
1689 if (t->ty == Terror)
1690 err = true;
1691 }
1692 else if (s && s->errors)
1693 err = true;
1694 }
1695 if (ex)
1696 {
1697 ex = semantic(ex, sc2);
1698 ex = resolvePropertiesOnly(sc2, ex);
1699 ex = ex->optimize(WANTvalue);
1700 if (sc2->func && sc2->func->type->ty == Tfunction)
1701 {
1702 TypeFunction *tf = (TypeFunction *)sc2->func->type;
1703 canThrow(ex, sc2->func, tf->isnothrow);
1704 }
1705 ex = checkGC(sc2, ex);
1706 if (ex->op == TOKerror)
1707 err = true;
1708 }
1709
1710 // Carefully detach the scope from the parent and throw it away as
1711 // we only need it to evaluate the expression
1712 // https://issues.dlang.org/show_bug.cgi?id=15428
1713 freeFieldinit(sc2);
1714 sc2->enclosing = NULL;
1715 sc2->pop();
1716
1717 if (global.endGagging(errors) || err)
1718 {
1719 return False(e);
1720 }
1721 }
1722 return True(e);
1723 }
1724 else if (e->ident == Id::isSame)
1725 {
1726 /* Determine if two symbols are the same
1727 */
1728 if (dim != 2)
1729 return dimError(e, 2, dim);
1730
1731 if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0))
1732 return new ErrorExp();
1733
1734 RootObject *o1 = (*e->args)[0];
1735 RootObject *o2 = (*e->args)[1];
1736
1737 // issue 12001, allow isSame, <BasicType>, <BasicType>
1738 Type *t1 = isType(o1);
1739 Type *t2 = isType(o2);
1740 if (t1 && t2 && t1->equals(t2))
1741 return True(e);
1742
1743 Dsymbol *s1 = getDsymbol(o1);
1744 Dsymbol *s2 = getDsymbol(o2);
1745 //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars());
1746 if (!s1 && !s2)
1747 {
1748 Expression *ea1 = isExpression(o1);
1749 Expression *ea2 = isExpression(o2);
1750 if (ea1 && ea2)
1751 {
1752 if (ea1->equals(ea2))
1753 return True(e);
1754 }
1755 }
1756 if (!s1 || !s2)
1757 return False(e);
1758 s1 = s1->toAlias();
1759 s2 = s2->toAlias();
1760
1761 if (s1->isFuncAliasDeclaration())
1762 s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc();
1763 if (s2->isFuncAliasDeclaration())
1764 s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc();
1765
1766 return (s1 == s2) ? True(e) : False(e);
1767 }
1768 else if (e->ident == Id::getUnitTests)
1769 {
1770 if (dim != 1)
1771 return dimError(e, 1, dim);
1772
1773 RootObject *o = (*e->args)[0];
1774 Dsymbol *s = getDsymbolWithoutExpCtx(o);
1775 if (!s)
1776 {
1777 e->error("argument %s to __traits(getUnitTests) must be a module or aggregate",
1778 o->toChars());
1779 return new ErrorExp();
1780 }
1781 if (Import *imp = s->isImport()) // Bugzilla 10990
1782 s = imp->mod;
1783
1784 ScopeDsymbol* sds = s->isScopeDsymbol();
1785 if (!sds)
1786 {
1787 e->error("argument %s to __traits(getUnitTests) must be a module or aggregate, not a %s",
1788 s->toChars(), s->kind());
1789 return new ErrorExp();
1790 }
1791
1792 Expressions *exps = new Expressions();
1793 if (global.params.useUnitTests)
1794 {
1795 // Should actually be a set
1796 AA* uniqueUnitTests = NULL;
1797 collectUnitTests(sds->members, uniqueUnitTests, exps);
1798 }
1799 TupleExp *te= new TupleExp(e->loc, exps);
1800 return semantic(te, sc);
1801 }
1802 else if (e->ident == Id::getVirtualIndex)
1803 {
1804 if (dim != 1)
1805 return dimError(e, 1, dim);
1806
1807 RootObject *o = (*e->args)[0];
1808 Dsymbol *s = getDsymbolWithoutExpCtx(o);
1809
1810 FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
1811 if (!fd)
1812 {
1813 e->error("first argument to __traits(getVirtualIndex) must be a function");
1814 return new ErrorExp();
1815 }
1816
1817 fd = fd->toAliasFunc(); // Neccessary to support multiple overloads.
1818 return new IntegerExp(e->loc, fd->vtblIndex, Type::tptrdiff_t);
1819 }
1820 else if (e->ident == Id::getPointerBitmap)
1821 {
1822 return pointerBitmap(e);
1823 }
1824 else if (e->ident == Id::isZeroInit)
1825 {
1826 if (dim != 1)
1827 return dimError(e, 1, dim);
1828
1829 RootObject *o = (*e->args)[0];
1830 Type *t = isType(o);
1831 if (!t)
1832 {
1833 e->error("type expected as second argument of __traits `%s` instead of `%s`",
1834 e->ident->toChars(), o->toChars());
1835 return new ErrorExp();
1836 }
1837
1838 Type *tb = t->baseElemOf();
1839 return tb->isZeroInit(e->loc) ? True(e) : False(e);
1840 }
1841 else if (e->ident == Id::getTargetInfo)
1842 {
1843 if (dim != 1)
1844 return dimError(e, 1, dim);
1845
1846 Expression *ex = isExpression((*e->args)[0]);
1847 StringExp *se = ex ? ex->ctfeInterpret()->toStringExp() : NULL;
1848 if (!ex || !se || se->len == 0)
1849 {
1850 e->error("string expected as argument of __traits `%s` instead of `%s`", e->ident->toChars(), ex->toChars());
1851 return new ErrorExp();
1852 }
1853 se = se->toUTF8(sc);
1854
1855 Expression *r = target.getTargetInfo(se->toPtr(), e->loc);
1856 if (!r)
1857 {
1858 e->error("`getTargetInfo` key `\"%s\"` not supported by this implementation", se->toPtr());
1859 return new ErrorExp();
1860 }
1861 return semantic(r, sc);
1862 }
1863 else if (e->ident == Id::getLocation)
1864 {
1865 if (dim != 1)
1866 return dimError(e, 1, dim);
1867 RootObject *arg0 = (*e->args)[0];
1868 Dsymbol *s = getDsymbolWithoutExpCtx(arg0);
1869 if (!s || !s->loc.filename)
1870 {
1871 e->error("can only get the location of a symbol, not `%s`", arg0->toChars());
1872 return new ErrorExp();
1873 }
1874
1875 const FuncDeclaration *fd = s->isFuncDeclaration();
1876 if (fd && fd->overnext)
1877 {
1878 e->error("cannot get location of an overload set, "
1879 "use `__traits(getOverloads, ..., \"%s\"%s)[N]` "
1880 "to get the Nth overload",
1881 arg0->toChars(), "");
1882 return new ErrorExp();
1883 }
1884
1885 Expressions *exps = new Expressions();
1886 exps->setDim(3);
1887 (*exps)[0] = new StringExp(e->loc, const_cast<char *>(s->loc.filename), strlen(s->loc.filename));
1888 (*exps)[1] = new IntegerExp(e->loc, s->loc.linnum, Type::tint32);
1889 (*exps)[2] = new IntegerExp(e->loc, s->loc.charnum, Type::tint32);
1890 TupleExp *tup = new TupleExp(e->loc, exps);
1891 return semantic(tup, sc);
1892 }
1893
1894 if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
1895 e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub);
1896 else
1897 e->error("unrecognized trait '%s'", e->ident->toChars());
1898 return new ErrorExp();
1899
1900 e->error("wrong number of arguments %d", (int)dim);
1901 return new ErrorExp();
1902 }