traits.d revision 1.1 1 1.1 mrg /**
2 1.1 mrg * Handle introspection functionality of the `__traits()` construct.
3 1.1 mrg *
4 1.1 mrg * Specification: $(LINK2 https://dlang.org/spec/traits.html, Traits)
5 1.1 mrg *
6 1.1 mrg * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
7 1.1 mrg * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 1.1 mrg * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 1.1 mrg * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/traits.d, _traits.d)
10 1.1 mrg * Documentation: https://dlang.org/phobos/dmd_traits.html
11 1.1 mrg * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/traits.d
12 1.1 mrg */
13 1.1 mrg
14 1.1 mrg module dmd.traits;
15 1.1 mrg
16 1.1 mrg import core.stdc.stdio;
17 1.1 mrg
18 1.1 mrg import dmd.aggregate;
19 1.1 mrg import dmd.arraytypes;
20 1.1 mrg import dmd.astcodegen;
21 1.1 mrg import dmd.astenums;
22 1.1 mrg import dmd.attrib;
23 1.1 mrg import dmd.canthrow;
24 1.1 mrg import dmd.dclass;
25 1.1 mrg import dmd.declaration;
26 1.1 mrg import dmd.dimport;
27 1.1 mrg import dmd.dmangle;
28 1.1 mrg import dmd.dmodule;
29 1.1 mrg import dmd.dscope;
30 1.1 mrg import dmd.dsymbol;
31 1.1 mrg import dmd.dsymbolsem;
32 1.1 mrg import dmd.dtemplate;
33 1.1 mrg import dmd.errors;
34 1.1 mrg import dmd.expression;
35 1.1 mrg import dmd.expressionsem;
36 1.1 mrg import dmd.func;
37 1.1 mrg import dmd.globals;
38 1.1 mrg import dmd.hdrgen;
39 1.1 mrg import dmd.id;
40 1.1 mrg import dmd.identifier;
41 1.1 mrg import dmd.mtype;
42 1.1 mrg import dmd.nogc;
43 1.1 mrg import dmd.parse;
44 1.1 mrg import dmd.root.array;
45 1.1 mrg import dmd.root.speller;
46 1.1 mrg import dmd.root.stringtable;
47 1.1 mrg import dmd.target;
48 1.1 mrg import dmd.tokens;
49 1.1 mrg import dmd.typesem;
50 1.1 mrg import dmd.visitor;
51 1.1 mrg import dmd.root.rootobject;
52 1.1 mrg import dmd.common.outbuffer;
53 1.1 mrg import dmd.root.string;
54 1.1 mrg
55 1.1 mrg enum LOGSEMANTIC = false;
56 1.1 mrg
57 1.1 mrg /************************ TraitsExp ************************************/
58 1.1 mrg
59 1.1 mrg /**************************************
60 1.1 mrg * Convert `Expression` or `Type` to corresponding `Dsymbol`, additionally
61 1.1 mrg * stripping off expression contexts.
62 1.1 mrg *
63 1.1 mrg * Some symbol related `__traits` ignore arguments expression contexts.
64 1.1 mrg * For example:
65 1.1 mrg * ----
66 1.1 mrg * struct S { void f() {} }
67 1.1 mrg * S s;
68 1.1 mrg * pragma(msg, __traits(isNested, s.f));
69 1.1 mrg * // s.f is `DotVarExp`, but `__traits(isNested)`` needs a `FuncDeclaration`.
70 1.1 mrg * ----
71 1.1 mrg *
72 1.1 mrg * This is used for that common `__traits` behavior.
73 1.1 mrg *
74 1.1 mrg * Input:
75 1.1 mrg * oarg object to get the symbol for
76 1.1 mrg * Returns:
77 1.1 mrg * Dsymbol the corresponding symbol for oarg
78 1.1 mrg */
79 1.1 mrg private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
80 1.1 mrg {
81 1.1 mrg if (auto e = isExpression(oarg))
82 1.1 mrg {
83 1.1 mrg if (auto dve = e.isDotVarExp())
84 1.1 mrg return dve.var;
85 1.1 mrg if (auto dte = e.isDotTemplateExp())
86 1.1 mrg return dte.td;
87 1.1 mrg }
88 1.1 mrg return getDsymbol(oarg);
89 1.1 mrg }
90 1.1 mrg
91 1.1 mrg private const StringTable!bool traitsStringTable;
92 1.1 mrg
93 1.1 mrg shared static this()
94 1.1 mrg {
95 1.1 mrg static immutable string[] names =
96 1.1 mrg [
97 1.1 mrg "isAbstractClass",
98 1.1 mrg "isArithmetic",
99 1.1 mrg "isAssociativeArray",
100 1.1 mrg "isDisabled",
101 1.1 mrg "isDeprecated",
102 1.1 mrg "isFuture",
103 1.1 mrg "isFinalClass",
104 1.1 mrg "isPOD",
105 1.1 mrg "isNested",
106 1.1 mrg "isFloating",
107 1.1 mrg "isIntegral",
108 1.1 mrg "isScalar",
109 1.1 mrg "isStaticArray",
110 1.1 mrg "isUnsigned",
111 1.1 mrg "isVirtualFunction",
112 1.1 mrg "isVirtualMethod",
113 1.1 mrg "isAbstractFunction",
114 1.1 mrg "isFinalFunction",
115 1.1 mrg "isOverrideFunction",
116 1.1 mrg "isStaticFunction",
117 1.1 mrg "isModule",
118 1.1 mrg "isPackage",
119 1.1 mrg "isRef",
120 1.1 mrg "isOut",
121 1.1 mrg "isLazy",
122 1.1 mrg "isReturnOnStack",
123 1.1 mrg "hasMember",
124 1.1 mrg "identifier",
125 1.1 mrg "getProtection",
126 1.1 mrg "getVisibility",
127 1.1 mrg "parent",
128 1.1 mrg "child",
129 1.1 mrg "getLinkage",
130 1.1 mrg "getMember",
131 1.1 mrg "getOverloads",
132 1.1 mrg "getVirtualFunctions",
133 1.1 mrg "getVirtualMethods",
134 1.1 mrg "classInstanceSize",
135 1.1 mrg "allMembers",
136 1.1 mrg "derivedMembers",
137 1.1 mrg "isSame",
138 1.1 mrg "compiles",
139 1.1 mrg "getAliasThis",
140 1.1 mrg "getAttributes",
141 1.1 mrg "getFunctionAttributes",
142 1.1 mrg "getFunctionVariadicStyle",
143 1.1 mrg "getParameterStorageClasses",
144 1.1 mrg "getUnitTests",
145 1.1 mrg "getVirtualIndex",
146 1.1 mrg "getPointerBitmap",
147 1.1 mrg "isZeroInit",
148 1.1 mrg "getTargetInfo",
149 1.1 mrg "getLocation",
150 1.1 mrg "hasPostblit",
151 1.1 mrg "hasCopyConstructor",
152 1.1 mrg "isCopyable",
153 1.1 mrg "parameters"
154 1.1 mrg ];
155 1.1 mrg
156 1.1 mrg StringTable!(bool)* stringTable = cast(StringTable!(bool)*) &traitsStringTable;
157 1.1 mrg stringTable._init(names.length);
158 1.1 mrg
159 1.1 mrg foreach (s; names)
160 1.1 mrg {
161 1.1 mrg auto sv = stringTable.insert(s, true);
162 1.1 mrg assert(sv);
163 1.1 mrg }
164 1.1 mrg }
165 1.1 mrg
166 1.1 mrg /**
167 1.1 mrg * get an array of size_t values that indicate possible pointer words in memory
168 1.1 mrg * if interpreted as the type given as argument
169 1.1 mrg * Returns: the size of the type in bytes, ulong.max on error
170 1.1 mrg */
171 1.1 mrg ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
172 1.1 mrg {
173 1.1 mrg ulong sz;
174 1.1 mrg if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration())
175 1.1 mrg sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc);
176 1.1 mrg else
177 1.1 mrg sz = t.size(loc);
178 1.1 mrg if (sz == SIZE_INVALID)
179 1.1 mrg return ulong.max;
180 1.1 mrg
181 1.1 mrg const sz_size_t = Type.tsize_t.size(loc);
182 1.1 mrg if (sz > sz.max - sz_size_t)
183 1.1 mrg {
184 1.1 mrg error(loc, "size overflow for type `%s`", t.toChars());
185 1.1 mrg return ulong.max;
186 1.1 mrg }
187 1.1 mrg
188 1.1 mrg ulong bitsPerWord = sz_size_t * 8;
189 1.1 mrg ulong cntptr = (sz + sz_size_t - 1) / sz_size_t;
190 1.1 mrg ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
191 1.1 mrg
192 1.1 mrg data.setDim(cast(size_t)cntdata);
193 1.1 mrg data.zero();
194 1.1 mrg
195 1.1 mrg extern (C++) final class PointerBitmapVisitor : Visitor
196 1.1 mrg {
197 1.1 mrg alias visit = Visitor.visit;
198 1.1 mrg public:
199 1.1 mrg extern (D) this(Array!(ulong)* _data, ulong _sz_size_t)
200 1.1 mrg {
201 1.1 mrg this.data = _data;
202 1.1 mrg this.sz_size_t = _sz_size_t;
203 1.1 mrg }
204 1.1 mrg
205 1.1 mrg void setpointer(ulong off)
206 1.1 mrg {
207 1.1 mrg ulong ptroff = off / sz_size_t;
208 1.1 mrg (*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t));
209 1.1 mrg }
210 1.1 mrg
211 1.1 mrg override void visit(Type t)
212 1.1 mrg {
213 1.1 mrg Type tb = t.toBasetype();
214 1.1 mrg if (tb != t)
215 1.1 mrg tb.accept(this);
216 1.1 mrg }
217 1.1 mrg
218 1.1 mrg override void visit(TypeError t)
219 1.1 mrg {
220 1.1 mrg visit(cast(Type)t);
221 1.1 mrg }
222 1.1 mrg
223 1.1 mrg override void visit(TypeNext t)
224 1.1 mrg {
225 1.1 mrg assert(0);
226 1.1 mrg }
227 1.1 mrg
228 1.1 mrg override void visit(TypeBasic t)
229 1.1 mrg {
230 1.1 mrg if (t.ty == Tvoid)
231 1.1 mrg setpointer(offset);
232 1.1 mrg }
233 1.1 mrg
234 1.1 mrg override void visit(TypeVector t)
235 1.1 mrg {
236 1.1 mrg }
237 1.1 mrg
238 1.1 mrg override void visit(TypeArray t)
239 1.1 mrg {
240 1.1 mrg assert(0);
241 1.1 mrg }
242 1.1 mrg
243 1.1 mrg override void visit(TypeSArray t)
244 1.1 mrg {
245 1.1 mrg ulong arrayoff = offset;
246 1.1 mrg ulong nextsize = t.next.size();
247 1.1 mrg if (nextsize == SIZE_INVALID)
248 1.1 mrg error = true;
249 1.1 mrg ulong dim = t.dim.toInteger();
250 1.1 mrg for (ulong i = 0; i < dim; i++)
251 1.1 mrg {
252 1.1 mrg offset = arrayoff + i * nextsize;
253 1.1 mrg t.next.accept(this);
254 1.1 mrg }
255 1.1 mrg offset = arrayoff;
256 1.1 mrg }
257 1.1 mrg
258 1.1 mrg override void visit(TypeDArray t)
259 1.1 mrg {
260 1.1 mrg setpointer(offset + sz_size_t);
261 1.1 mrg }
262 1.1 mrg
263 1.1 mrg // dynamic array is {length,ptr}
264 1.1 mrg override void visit(TypeAArray t)
265 1.1 mrg {
266 1.1 mrg setpointer(offset);
267 1.1 mrg }
268 1.1 mrg
269 1.1 mrg override void visit(TypePointer t)
270 1.1 mrg {
271 1.1 mrg if (t.nextOf().ty != Tfunction) // don't mark function pointers
272 1.1 mrg setpointer(offset);
273 1.1 mrg }
274 1.1 mrg
275 1.1 mrg override void visit(TypeReference t)
276 1.1 mrg {
277 1.1 mrg setpointer(offset);
278 1.1 mrg }
279 1.1 mrg
280 1.1 mrg override void visit(TypeClass t)
281 1.1 mrg {
282 1.1 mrg setpointer(offset);
283 1.1 mrg }
284 1.1 mrg
285 1.1 mrg override void visit(TypeFunction t)
286 1.1 mrg {
287 1.1 mrg }
288 1.1 mrg
289 1.1 mrg override void visit(TypeDelegate t)
290 1.1 mrg {
291 1.1 mrg setpointer(offset);
292 1.1 mrg }
293 1.1 mrg
294 1.1 mrg // delegate is {context, function}
295 1.1 mrg override void visit(TypeQualified t)
296 1.1 mrg {
297 1.1 mrg assert(0);
298 1.1 mrg }
299 1.1 mrg
300 1.1 mrg // assume resolved
301 1.1 mrg override void visit(TypeIdentifier t)
302 1.1 mrg {
303 1.1 mrg assert(0);
304 1.1 mrg }
305 1.1 mrg
306 1.1 mrg override void visit(TypeInstance t)
307 1.1 mrg {
308 1.1 mrg assert(0);
309 1.1 mrg }
310 1.1 mrg
311 1.1 mrg override void visit(TypeTypeof t)
312 1.1 mrg {
313 1.1 mrg assert(0);
314 1.1 mrg }
315 1.1 mrg
316 1.1 mrg override void visit(TypeReturn t)
317 1.1 mrg {
318 1.1 mrg assert(0);
319 1.1 mrg }
320 1.1 mrg
321 1.1 mrg override void visit(TypeEnum t)
322 1.1 mrg {
323 1.1 mrg visit(cast(Type)t);
324 1.1 mrg }
325 1.1 mrg
326 1.1 mrg override void visit(TypeTuple t)
327 1.1 mrg {
328 1.1 mrg visit(cast(Type)t);
329 1.1 mrg }
330 1.1 mrg
331 1.1 mrg override void visit(TypeSlice t)
332 1.1 mrg {
333 1.1 mrg assert(0);
334 1.1 mrg }
335 1.1 mrg
336 1.1 mrg override void visit(TypeNull t)
337 1.1 mrg {
338 1.1 mrg // always a null pointer
339 1.1 mrg }
340 1.1 mrg
341 1.1 mrg override void visit(TypeStruct t)
342 1.1 mrg {
343 1.1 mrg ulong structoff = offset;
344 1.1 mrg foreach (v; t.sym.fields)
345 1.1 mrg {
346 1.1 mrg offset = structoff + v.offset;
347 1.1 mrg if (v.type.ty == Tclass)
348 1.1 mrg setpointer(offset);
349 1.1 mrg else
350 1.1 mrg v.type.accept(this);
351 1.1 mrg }
352 1.1 mrg offset = structoff;
353 1.1 mrg }
354 1.1 mrg
355 1.1 mrg // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references
356 1.1 mrg void visitClass(TypeClass t)
357 1.1 mrg {
358 1.1 mrg ulong classoff = offset;
359 1.1 mrg // skip vtable-ptr and monitor
360 1.1 mrg if (t.sym.baseClass)
361 1.1 mrg visitClass(cast(TypeClass)t.sym.baseClass.type);
362 1.1 mrg foreach (v; t.sym.fields)
363 1.1 mrg {
364 1.1 mrg offset = classoff + v.offset;
365 1.1 mrg v.type.accept(this);
366 1.1 mrg }
367 1.1 mrg offset = classoff;
368 1.1 mrg }
369 1.1 mrg
370 1.1 mrg Array!(ulong)* data;
371 1.1 mrg ulong offset;
372 1.1 mrg ulong sz_size_t;
373 1.1 mrg bool error;
374 1.1 mrg }
375 1.1 mrg
376 1.1 mrg scope PointerBitmapVisitor pbv = new PointerBitmapVisitor(data, sz_size_t);
377 1.1 mrg if (t.ty == Tclass)
378 1.1 mrg pbv.visitClass(cast(TypeClass)t);
379 1.1 mrg else
380 1.1 mrg t.accept(pbv);
381 1.1 mrg return pbv.error ? ulong.max : sz;
382 1.1 mrg }
383 1.1 mrg
384 1.1 mrg /**
385 1.1 mrg * get an array of size_t values that indicate possible pointer words in memory
386 1.1 mrg * if interpreted as the type given as argument
387 1.1 mrg * the first array element is the size of the type for independent interpretation
388 1.1 mrg * of the array
389 1.1 mrg * following elements bits represent one word (4/8 bytes depending on the target
390 1.1 mrg * architecture). If set the corresponding memory might contain a pointer/reference.
391 1.1 mrg *
392 1.1 mrg * Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...]
393 1.1 mrg */
394 1.1 mrg private Expression pointerBitmap(TraitsExp e)
395 1.1 mrg {
396 1.1 mrg if (!e.args || e.args.dim != 1)
397 1.1 mrg {
398 1.1 mrg error(e.loc, "a single type expected for trait pointerBitmap");
399 1.1 mrg return ErrorExp.get();
400 1.1 mrg }
401 1.1 mrg
402 1.1 mrg Type t = getType((*e.args)[0]);
403 1.1 mrg if (!t)
404 1.1 mrg {
405 1.1 mrg error(e.loc, "`%s` is not a type", (*e.args)[0].toChars());
406 1.1 mrg return ErrorExp.get();
407 1.1 mrg }
408 1.1 mrg
409 1.1 mrg Array!(ulong) data;
410 1.1 mrg ulong sz = getTypePointerBitmap(e.loc, t, &data);
411 1.1 mrg if (sz == ulong.max)
412 1.1 mrg return ErrorExp.get();
413 1.1 mrg
414 1.1 mrg auto exps = new Expressions(data.dim + 1);
415 1.1 mrg (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t);
416 1.1 mrg foreach (size_t i; 1 .. exps.dim)
417 1.1 mrg (*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t);
418 1.1 mrg
419 1.1 mrg auto ale = new ArrayLiteralExp(e.loc, Type.tsize_t.sarrayOf(data.dim + 1), exps);
420 1.1 mrg return ale;
421 1.1 mrg }
422 1.1 mrg
423 1.1 mrg Expression semanticTraits(TraitsExp e, Scope* sc)
424 1.1 mrg {
425 1.1 mrg static if (LOGSEMANTIC)
426 1.1 mrg {
427 1.1 mrg printf("TraitsExp::semantic() %s\n", e.toChars());
428 1.1 mrg }
429 1.1 mrg
430 1.1 mrg if (e.ident != Id.compiles &&
431 1.1 mrg e.ident != Id.isSame &&
432 1.1 mrg e.ident != Id.identifier &&
433 1.1 mrg e.ident != Id.getProtection && e.ident != Id.getVisibility &&
434 1.1 mrg e.ident != Id.getAttributes)
435 1.1 mrg {
436 1.1 mrg // Pretend we're in a deprecated scope so that deprecation messages
437 1.1 mrg // aren't triggered when checking if a symbol is deprecated
438 1.1 mrg const save = sc.stc;
439 1.1 mrg if (e.ident == Id.isDeprecated)
440 1.1 mrg sc.stc |= STC.deprecated_;
441 1.1 mrg if (!TemplateInstance.semanticTiargs(e.loc, sc, e.args, 1))
442 1.1 mrg {
443 1.1 mrg sc.stc = save;
444 1.1 mrg return ErrorExp.get();
445 1.1 mrg }
446 1.1 mrg sc.stc = save;
447 1.1 mrg }
448 1.1 mrg size_t dim = e.args ? e.args.dim : 0;
449 1.1 mrg
450 1.1 mrg Expression dimError(int expected)
451 1.1 mrg {
452 1.1 mrg e.error("expected %d arguments for `%s` but had %d", expected, e.ident.toChars(), cast(int)dim);
453 1.1 mrg return ErrorExp.get();
454 1.1 mrg }
455 1.1 mrg
456 1.1 mrg static IntegerExp True()
457 1.1 mrg {
458 1.1 mrg return IntegerExp.createBool(true);
459 1.1 mrg }
460 1.1 mrg
461 1.1 mrg static IntegerExp False()
462 1.1 mrg {
463 1.1 mrg return IntegerExp.createBool(false);
464 1.1 mrg }
465 1.1 mrg
466 1.1 mrg /********
467 1.1 mrg * Gets the function type from a given AST node
468 1.1 mrg * if the node is a function of some sort.
469 1.1 mrg * Params:
470 1.1 mrg * o = an AST node to check for a `TypeFunction`
471 1.1 mrg * fdp = if `o` is a FuncDeclaration then fdp is set to that, otherwise `null`
472 1.1 mrg * Returns:
473 1.1 mrg * a type node if `o` is a declaration of
474 1.1 mrg * a delegate, function, function-pointer or a variable of the former.
475 1.1 mrg * Otherwise, `null`.
476 1.1 mrg */
477 1.1 mrg static TypeFunction toTypeFunction(RootObject o, out FuncDeclaration fdp)
478 1.1 mrg {
479 1.1 mrg Type t;
480 1.1 mrg if (auto s = getDsymbolWithoutExpCtx(o))
481 1.1 mrg {
482 1.1 mrg if (auto fd = s.isFuncDeclaration())
483 1.1 mrg {
484 1.1 mrg t = fd.type;
485 1.1 mrg fdp = fd;
486 1.1 mrg }
487 1.1 mrg else if (auto vd = s.isVarDeclaration())
488 1.1 mrg t = vd.type;
489 1.1 mrg else
490 1.1 mrg t = isType(o);
491 1.1 mrg }
492 1.1 mrg else
493 1.1 mrg t = isType(o);
494 1.1 mrg
495 1.1 mrg if (t)
496 1.1 mrg {
497 1.1 mrg if (auto tf = t.isFunction_Delegate_PtrToFunction())
498 1.1 mrg return tf;
499 1.1 mrg }
500 1.1 mrg
501 1.1 mrg return null;
502 1.1 mrg }
503 1.1 mrg
504 1.1 mrg IntegerExp isX(T)(bool delegate(T) fp)
505 1.1 mrg {
506 1.1 mrg if (!dim)
507 1.1 mrg return False();
508 1.1 mrg foreach (o; *e.args)
509 1.1 mrg {
510 1.1 mrg static if (is(T == Type))
511 1.1 mrg auto y = getType(o);
512 1.1 mrg
513 1.1 mrg static if (is(T : Dsymbol))
514 1.1 mrg {
515 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
516 1.1 mrg if (!s)
517 1.1 mrg return False();
518 1.1 mrg }
519 1.1 mrg static if (is(T == Dsymbol))
520 1.1 mrg alias y = s;
521 1.1 mrg static if (is(T == Declaration))
522 1.1 mrg auto y = s.isDeclaration();
523 1.1 mrg static if (is(T == FuncDeclaration))
524 1.1 mrg auto y = s.isFuncDeclaration();
525 1.1 mrg
526 1.1 mrg if (!y || !fp(y))
527 1.1 mrg return False();
528 1.1 mrg }
529 1.1 mrg return True();
530 1.1 mrg }
531 1.1 mrg
532 1.1 mrg alias isTypeX = isX!Type;
533 1.1 mrg alias isDsymX = isX!Dsymbol;
534 1.1 mrg alias isDeclX = isX!Declaration;
535 1.1 mrg alias isFuncX = isX!FuncDeclaration;
536 1.1 mrg
537 1.1 mrg Expression isPkgX(bool function(Package) fp)
538 1.1 mrg {
539 1.1 mrg return isDsymX((Dsymbol sym) {
540 1.1 mrg Package p = resolveIsPackage(sym);
541 1.1 mrg return (p !is null) && fp(p);
542 1.1 mrg });
543 1.1 mrg }
544 1.1 mrg
545 1.1 mrg if (e.ident == Id.isArithmetic)
546 1.1 mrg {
547 1.1 mrg return isTypeX(t => t.isintegral() || t.isfloating());
548 1.1 mrg }
549 1.1 mrg if (e.ident == Id.isFloating)
550 1.1 mrg {
551 1.1 mrg return isTypeX(t => t.isfloating());
552 1.1 mrg }
553 1.1 mrg if (e.ident == Id.isIntegral)
554 1.1 mrg {
555 1.1 mrg return isTypeX(t => t.isintegral());
556 1.1 mrg }
557 1.1 mrg if (e.ident == Id.isScalar)
558 1.1 mrg {
559 1.1 mrg return isTypeX(t => t.isscalar());
560 1.1 mrg }
561 1.1 mrg if (e.ident == Id.isUnsigned)
562 1.1 mrg {
563 1.1 mrg return isTypeX(t => t.isunsigned());
564 1.1 mrg }
565 1.1 mrg if (e.ident == Id.isAssociativeArray)
566 1.1 mrg {
567 1.1 mrg return isTypeX(t => t.toBasetype().ty == Taarray);
568 1.1 mrg }
569 1.1 mrg if (e.ident == Id.isDeprecated)
570 1.1 mrg {
571 1.1 mrg if (isTypeX(t => t.iscomplex() || t.isimaginary()).toBool().hasValue(true))
572 1.1 mrg return True();
573 1.1 mrg return isDsymX(t => t.isDeprecated());
574 1.1 mrg }
575 1.1 mrg if (e.ident == Id.isFuture)
576 1.1 mrg {
577 1.1 mrg return isDeclX(t => t.isFuture());
578 1.1 mrg }
579 1.1 mrg if (e.ident == Id.isStaticArray)
580 1.1 mrg {
581 1.1 mrg return isTypeX(t => t.toBasetype().ty == Tsarray);
582 1.1 mrg }
583 1.1 mrg if (e.ident == Id.isAbstractClass)
584 1.1 mrg {
585 1.1 mrg return isTypeX(t => t.toBasetype().ty == Tclass &&
586 1.1 mrg (cast(TypeClass)t.toBasetype()).sym.isAbstract());
587 1.1 mrg }
588 1.1 mrg if (e.ident == Id.isFinalClass)
589 1.1 mrg {
590 1.1 mrg return isTypeX(t => t.toBasetype().ty == Tclass &&
591 1.1 mrg ((cast(TypeClass)t.toBasetype()).sym.storage_class & STC.final_) != 0);
592 1.1 mrg }
593 1.1 mrg if (e.ident == Id.isTemplate)
594 1.1 mrg {
595 1.1 mrg if (dim != 1)
596 1.1 mrg return dimError(1);
597 1.1 mrg
598 1.1 mrg return isDsymX((s)
599 1.1 mrg {
600 1.1 mrg if (!s.toAlias().isOverloadable())
601 1.1 mrg return false;
602 1.1 mrg return overloadApply(s,
603 1.1 mrg sm => sm.isTemplateDeclaration() !is null) != 0;
604 1.1 mrg });
605 1.1 mrg }
606 1.1 mrg if (e.ident == Id.isPOD)
607 1.1 mrg {
608 1.1 mrg if (dim != 1)
609 1.1 mrg return dimError(1);
610 1.1 mrg
611 1.1 mrg auto o = (*e.args)[0];
612 1.1 mrg auto t = isType(o);
613 1.1 mrg if (!t)
614 1.1 mrg {
615 1.1 mrg e.error("type expected as second argument of __traits `%s` instead of `%s`",
616 1.1 mrg e.ident.toChars(), o.toChars());
617 1.1 mrg return ErrorExp.get();
618 1.1 mrg }
619 1.1 mrg
620 1.1 mrg Type tb = t.baseElemOf();
621 1.1 mrg if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null)
622 1.1 mrg {
623 1.1 mrg return sd.isPOD() ? True() : False();
624 1.1 mrg }
625 1.1 mrg return True();
626 1.1 mrg }
627 1.1 mrg if (e.ident == Id.hasCopyConstructor || e.ident == Id.hasPostblit)
628 1.1 mrg {
629 1.1 mrg if (dim != 1)
630 1.1 mrg return dimError(1);
631 1.1 mrg
632 1.1 mrg auto o = (*e.args)[0];
633 1.1 mrg auto t = isType(o);
634 1.1 mrg if (!t)
635 1.1 mrg {
636 1.1 mrg e.error("type expected as second argument of __traits `%s` instead of `%s`",
637 1.1 mrg e.ident.toChars(), o.toChars());
638 1.1 mrg return ErrorExp.get();
639 1.1 mrg }
640 1.1 mrg
641 1.1 mrg Type tb = t.baseElemOf();
642 1.1 mrg if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null)
643 1.1 mrg {
644 1.1 mrg return (e.ident == Id.hasPostblit) ? (sd.postblit ? True() : False())
645 1.1 mrg : (sd.hasCopyCtor ? True() : False());
646 1.1 mrg }
647 1.1 mrg return False();
648 1.1 mrg }
649 1.1 mrg if (e.ident == Id.isCopyable)
650 1.1 mrg {
651 1.1 mrg if (dim != 1)
652 1.1 mrg return dimError(1);
653 1.1 mrg
654 1.1 mrg auto o = (*e.args)[0];
655 1.1 mrg auto t = isType(o);
656 1.1 mrg if (!t)
657 1.1 mrg {
658 1.1 mrg e.error("type expected as second argument of __traits `%s` instead of `%s`",
659 1.1 mrg e.ident.toChars(), o.toChars());
660 1.1 mrg return ErrorExp.get();
661 1.1 mrg }
662 1.1 mrg
663 1.1 mrg t = t.toBasetype(); // get the base in case `t` is an `enum`
664 1.1 mrg
665 1.1 mrg if (auto ts = t.isTypeStruct())
666 1.1 mrg {
667 1.1 mrg ts.sym.dsymbolSemantic(sc);
668 1.1 mrg }
669 1.1 mrg
670 1.1 mrg return isCopyable(t) ? True() : False();
671 1.1 mrg }
672 1.1 mrg
673 1.1 mrg if (e.ident == Id.isNested)
674 1.1 mrg {
675 1.1 mrg if (dim != 1)
676 1.1 mrg return dimError(1);
677 1.1 mrg
678 1.1 mrg auto o = (*e.args)[0];
679 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
680 1.1 mrg if (!s)
681 1.1 mrg {
682 1.1 mrg }
683 1.1 mrg else if (auto ad = s.isAggregateDeclaration())
684 1.1 mrg {
685 1.1 mrg return ad.isNested() ? True() : False();
686 1.1 mrg }
687 1.1 mrg else if (auto fd = s.isFuncDeclaration())
688 1.1 mrg {
689 1.1 mrg return fd.isNested() ? True() : False();
690 1.1 mrg }
691 1.1 mrg
692 1.1 mrg e.error("aggregate or function expected instead of `%s`", o.toChars());
693 1.1 mrg return ErrorExp.get();
694 1.1 mrg }
695 1.1 mrg if (e.ident == Id.isDisabled)
696 1.1 mrg {
697 1.1 mrg if (dim != 1)
698 1.1 mrg return dimError(1);
699 1.1 mrg
700 1.1 mrg return isDeclX(f => f.isDisabled());
701 1.1 mrg }
702 1.1 mrg if (e.ident == Id.isAbstractFunction)
703 1.1 mrg {
704 1.1 mrg if (dim != 1)
705 1.1 mrg return dimError(1);
706 1.1 mrg
707 1.1 mrg return isFuncX(f => f.isAbstract());
708 1.1 mrg }
709 1.1 mrg if (e.ident == Id.isVirtualFunction)
710 1.1 mrg {
711 1.1 mrg if (dim != 1)
712 1.1 mrg return dimError(1);
713 1.1 mrg
714 1.1 mrg return isFuncX(f => f.isVirtual());
715 1.1 mrg }
716 1.1 mrg if (e.ident == Id.isVirtualMethod)
717 1.1 mrg {
718 1.1 mrg if (dim != 1)
719 1.1 mrg return dimError(1);
720 1.1 mrg
721 1.1 mrg return isFuncX(f => f.isVirtualMethod());
722 1.1 mrg }
723 1.1 mrg if (e.ident == Id.isFinalFunction)
724 1.1 mrg {
725 1.1 mrg if (dim != 1)
726 1.1 mrg return dimError(1);
727 1.1 mrg
728 1.1 mrg return isFuncX(f => f.isFinalFunc());
729 1.1 mrg }
730 1.1 mrg if (e.ident == Id.isOverrideFunction)
731 1.1 mrg {
732 1.1 mrg if (dim != 1)
733 1.1 mrg return dimError(1);
734 1.1 mrg
735 1.1 mrg return isFuncX(f => f.isOverride());
736 1.1 mrg }
737 1.1 mrg if (e.ident == Id.isStaticFunction)
738 1.1 mrg {
739 1.1 mrg if (dim != 1)
740 1.1 mrg return dimError(1);
741 1.1 mrg
742 1.1 mrg return isFuncX(f => !f.needThis() && !f.isNested());
743 1.1 mrg }
744 1.1 mrg if (e.ident == Id.isModule)
745 1.1 mrg {
746 1.1 mrg if (dim != 1)
747 1.1 mrg return dimError(1);
748 1.1 mrg
749 1.1 mrg return isPkgX(p => p.isModule() || p.isPackageMod());
750 1.1 mrg }
751 1.1 mrg if (e.ident == Id.isPackage)
752 1.1 mrg {
753 1.1 mrg if (dim != 1)
754 1.1 mrg return dimError(1);
755 1.1 mrg
756 1.1 mrg return isPkgX(p => p.isModule() is null);
757 1.1 mrg }
758 1.1 mrg if (e.ident == Id.isRef)
759 1.1 mrg {
760 1.1 mrg if (dim != 1)
761 1.1 mrg return dimError(1);
762 1.1 mrg
763 1.1 mrg return isDeclX(d => d.isRef());
764 1.1 mrg }
765 1.1 mrg if (e.ident == Id.isOut)
766 1.1 mrg {
767 1.1 mrg if (dim != 1)
768 1.1 mrg return dimError(1);
769 1.1 mrg
770 1.1 mrg return isDeclX(d => d.isOut());
771 1.1 mrg }
772 1.1 mrg if (e.ident == Id.isLazy)
773 1.1 mrg {
774 1.1 mrg if (dim != 1)
775 1.1 mrg return dimError(1);
776 1.1 mrg
777 1.1 mrg return isDeclX(d => (d.storage_class & STC.lazy_) != 0);
778 1.1 mrg }
779 1.1 mrg if (e.ident == Id.identifier)
780 1.1 mrg {
781 1.1 mrg // Get identifier for symbol as a string literal
782 1.1 mrg /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
783 1.1 mrg * a symbol should not be folded to a constant.
784 1.1 mrg * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
785 1.1 mrg */
786 1.1 mrg if (!TemplateInstance.semanticTiargs(e.loc, sc, e.args, 2))
787 1.1 mrg return ErrorExp.get();
788 1.1 mrg if (dim != 1)
789 1.1 mrg return dimError(1);
790 1.1 mrg
791 1.1 mrg auto o = (*e.args)[0];
792 1.1 mrg Identifier id;
793 1.1 mrg if (auto po = isParameter(o))
794 1.1 mrg {
795 1.1 mrg if (!po.ident)
796 1.1 mrg {
797 1.1 mrg e.error("argument `%s` has no identifier", po.type.toChars());
798 1.1 mrg return ErrorExp.get();
799 1.1 mrg }
800 1.1 mrg id = po.ident;
801 1.1 mrg }
802 1.1 mrg else
803 1.1 mrg {
804 1.1 mrg Dsymbol s = getDsymbolWithoutExpCtx(o);
805 1.1 mrg if (!s || !s.ident)
806 1.1 mrg {
807 1.1 mrg e.error("argument `%s` has no identifier", o.toChars());
808 1.1 mrg return ErrorExp.get();
809 1.1 mrg }
810 1.1 mrg id = s.ident;
811 1.1 mrg }
812 1.1 mrg
813 1.1 mrg auto se = new StringExp(e.loc, id.toString());
814 1.1 mrg return se.expressionSemantic(sc);
815 1.1 mrg }
816 1.1 mrg if (e.ident == Id.getProtection || e.ident == Id.getVisibility)
817 1.1 mrg {
818 1.1 mrg if (dim != 1)
819 1.1 mrg return dimError(1);
820 1.1 mrg
821 1.1 mrg Scope* sc2 = sc.push();
822 1.1 mrg sc2.flags = sc.flags | SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility;
823 1.1 mrg bool ok = TemplateInstance.semanticTiargs(e.loc, sc2, e.args, 1);
824 1.1 mrg sc2.pop();
825 1.1 mrg if (!ok)
826 1.1 mrg return ErrorExp.get();
827 1.1 mrg
828 1.1 mrg auto o = (*e.args)[0];
829 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
830 1.1 mrg if (!s)
831 1.1 mrg {
832 1.1 mrg if (!isError(o))
833 1.1 mrg e.error("argument `%s` has no visibility", o.toChars());
834 1.1 mrg return ErrorExp.get();
835 1.1 mrg }
836 1.1 mrg if (s.semanticRun == PASS.initial)
837 1.1 mrg s.dsymbolSemantic(null);
838 1.1 mrg
839 1.1 mrg auto protName = visibilityToString(s.visible().kind); // TODO: How about package(names)
840 1.1 mrg assert(protName);
841 1.1 mrg auto se = new StringExp(e.loc, protName);
842 1.1 mrg return se.expressionSemantic(sc);
843 1.1 mrg }
844 1.1 mrg if (e.ident == Id.parent)
845 1.1 mrg {
846 1.1 mrg if (dim != 1)
847 1.1 mrg return dimError(1);
848 1.1 mrg
849 1.1 mrg auto o = (*e.args)[0];
850 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
851 1.1 mrg if (s)
852 1.1 mrg {
853 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=12496
854 1.1 mrg // Consider:
855 1.1 mrg // class T1
856 1.1 mrg // {
857 1.1 mrg // class C(uint value) { }
858 1.1 mrg // }
859 1.1 mrg // __traits(parent, T1.C!2)
860 1.1 mrg if (auto ad = s.isAggregateDeclaration()) // `s` is `C`
861 1.1 mrg {
862 1.1 mrg if (ad.isNested()) // `C` is nested
863 1.1 mrg {
864 1.1 mrg if (auto p = s.toParent()) // `C`'s parent is `C!2`, believe it or not
865 1.1 mrg {
866 1.1 mrg if (p.isTemplateInstance()) // `C!2` is a template instance
867 1.1 mrg {
868 1.1 mrg s = p; // `C!2`'s parent is `T1`
869 1.1 mrg auto td = (cast(TemplateInstance)p).tempdecl;
870 1.1 mrg if (td)
871 1.1 mrg s = td; // get the declaration context just in case there's two contexts
872 1.1 mrg }
873 1.1 mrg }
874 1.1 mrg }
875 1.1 mrg }
876 1.1 mrg
877 1.1 mrg if (auto fd = s.isFuncDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=8943
878 1.1 mrg s = fd.toAliasFunc();
879 1.1 mrg if (!s.isImport()) // https://issues.dlang.org/show_bug.cgi?id=8922
880 1.1 mrg s = s.toParent();
881 1.1 mrg }
882 1.1 mrg if (!s || s.isImport())
883 1.1 mrg {
884 1.1 mrg e.error("argument `%s` has no parent", o.toChars());
885 1.1 mrg return ErrorExp.get();
886 1.1 mrg }
887 1.1 mrg
888 1.1 mrg if (auto f = s.isFuncDeclaration())
889 1.1 mrg {
890 1.1 mrg if (auto td = getFuncTemplateDecl(f))
891 1.1 mrg {
892 1.1 mrg if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
893 1.1 mrg td = td.overroot; // then get the start
894 1.1 mrg Expression ex = new TemplateExp(e.loc, td, f);
895 1.1 mrg ex = ex.expressionSemantic(sc);
896 1.1 mrg return ex;
897 1.1 mrg }
898 1.1 mrg if (auto fld = f.isFuncLiteralDeclaration())
899 1.1 mrg {
900 1.1 mrg // Directly translate to VarExp instead of FuncExp
901 1.1 mrg Expression ex = new VarExp(e.loc, fld, true);
902 1.1 mrg return ex.expressionSemantic(sc);
903 1.1 mrg }
904 1.1 mrg }
905 1.1 mrg return symbolToExp(s, e.loc, sc, false);
906 1.1 mrg }
907 1.1 mrg if (e.ident == Id.child)
908 1.1 mrg {
909 1.1 mrg if (dim != 2)
910 1.1 mrg return dimError(2);
911 1.1 mrg
912 1.1 mrg Expression ex;
913 1.1 mrg auto op = (*e.args)[0];
914 1.1 mrg if (auto symp = getDsymbol(op))
915 1.1 mrg ex = new DsymbolExp(e.loc, symp);
916 1.1 mrg else if (auto exp = op.isExpression())
917 1.1 mrg ex = exp;
918 1.1 mrg else
919 1.1 mrg {
920 1.1 mrg e.error("symbol or expression expected as first argument of __traits `child` instead of `%s`", op.toChars());
921 1.1 mrg return ErrorExp.get();
922 1.1 mrg }
923 1.1 mrg
924 1.1 mrg ex = ex.expressionSemantic(sc);
925 1.1 mrg auto oc = (*e.args)[1];
926 1.1 mrg auto symc = getDsymbol(oc);
927 1.1 mrg if (!symc)
928 1.1 mrg {
929 1.1 mrg e.error("symbol expected as second argument of __traits `child` instead of `%s`", oc.toChars());
930 1.1 mrg return ErrorExp.get();
931 1.1 mrg }
932 1.1 mrg
933 1.1 mrg if (auto d = symc.isDeclaration())
934 1.1 mrg ex = new DotVarExp(e.loc, ex, d);
935 1.1 mrg else if (auto td = symc.isTemplateDeclaration())
936 1.1 mrg ex = new DotExp(e.loc, ex, new TemplateExp(e.loc, td));
937 1.1 mrg else if (auto ti = symc.isScopeDsymbol())
938 1.1 mrg ex = new DotExp(e.loc, ex, new ScopeExp(e.loc, ti));
939 1.1 mrg else
940 1.1 mrg assert(0);
941 1.1 mrg
942 1.1 mrg ex = ex.expressionSemantic(sc);
943 1.1 mrg return ex;
944 1.1 mrg }
945 1.1 mrg if (e.ident == Id.toType)
946 1.1 mrg {
947 1.1 mrg if (dim != 1)
948 1.1 mrg return dimError(1);
949 1.1 mrg
950 1.1 mrg auto ex = isExpression((*e.args)[0]);
951 1.1 mrg if (!ex)
952 1.1 mrg {
953 1.1 mrg e.error("expression expected as second argument of __traits `%s`", e.ident.toChars());
954 1.1 mrg return ErrorExp.get();
955 1.1 mrg }
956 1.1 mrg ex = ex.ctfeInterpret();
957 1.1 mrg
958 1.1 mrg StringExp se = semanticString(sc, ex, "__traits(toType, string)");
959 1.1 mrg if (!se)
960 1.1 mrg {
961 1.1 mrg return ErrorExp.get();
962 1.1 mrg }
963 1.1 mrg Type t = decoToType(se.toUTF8(sc).peekString());
964 1.1 mrg if (!t)
965 1.1 mrg {
966 1.1 mrg e.error("cannot determine `%s`", e.toChars());
967 1.1 mrg return ErrorExp.get();
968 1.1 mrg }
969 1.1 mrg return (new TypeExp(e.loc, t)).expressionSemantic(sc);
970 1.1 mrg }
971 1.1 mrg if (e.ident == Id.hasMember ||
972 1.1 mrg e.ident == Id.getMember ||
973 1.1 mrg e.ident == Id.getOverloads ||
974 1.1 mrg e.ident == Id.getVirtualMethods ||
975 1.1 mrg e.ident == Id.getVirtualFunctions)
976 1.1 mrg {
977 1.1 mrg if (dim != 2 && !(dim == 3 && e.ident == Id.getOverloads))
978 1.1 mrg return dimError(2);
979 1.1 mrg
980 1.1 mrg auto o = (*e.args)[0];
981 1.1 mrg auto ex = isExpression((*e.args)[1]);
982 1.1 mrg if (!ex)
983 1.1 mrg {
984 1.1 mrg e.error("expression expected as second argument of __traits `%s`", e.ident.toChars());
985 1.1 mrg return ErrorExp.get();
986 1.1 mrg }
987 1.1 mrg ex = ex.ctfeInterpret();
988 1.1 mrg
989 1.1 mrg bool includeTemplates = false;
990 1.1 mrg if (dim == 3 && e.ident == Id.getOverloads)
991 1.1 mrg {
992 1.1 mrg auto b = isExpression((*e.args)[2]);
993 1.1 mrg b = b.ctfeInterpret();
994 1.1 mrg if (!b.type.equals(Type.tbool))
995 1.1 mrg {
996 1.1 mrg e.error("`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b.toChars(), b.type.toChars());
997 1.1 mrg return ErrorExp.get();
998 1.1 mrg }
999 1.1 mrg includeTemplates = b.toBool().get();
1000 1.1 mrg }
1001 1.1 mrg
1002 1.1 mrg StringExp se = ex.toStringExp();
1003 1.1 mrg if (!se || se.len == 0)
1004 1.1 mrg {
1005 1.1 mrg e.error("string expected as second argument of __traits `%s` instead of `%s`", e.ident.toChars(), ex.toChars());
1006 1.1 mrg return ErrorExp.get();
1007 1.1 mrg }
1008 1.1 mrg se = se.toUTF8(sc);
1009 1.1 mrg
1010 1.1 mrg if (se.sz != 1)
1011 1.1 mrg {
1012 1.1 mrg e.error("string must be chars");
1013 1.1 mrg return ErrorExp.get();
1014 1.1 mrg }
1015 1.1 mrg auto id = Identifier.idPool(se.peekString());
1016 1.1 mrg
1017 1.1 mrg /* Prefer a Type, because getDsymbol(Type) can lose type modifiers.
1018 1.1 mrg Then a Dsymbol, because it might need some runtime contexts.
1019 1.1 mrg */
1020 1.1 mrg
1021 1.1 mrg Dsymbol sym = getDsymbol(o);
1022 1.1 mrg if (auto t = isType(o))
1023 1.1 mrg ex = typeDotIdExp(e.loc, t, id);
1024 1.1 mrg else if (sym)
1025 1.1 mrg {
1026 1.1 mrg if (e.ident == Id.hasMember)
1027 1.1 mrg {
1028 1.1 mrg if (auto sm = sym.search(e.loc, id))
1029 1.1 mrg return True();
1030 1.1 mrg }
1031 1.1 mrg ex = new DsymbolExp(e.loc, sym);
1032 1.1 mrg ex = new DotIdExp(e.loc, ex, id);
1033 1.1 mrg }
1034 1.1 mrg else if (auto ex2 = isExpression(o))
1035 1.1 mrg ex = new DotIdExp(e.loc, ex2, id);
1036 1.1 mrg else
1037 1.1 mrg {
1038 1.1 mrg e.error("invalid first argument");
1039 1.1 mrg return ErrorExp.get();
1040 1.1 mrg }
1041 1.1 mrg
1042 1.1 mrg // ignore symbol visibility and disable access checks for these traits
1043 1.1 mrg Scope* scx = sc.push();
1044 1.1 mrg scx.flags |= SCOPE.ignoresymbolvisibility | SCOPE.noaccesscheck;
1045 1.1 mrg scope (exit) scx.pop();
1046 1.1 mrg
1047 1.1 mrg if (e.ident == Id.hasMember)
1048 1.1 mrg {
1049 1.1 mrg /* Take any errors as meaning it wasn't found
1050 1.1 mrg */
1051 1.1 mrg ex = ex.trySemantic(scx);
1052 1.1 mrg return ex ? True() : False();
1053 1.1 mrg }
1054 1.1 mrg else if (e.ident == Id.getMember)
1055 1.1 mrg {
1056 1.1 mrg if (auto die = ex.isDotIdExp())
1057 1.1 mrg // Prevent semantic() from replacing Symbol with its initializer
1058 1.1 mrg die.wantsym = true;
1059 1.1 mrg ex = ex.expressionSemantic(scx);
1060 1.1 mrg return ex;
1061 1.1 mrg }
1062 1.1 mrg else if (e.ident == Id.getVirtualFunctions ||
1063 1.1 mrg e.ident == Id.getVirtualMethods ||
1064 1.1 mrg e.ident == Id.getOverloads)
1065 1.1 mrg {
1066 1.1 mrg uint errors = global.errors;
1067 1.1 mrg Expression eorig = ex;
1068 1.1 mrg ex = ex.expressionSemantic(scx);
1069 1.1 mrg if (errors < global.errors)
1070 1.1 mrg e.error("`%s` cannot be resolved", eorig.toChars());
1071 1.1 mrg
1072 1.1 mrg /* Create tuple of functions of ex
1073 1.1 mrg */
1074 1.1 mrg auto exps = new Expressions();
1075 1.1 mrg Dsymbol f;
1076 1.1 mrg if (auto ve = ex.isVarExp)
1077 1.1 mrg {
1078 1.1 mrg if (ve.var.isFuncDeclaration() || ve.var.isOverDeclaration())
1079 1.1 mrg f = ve.var;
1080 1.1 mrg ex = null;
1081 1.1 mrg }
1082 1.1 mrg else if (auto dve = ex.isDotVarExp)
1083 1.1 mrg {
1084 1.1 mrg if (dve.var.isFuncDeclaration() || dve.var.isOverDeclaration())
1085 1.1 mrg f = dve.var;
1086 1.1 mrg if (dve.e1.op == EXP.dotType || dve.e1.op == EXP.this_)
1087 1.1 mrg ex = null;
1088 1.1 mrg else
1089 1.1 mrg ex = dve.e1;
1090 1.1 mrg }
1091 1.1 mrg else if (auto te = ex.isTemplateExp)
1092 1.1 mrg {
1093 1.1 mrg auto td = te.td;
1094 1.1 mrg f = td;
1095 1.1 mrg if (td && td.funcroot)
1096 1.1 mrg f = td.funcroot;
1097 1.1 mrg ex = null;
1098 1.1 mrg }
1099 1.1 mrg else if (auto dte = ex.isDotTemplateExp)
1100 1.1 mrg {
1101 1.1 mrg auto td = dte.td;
1102 1.1 mrg f = td;
1103 1.1 mrg if (td && td.funcroot)
1104 1.1 mrg f = td.funcroot;
1105 1.1 mrg ex = null;
1106 1.1 mrg if (dte.e1.op != EXP.dotType && dte.e1.op != EXP.this_)
1107 1.1 mrg ex = dte.e1;
1108 1.1 mrg }
1109 1.1 mrg bool[string] funcTypeHash;
1110 1.1 mrg
1111 1.1 mrg /* Compute the function signature and insert it in the
1112 1.1 mrg * hashtable, if not present. This is needed so that
1113 1.1 mrg * traits(getOverlods, F3, "visit") does not count `int visit(int)`
1114 1.1 mrg * twice in the following example:
1115 1.1 mrg *
1116 1.1 mrg * =============================================
1117 1.1 mrg * interface F1 { int visit(int);}
1118 1.1 mrg * interface F2 { int visit(int); void visit(); }
1119 1.1 mrg * interface F3 : F2, F1 {}
1120 1.1 mrg *==============================================
1121 1.1 mrg */
1122 1.1 mrg void insertInterfaceInheritedFunction(FuncDeclaration fd, Expression e)
1123 1.1 mrg {
1124 1.1 mrg auto signature = fd.type.toString();
1125 1.1 mrg //printf("%s - %s\n", fd.toChars, signature);
1126 1.1 mrg if (signature !in funcTypeHash)
1127 1.1 mrg {
1128 1.1 mrg funcTypeHash[signature] = true;
1129 1.1 mrg exps.push(e);
1130 1.1 mrg }
1131 1.1 mrg }
1132 1.1 mrg
1133 1.1 mrg int dg(Dsymbol s)
1134 1.1 mrg {
1135 1.1 mrg auto fd = s.isFuncDeclaration();
1136 1.1 mrg if (!fd)
1137 1.1 mrg {
1138 1.1 mrg if (includeTemplates)
1139 1.1 mrg {
1140 1.1 mrg if (auto td = s.isTemplateDeclaration())
1141 1.1 mrg {
1142 1.1 mrg // if td is part of an overload set we must take a copy
1143 1.1 mrg // which shares the same `instances` cache but without
1144 1.1 mrg // `overroot` and `overnext` set to avoid overload
1145 1.1 mrg // behaviour in the result.
1146 1.1 mrg if (td.overnext !is null)
1147 1.1 mrg {
1148 1.1 mrg if (td.instances is null)
1149 1.1 mrg {
1150 1.1 mrg // create an empty AA just to copy it
1151 1.1 mrg scope ti = new TemplateInstance(Loc.initial, Id.empty, null);
1152 1.1 mrg auto tib = TemplateInstanceBox(ti);
1153 1.1 mrg td.instances[tib] = null;
1154 1.1 mrg td.instances.clear();
1155 1.1 mrg }
1156 1.1 mrg td = td.syntaxCopy(null);
1157 1.1 mrg import core.stdc.string : memcpy;
1158 1.1 mrg memcpy(cast(void*) td, cast(void*) s,
1159 1.1 mrg __traits(classInstanceSize, TemplateDeclaration));
1160 1.1 mrg td.overroot = null;
1161 1.1 mrg td.overnext = null;
1162 1.1 mrg }
1163 1.1 mrg
1164 1.1 mrg auto e = ex ? new DotTemplateExp(Loc.initial, ex, td)
1165 1.1 mrg : new DsymbolExp(Loc.initial, td);
1166 1.1 mrg exps.push(e);
1167 1.1 mrg }
1168 1.1 mrg }
1169 1.1 mrg return 0;
1170 1.1 mrg }
1171 1.1 mrg if (e.ident == Id.getVirtualFunctions && !fd.isVirtual())
1172 1.1 mrg return 0;
1173 1.1 mrg if (e.ident == Id.getVirtualMethods && !fd.isVirtualMethod())
1174 1.1 mrg return 0;
1175 1.1 mrg
1176 1.1 mrg auto fa = new FuncAliasDeclaration(fd.ident, fd, false);
1177 1.1 mrg fa.visibility = fd.visibility;
1178 1.1 mrg
1179 1.1 mrg auto e = ex ? new DotVarExp(Loc.initial, ex, fa, false)
1180 1.1 mrg : new DsymbolExp(Loc.initial, fa, false);
1181 1.1 mrg
1182 1.1 mrg // if the parent is an interface declaration
1183 1.1 mrg // we must check for functions with the same signature
1184 1.1 mrg // in different inherited interfaces
1185 1.1 mrg if (sym && sym.isInterfaceDeclaration())
1186 1.1 mrg insertInterfaceInheritedFunction(fd, e);
1187 1.1 mrg else
1188 1.1 mrg exps.push(e);
1189 1.1 mrg return 0;
1190 1.1 mrg }
1191 1.1 mrg
1192 1.1 mrg InterfaceDeclaration ifd = null;
1193 1.1 mrg if (sym)
1194 1.1 mrg ifd = sym.isInterfaceDeclaration();
1195 1.1 mrg // If the symbol passed as a parameter is an
1196 1.1 mrg // interface that inherits other interfaces
1197 1.1 mrg overloadApply(f, &dg);
1198 1.1 mrg if (ifd && ifd.interfaces && f)
1199 1.1 mrg {
1200 1.1 mrg // check the overloads of each inherited interface individually
1201 1.1 mrg foreach (bc; ifd.interfaces)
1202 1.1 mrg {
1203 1.1 mrg if (auto fd = bc.sym.search(e.loc, f.ident))
1204 1.1 mrg overloadApply(fd, &dg);
1205 1.1 mrg }
1206 1.1 mrg }
1207 1.1 mrg
1208 1.1 mrg auto tup = new TupleExp(e.loc, exps);
1209 1.1 mrg return tup.expressionSemantic(scx);
1210 1.1 mrg }
1211 1.1 mrg else
1212 1.1 mrg assert(0);
1213 1.1 mrg }
1214 1.1 mrg if (e.ident == Id.classInstanceSize)
1215 1.1 mrg {
1216 1.1 mrg if (dim != 1)
1217 1.1 mrg return dimError(1);
1218 1.1 mrg
1219 1.1 mrg auto o = (*e.args)[0];
1220 1.1 mrg auto s = getDsymbol(o);
1221 1.1 mrg auto cd = s ? s.isClassDeclaration() : null;
1222 1.1 mrg if (!cd)
1223 1.1 mrg {
1224 1.1 mrg e.error("first argument is not a class");
1225 1.1 mrg return ErrorExp.get();
1226 1.1 mrg }
1227 1.1 mrg if (cd.sizeok != Sizeok.done)
1228 1.1 mrg {
1229 1.1 mrg cd.size(e.loc);
1230 1.1 mrg }
1231 1.1 mrg if (cd.sizeok != Sizeok.done)
1232 1.1 mrg {
1233 1.1 mrg e.error("%s `%s` is forward referenced", cd.kind(), cd.toChars());
1234 1.1 mrg return ErrorExp.get();
1235 1.1 mrg }
1236 1.1 mrg
1237 1.1 mrg return new IntegerExp(e.loc, cd.structsize, Type.tsize_t);
1238 1.1 mrg }
1239 1.1 mrg if (e.ident == Id.getAliasThis)
1240 1.1 mrg {
1241 1.1 mrg if (dim != 1)
1242 1.1 mrg return dimError(1);
1243 1.1 mrg
1244 1.1 mrg auto o = (*e.args)[0];
1245 1.1 mrg auto s = getDsymbol(o);
1246 1.1 mrg auto ad = s ? s.isAggregateDeclaration() : null;
1247 1.1 mrg
1248 1.1 mrg auto exps = new Expressions();
1249 1.1 mrg if (ad && ad.aliasthis)
1250 1.1 mrg exps.push(new StringExp(e.loc, ad.aliasthis.ident.toString()));
1251 1.1 mrg Expression ex = new TupleExp(e.loc, exps);
1252 1.1 mrg ex = ex.expressionSemantic(sc);
1253 1.1 mrg return ex;
1254 1.1 mrg }
1255 1.1 mrg if (e.ident == Id.getAttributes)
1256 1.1 mrg {
1257 1.1 mrg /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
1258 1.1 mrg * a symbol should not be folded to a constant.
1259 1.1 mrg * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
1260 1.1 mrg */
1261 1.1 mrg if (!TemplateInstance.semanticTiargs(e.loc, sc, e.args, 3))
1262 1.1 mrg return ErrorExp.get();
1263 1.1 mrg
1264 1.1 mrg if (dim != 1)
1265 1.1 mrg return dimError(1);
1266 1.1 mrg
1267 1.1 mrg auto o = (*e.args)[0];
1268 1.1 mrg auto po = isParameter(o);
1269 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
1270 1.1 mrg UserAttributeDeclaration udad = null;
1271 1.1 mrg if (po)
1272 1.1 mrg {
1273 1.1 mrg udad = po.userAttribDecl;
1274 1.1 mrg }
1275 1.1 mrg else if (s)
1276 1.1 mrg {
1277 1.1 mrg if (s.isImport())
1278 1.1 mrg {
1279 1.1 mrg s = s.isImport().mod;
1280 1.1 mrg }
1281 1.1 mrg //printf("getAttributes %s, attrs = %p, scope = %p\n", s.toChars(), s.userAttribDecl, s._scope);
1282 1.1 mrg udad = s.userAttribDecl;
1283 1.1 mrg }
1284 1.1 mrg else
1285 1.1 mrg {
1286 1.1 mrg version (none)
1287 1.1 mrg {
1288 1.1 mrg Expression x = isExpression(o);
1289 1.1 mrg Type t = isType(o);
1290 1.1 mrg if (x)
1291 1.1 mrg printf("e = %s %s\n", EXPtoString(x.op).ptr, x.toChars());
1292 1.1 mrg if (t)
1293 1.1 mrg printf("t = %d %s\n", t.ty, t.toChars());
1294 1.1 mrg }
1295 1.1 mrg e.error("first argument is not a symbol");
1296 1.1 mrg return ErrorExp.get();
1297 1.1 mrg }
1298 1.1 mrg
1299 1.1 mrg auto exps = udad ? udad.getAttributes() : new Expressions();
1300 1.1 mrg auto tup = new TupleExp(e.loc, exps);
1301 1.1 mrg return tup.expressionSemantic(sc);
1302 1.1 mrg }
1303 1.1 mrg if (e.ident == Id.getFunctionAttributes)
1304 1.1 mrg {
1305 1.1 mrg /* Extract all function attributes as a tuple (const/shared/inout/pure/nothrow/etc) except UDAs.
1306 1.1 mrg * https://dlang.org/spec/traits.html#getFunctionAttributes
1307 1.1 mrg */
1308 1.1 mrg if (dim != 1)
1309 1.1 mrg return dimError(1);
1310 1.1 mrg
1311 1.1 mrg FuncDeclaration fd;
1312 1.1 mrg TypeFunction tf = toTypeFunction((*e.args)[0], fd);
1313 1.1 mrg
1314 1.1 mrg if (!tf)
1315 1.1 mrg {
1316 1.1 mrg e.error("first argument is not a function");
1317 1.1 mrg return ErrorExp.get();
1318 1.1 mrg }
1319 1.1 mrg
1320 1.1 mrg auto mods = new Expressions();
1321 1.1 mrg
1322 1.1 mrg void addToMods(string str)
1323 1.1 mrg {
1324 1.1 mrg mods.push(new StringExp(Loc.initial, str));
1325 1.1 mrg }
1326 1.1 mrg tf.modifiersApply(&addToMods);
1327 1.1 mrg tf.attributesApply(&addToMods, TRUSTformatSystem);
1328 1.1 mrg
1329 1.1 mrg auto tup = new TupleExp(e.loc, mods);
1330 1.1 mrg return tup.expressionSemantic(sc);
1331 1.1 mrg }
1332 1.1 mrg if (e.ident == Id.isReturnOnStack)
1333 1.1 mrg {
1334 1.1 mrg /* Extract as a boolean if function return value is on the stack
1335 1.1 mrg * https://dlang.org/spec/traits.html#isReturnOnStack
1336 1.1 mrg */
1337 1.1 mrg if (dim != 1)
1338 1.1 mrg return dimError(1);
1339 1.1 mrg
1340 1.1 mrg RootObject o = (*e.args)[0];
1341 1.1 mrg FuncDeclaration fd;
1342 1.1 mrg TypeFunction tf = toTypeFunction(o, fd);
1343 1.1 mrg
1344 1.1 mrg if (!tf)
1345 1.1 mrg {
1346 1.1 mrg e.error("argument to `__traits(isReturnOnStack, %s)` is not a function", o.toChars());
1347 1.1 mrg return ErrorExp.get();
1348 1.1 mrg }
1349 1.1 mrg
1350 1.1 mrg bool value = target.isReturnOnStack(tf, fd && fd.needThis());
1351 1.1 mrg return IntegerExp.createBool(value);
1352 1.1 mrg }
1353 1.1 mrg if (e.ident == Id.getFunctionVariadicStyle)
1354 1.1 mrg {
1355 1.1 mrg /* Accept a symbol or a type. Returns one of the following:
1356 1.1 mrg * "none" not a variadic function
1357 1.1 mrg * "argptr" extern(D) void dstyle(...), use `__argptr` and `__arguments`
1358 1.1 mrg * "stdarg" extern(C) void cstyle(int, ...), use core.stdc.stdarg
1359 1.1 mrg * "typesafe" void typesafe(T[] ...)
1360 1.1 mrg */
1361 1.1 mrg // get symbol linkage as a string
1362 1.1 mrg if (dim != 1)
1363 1.1 mrg return dimError(1);
1364 1.1 mrg
1365 1.1 mrg LINK link;
1366 1.1 mrg VarArg varargs;
1367 1.1 mrg auto o = (*e.args)[0];
1368 1.1 mrg
1369 1.1 mrg FuncDeclaration fd;
1370 1.1 mrg TypeFunction tf = toTypeFunction(o, fd);
1371 1.1 mrg
1372 1.1 mrg if (tf)
1373 1.1 mrg {
1374 1.1 mrg link = tf.linkage;
1375 1.1 mrg varargs = tf.parameterList.varargs;
1376 1.1 mrg }
1377 1.1 mrg else
1378 1.1 mrg {
1379 1.1 mrg if (!fd)
1380 1.1 mrg {
1381 1.1 mrg e.error("argument to `__traits(getFunctionVariadicStyle, %s)` is not a function", o.toChars());
1382 1.1 mrg return ErrorExp.get();
1383 1.1 mrg }
1384 1.1 mrg link = fd._linkage;
1385 1.1 mrg varargs = fd.getParameterList().varargs;
1386 1.1 mrg }
1387 1.1 mrg string style;
1388 1.1 mrg final switch (varargs)
1389 1.1 mrg {
1390 1.1 mrg case VarArg.none: style = "none"; break;
1391 1.1 mrg case VarArg.variadic: style = (link == LINK.d)
1392 1.1 mrg ? "argptr"
1393 1.1 mrg : "stdarg"; break;
1394 1.1 mrg case VarArg.typesafe: style = "typesafe"; break;
1395 1.1 mrg }
1396 1.1 mrg auto se = new StringExp(e.loc, style);
1397 1.1 mrg return se.expressionSemantic(sc);
1398 1.1 mrg }
1399 1.1 mrg if (e.ident == Id.getParameterStorageClasses)
1400 1.1 mrg {
1401 1.1 mrg /* Accept a function symbol or a type, followed by a parameter index.
1402 1.1 mrg * Returns a tuple of strings of the parameter's storage classes.
1403 1.1 mrg */
1404 1.1 mrg // get symbol linkage as a string
1405 1.1 mrg if (dim != 2)
1406 1.1 mrg return dimError(2);
1407 1.1 mrg
1408 1.1 mrg auto o = (*e.args)[0];
1409 1.1 mrg auto o1 = (*e.args)[1];
1410 1.1 mrg
1411 1.1 mrg ParameterList fparams;
1412 1.1 mrg
1413 1.1 mrg CallExp ce;
1414 1.1 mrg if (auto exp = isExpression(o))
1415 1.1 mrg ce = exp.isCallExp();
1416 1.1 mrg
1417 1.1 mrg if (ce)
1418 1.1 mrg {
1419 1.1 mrg fparams = ce.f.getParameterList();
1420 1.1 mrg }
1421 1.1 mrg else
1422 1.1 mrg {
1423 1.1 mrg FuncDeclaration fd;
1424 1.1 mrg auto tf = toTypeFunction(o, fd);
1425 1.1 mrg if (tf)
1426 1.1 mrg fparams = tf.parameterList;
1427 1.1 mrg else if (fd)
1428 1.1 mrg fparams = fd.getParameterList();
1429 1.1 mrg else
1430 1.1 mrg {
1431 1.1 mrg e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function or a function call",
1432 1.1 mrg o.toChars(), o1.toChars());
1433 1.1 mrg return ErrorExp.get();
1434 1.1 mrg }
1435 1.1 mrg }
1436 1.1 mrg
1437 1.1 mrg // Avoid further analysis for invalid functions leading to misleading error messages
1438 1.1 mrg if (!fparams.parameters)
1439 1.1 mrg return ErrorExp.get();
1440 1.1 mrg
1441 1.1 mrg StorageClass stc;
1442 1.1 mrg
1443 1.1 mrg // Set stc to storage class of the ith parameter
1444 1.1 mrg auto ex = isExpression((*e.args)[1]);
1445 1.1 mrg if (!ex)
1446 1.1 mrg {
1447 1.1 mrg e.error("expression expected as second argument of `__traits(getParameterStorageClasses, %s, %s)`",
1448 1.1 mrg o.toChars(), o1.toChars());
1449 1.1 mrg return ErrorExp.get();
1450 1.1 mrg }
1451 1.1 mrg ex = ex.ctfeInterpret();
1452 1.1 mrg auto ii = ex.toUInteger();
1453 1.1 mrg if (ii >= fparams.length)
1454 1.1 mrg {
1455 1.1 mrg e.error("parameter index must be in range 0..%u not %s", cast(uint)fparams.length, ex.toChars());
1456 1.1 mrg return ErrorExp.get();
1457 1.1 mrg }
1458 1.1 mrg
1459 1.1 mrg uint n = cast(uint)ii;
1460 1.1 mrg Parameter p = fparams[n];
1461 1.1 mrg stc = p.storageClass;
1462 1.1 mrg
1463 1.1 mrg // This mirrors hdrgen.visit(Parameter p)
1464 1.1 mrg if (p.type && p.type.mod & MODFlags.shared_)
1465 1.1 mrg stc &= ~STC.shared_;
1466 1.1 mrg
1467 1.1 mrg auto exps = new Expressions;
1468 1.1 mrg
1469 1.1 mrg void push(string s)
1470 1.1 mrg {
1471 1.1 mrg exps.push(new StringExp(e.loc, s));
1472 1.1 mrg }
1473 1.1 mrg
1474 1.1 mrg if (stc & STC.auto_)
1475 1.1 mrg push("auto");
1476 1.1 mrg if (stc & STC.return_)
1477 1.1 mrg push("return");
1478 1.1 mrg
1479 1.1 mrg if (stc & STC.out_)
1480 1.1 mrg push("out");
1481 1.1 mrg else if (stc & STC.in_)
1482 1.1 mrg push("in");
1483 1.1 mrg else if (stc & STC.ref_)
1484 1.1 mrg push("ref");
1485 1.1 mrg else if (stc & STC.lazy_)
1486 1.1 mrg push("lazy");
1487 1.1 mrg else if (stc & STC.alias_)
1488 1.1 mrg push("alias");
1489 1.1 mrg
1490 1.1 mrg if (stc & STC.const_)
1491 1.1 mrg push("const");
1492 1.1 mrg if (stc & STC.immutable_)
1493 1.1 mrg push("immutable");
1494 1.1 mrg if (stc & STC.wild)
1495 1.1 mrg push("inout");
1496 1.1 mrg if (stc & STC.shared_)
1497 1.1 mrg push("shared");
1498 1.1 mrg if (stc & STC.scope_ && !(stc & STC.scopeinferred))
1499 1.1 mrg push("scope");
1500 1.1 mrg
1501 1.1 mrg auto tup = new TupleExp(e.loc, exps);
1502 1.1 mrg return tup.expressionSemantic(sc);
1503 1.1 mrg }
1504 1.1 mrg if (e.ident == Id.getLinkage)
1505 1.1 mrg {
1506 1.1 mrg // get symbol linkage as a string
1507 1.1 mrg if (dim != 1)
1508 1.1 mrg return dimError(1);
1509 1.1 mrg
1510 1.1 mrg LINK link;
1511 1.1 mrg auto o = (*e.args)[0];
1512 1.1 mrg
1513 1.1 mrg FuncDeclaration fd;
1514 1.1 mrg TypeFunction tf = toTypeFunction(o, fd);
1515 1.1 mrg
1516 1.1 mrg if (tf)
1517 1.1 mrg {
1518 1.1 mrg link = fd ? fd.toAliasFunc()._linkage : tf.linkage;
1519 1.1 mrg }
1520 1.1 mrg else
1521 1.1 mrg {
1522 1.1 mrg auto s = getDsymbol(o);
1523 1.1 mrg Declaration d;
1524 1.1 mrg AggregateDeclaration agg;
1525 1.1 mrg if (!s || ((d = s.isDeclaration()) is null && (agg = s.isAggregateDeclaration()) is null))
1526 1.1 mrg {
1527 1.1 mrg e.error("argument to `__traits(getLinkage, %s)` is not a declaration", o.toChars());
1528 1.1 mrg return ErrorExp.get();
1529 1.1 mrg }
1530 1.1 mrg
1531 1.1 mrg if (d !is null)
1532 1.1 mrg link = d._linkage;
1533 1.1 mrg else
1534 1.1 mrg {
1535 1.1 mrg // Resolves forward references
1536 1.1 mrg if (agg.sizeok != Sizeok.done)
1537 1.1 mrg {
1538 1.1 mrg agg.size(e.loc);
1539 1.1 mrg if (agg.sizeok != Sizeok.done)
1540 1.1 mrg {
1541 1.1 mrg e.error("%s `%s` is forward referenced", agg.kind(), agg.toChars());
1542 1.1 mrg return ErrorExp.get();
1543 1.1 mrg }
1544 1.1 mrg }
1545 1.1 mrg
1546 1.1 mrg final switch (agg.classKind)
1547 1.1 mrg {
1548 1.1 mrg case ClassKind.d:
1549 1.1 mrg link = LINK.d;
1550 1.1 mrg break;
1551 1.1 mrg case ClassKind.cpp:
1552 1.1 mrg link = LINK.cpp;
1553 1.1 mrg break;
1554 1.1 mrg case ClassKind.objc:
1555 1.1 mrg link = LINK.objc;
1556 1.1 mrg break;
1557 1.1 mrg case ClassKind.c:
1558 1.1 mrg link = LINK.c;
1559 1.1 mrg break;
1560 1.1 mrg }
1561 1.1 mrg }
1562 1.1 mrg }
1563 1.1 mrg auto linkage = linkageToChars(link);
1564 1.1 mrg auto se = new StringExp(e.loc, linkage.toDString());
1565 1.1 mrg return se.expressionSemantic(sc);
1566 1.1 mrg }
1567 1.1 mrg if (e.ident == Id.allMembers ||
1568 1.1 mrg e.ident == Id.derivedMembers)
1569 1.1 mrg {
1570 1.1 mrg if (dim != 1)
1571 1.1 mrg return dimError(1);
1572 1.1 mrg
1573 1.1 mrg auto o = (*e.args)[0];
1574 1.1 mrg auto s = getDsymbol(o);
1575 1.1 mrg if (!s)
1576 1.1 mrg {
1577 1.1 mrg e.error("In expression `%s` `%s` can't have members", e.toChars(), o.toChars());
1578 1.1 mrg e.errorSupplemental("`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", o.toChars());
1579 1.1 mrg
1580 1.1 mrg return ErrorExp.get();
1581 1.1 mrg }
1582 1.1 mrg if (auto imp = s.isImport())
1583 1.1 mrg {
1584 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=9692
1585 1.1 mrg s = imp.mod;
1586 1.1 mrg }
1587 1.1 mrg
1588 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=16044
1589 1.1 mrg if (auto p = s.isPackage())
1590 1.1 mrg {
1591 1.1 mrg if (auto pm = p.isPackageMod())
1592 1.1 mrg s = pm;
1593 1.1 mrg }
1594 1.1 mrg
1595 1.1 mrg auto sds = s.isScopeDsymbol();
1596 1.1 mrg if (!sds || sds.isTemplateDeclaration())
1597 1.1 mrg {
1598 1.1 mrg e.error("In expression `%s` %s `%s` has no members", e.toChars(), s.kind(), s.toChars());
1599 1.1 mrg e.errorSupplemental("`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation", s.toChars());
1600 1.1 mrg return ErrorExp.get();
1601 1.1 mrg }
1602 1.1 mrg
1603 1.1 mrg auto idents = new Identifiers();
1604 1.1 mrg
1605 1.1 mrg int pushIdentsDg(size_t n, Dsymbol sm)
1606 1.1 mrg {
1607 1.1 mrg if (!sm)
1608 1.1 mrg return 1;
1609 1.1 mrg
1610 1.1 mrg // skip local symbols, such as static foreach loop variables
1611 1.1 mrg if (auto decl = sm.isDeclaration())
1612 1.1 mrg {
1613 1.1 mrg if (decl.storage_class & STC.local)
1614 1.1 mrg {
1615 1.1 mrg return 0;
1616 1.1 mrg }
1617 1.1 mrg // skip 'this' context pointers
1618 1.1 mrg else if (decl.isThisDeclaration())
1619 1.1 mrg return 0;
1620 1.1 mrg }
1621 1.1 mrg
1622 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=20915
1623 1.1 mrg // skip version and debug identifiers
1624 1.1 mrg if (sm.isVersionSymbol() || sm.isDebugSymbol())
1625 1.1 mrg return 0;
1626 1.1 mrg
1627 1.1 mrg //printf("\t[%i] %s %s\n", i, sm.kind(), sm.toChars());
1628 1.1 mrg if (sm.ident)
1629 1.1 mrg {
1630 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=10096
1631 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=10100
1632 1.1 mrg // Skip over internal members in __traits(allMembers)
1633 1.1 mrg if ((sm.isCtorDeclaration() && sm.ident != Id.ctor) ||
1634 1.1 mrg (sm.isDtorDeclaration() && sm.ident != Id.dtor) ||
1635 1.1 mrg (sm.isPostBlitDeclaration() && sm.ident != Id.postblit) ||
1636 1.1 mrg sm.isInvariantDeclaration() ||
1637 1.1 mrg sm.isUnitTestDeclaration())
1638 1.1 mrg
1639 1.1 mrg {
1640 1.1 mrg return 0;
1641 1.1 mrg }
1642 1.1 mrg if (sm.ident == Id.empty)
1643 1.1 mrg {
1644 1.1 mrg return 0;
1645 1.1 mrg }
1646 1.1 mrg if (sm.isTypeInfoDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=15177
1647 1.1 mrg return 0;
1648 1.1 mrg if ((!sds.isModule() && !sds.isPackage()) && sm.isImport()) // https://issues.dlang.org/show_bug.cgi?id=17057
1649 1.1 mrg return 0;
1650 1.1 mrg
1651 1.1 mrg //printf("\t%s\n", sm.ident.toChars());
1652 1.1 mrg
1653 1.1 mrg /* Skip if already present in idents[]
1654 1.1 mrg */
1655 1.1 mrg foreach (id; *idents)
1656 1.1 mrg {
1657 1.1 mrg if (id == sm.ident)
1658 1.1 mrg return 0;
1659 1.1 mrg
1660 1.1 mrg // Avoid using strcmp in the first place due to the performance impact in an O(N^2) loop.
1661 1.1 mrg debug
1662 1.1 mrg {
1663 1.1 mrg import core.stdc.string : strcmp;
1664 1.1 mrg assert(strcmp(id.toChars(), sm.ident.toChars()) != 0);
1665 1.1 mrg }
1666 1.1 mrg }
1667 1.1 mrg idents.push(sm.ident);
1668 1.1 mrg }
1669 1.1 mrg else if (auto ed = sm.isEnumDeclaration())
1670 1.1 mrg {
1671 1.1 mrg ScopeDsymbol._foreach(null, ed.members, &pushIdentsDg);
1672 1.1 mrg }
1673 1.1 mrg return 0;
1674 1.1 mrg }
1675 1.1 mrg
1676 1.1 mrg ScopeDsymbol._foreach(sc, sds.members, &pushIdentsDg);
1677 1.1 mrg auto cd = sds.isClassDeclaration();
1678 1.1 mrg if (cd && e.ident == Id.allMembers)
1679 1.1 mrg {
1680 1.1 mrg if (cd.semanticRun < PASS.semanticdone)
1681 1.1 mrg cd.dsymbolSemantic(null); // https://issues.dlang.org/show_bug.cgi?id=13668
1682 1.1 mrg // Try to resolve forward reference
1683 1.1 mrg
1684 1.1 mrg void pushBaseMembersDg(ClassDeclaration cd)
1685 1.1 mrg {
1686 1.1 mrg for (size_t i = 0; i < cd.baseclasses.dim; i++)
1687 1.1 mrg {
1688 1.1 mrg auto cb = (*cd.baseclasses)[i].sym;
1689 1.1 mrg assert(cb);
1690 1.1 mrg ScopeDsymbol._foreach(null, cb.members, &pushIdentsDg);
1691 1.1 mrg if (cb.baseclasses.dim)
1692 1.1 mrg pushBaseMembersDg(cb);
1693 1.1 mrg }
1694 1.1 mrg }
1695 1.1 mrg
1696 1.1 mrg pushBaseMembersDg(cd);
1697 1.1 mrg }
1698 1.1 mrg
1699 1.1 mrg // Turn Identifiers into StringExps reusing the allocated array
1700 1.1 mrg assert(Expressions.sizeof == Identifiers.sizeof);
1701 1.1 mrg auto exps = cast(Expressions*)idents;
1702 1.1 mrg foreach (i, id; *idents)
1703 1.1 mrg {
1704 1.1 mrg auto se = new StringExp(e.loc, id.toString());
1705 1.1 mrg (*exps)[i] = se;
1706 1.1 mrg }
1707 1.1 mrg
1708 1.1 mrg /* Making this a tuple is more flexible, as it can be statically unrolled.
1709 1.1 mrg * To make an array literal, enclose __traits in [ ]:
1710 1.1 mrg * [ __traits(allMembers, ...) ]
1711 1.1 mrg */
1712 1.1 mrg Expression ex = new TupleExp(e.loc, exps);
1713 1.1 mrg ex = ex.expressionSemantic(sc);
1714 1.1 mrg return ex;
1715 1.1 mrg }
1716 1.1 mrg if (e.ident == Id.compiles)
1717 1.1 mrg {
1718 1.1 mrg /* Determine if all the objects - types, expressions, or symbols -
1719 1.1 mrg * compile without error
1720 1.1 mrg */
1721 1.1 mrg if (!dim)
1722 1.1 mrg return False();
1723 1.1 mrg
1724 1.1 mrg foreach (o; *e.args)
1725 1.1 mrg {
1726 1.1 mrg uint errors = global.startGagging();
1727 1.1 mrg Scope* sc2 = sc.push();
1728 1.1 mrg sc2.tinst = null;
1729 1.1 mrg sc2.minst = null;
1730 1.1 mrg sc2.flags = (sc.flags & ~(SCOPE.ctfe | SCOPE.condition)) | SCOPE.compile | SCOPE.fullinst;
1731 1.1 mrg
1732 1.1 mrg bool err = false;
1733 1.1 mrg
1734 1.1 mrg auto t = isType(o);
1735 1.1 mrg auto ex = isExpression(o);
1736 1.1 mrg if (t)
1737 1.1 mrg {
1738 1.1 mrg Dsymbol s;
1739 1.1 mrg t.resolve(e.loc, sc2, ex, t, s);
1740 1.1 mrg if (t)
1741 1.1 mrg {
1742 1.1 mrg t.typeSemantic(e.loc, sc2);
1743 1.1 mrg if (t.ty == Terror)
1744 1.1 mrg err = true;
1745 1.1 mrg }
1746 1.1 mrg else if (s && s.errors)
1747 1.1 mrg err = true;
1748 1.1 mrg }
1749 1.1 mrg if (ex)
1750 1.1 mrg {
1751 1.1 mrg ex = ex.expressionSemantic(sc2);
1752 1.1 mrg ex = resolvePropertiesOnly(sc2, ex);
1753 1.1 mrg ex = ex.optimize(WANTvalue);
1754 1.1 mrg if (sc2.func && sc2.func.type.ty == Tfunction)
1755 1.1 mrg {
1756 1.1 mrg const tf = cast(TypeFunction)sc2.func.type;
1757 1.1 mrg err |= tf.isnothrow && canThrow(ex, sc2.func, false);
1758 1.1 mrg }
1759 1.1 mrg ex = checkGC(sc2, ex);
1760 1.1 mrg if (ex.op == EXP.error)
1761 1.1 mrg err = true;
1762 1.1 mrg }
1763 1.1 mrg
1764 1.1 mrg // Carefully detach the scope from the parent and throw it away as
1765 1.1 mrg // we only need it to evaluate the expression
1766 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=15428
1767 1.1 mrg sc2.detach();
1768 1.1 mrg
1769 1.1 mrg if (global.endGagging(errors) || err)
1770 1.1 mrg {
1771 1.1 mrg return False();
1772 1.1 mrg }
1773 1.1 mrg }
1774 1.1 mrg return True();
1775 1.1 mrg }
1776 1.1 mrg if (e.ident == Id.isSame)
1777 1.1 mrg {
1778 1.1 mrg /* Determine if two symbols are the same
1779 1.1 mrg */
1780 1.1 mrg if (dim != 2)
1781 1.1 mrg return dimError(2);
1782 1.1 mrg
1783 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=20761
1784 1.1 mrg // tiarg semantic may expand in place the list of arguments, for example:
1785 1.1 mrg //
1786 1.1 mrg // before tiarg sema: __traits(isSame, seq!(0,0), seq!(1,1))
1787 1.1 mrg // after : __traits(isSame, 0, 0, 1, 1)
1788 1.1 mrg //
1789 1.1 mrg // so we split in two lists
1790 1.1 mrg Objects ob1;
1791 1.1 mrg ob1.push((*e.args)[0]);
1792 1.1 mrg Objects ob2;
1793 1.1 mrg ob2.push((*e.args)[1]);
1794 1.1 mrg if (!TemplateInstance.semanticTiargs(e.loc, sc, &ob1, 0))
1795 1.1 mrg return ErrorExp.get();
1796 1.1 mrg if (!TemplateInstance.semanticTiargs(e.loc, sc, &ob2, 0))
1797 1.1 mrg return ErrorExp.get();
1798 1.1 mrg if (ob1.dim != ob2.dim)
1799 1.1 mrg return False();
1800 1.1 mrg foreach (immutable i; 0 .. ob1.dim)
1801 1.1 mrg if (!ob1[i].isSame(ob2[i], sc))
1802 1.1 mrg return False();
1803 1.1 mrg return True();
1804 1.1 mrg }
1805 1.1 mrg if (e.ident == Id.getUnitTests)
1806 1.1 mrg {
1807 1.1 mrg if (dim != 1)
1808 1.1 mrg return dimError(1);
1809 1.1 mrg
1810 1.1 mrg auto o = (*e.args)[0];
1811 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
1812 1.1 mrg if (!s)
1813 1.1 mrg {
1814 1.1 mrg e.error("argument `%s` to __traits(getUnitTests) must be a module or aggregate",
1815 1.1 mrg o.toChars());
1816 1.1 mrg return ErrorExp.get();
1817 1.1 mrg }
1818 1.1 mrg if (auto imp = s.isImport()) // https://issues.dlang.org/show_bug.cgi?id=10990
1819 1.1 mrg s = imp.mod;
1820 1.1 mrg
1821 1.1 mrg auto sds = s.isScopeDsymbol();
1822 1.1 mrg if (!sds || sds.isTemplateDeclaration())
1823 1.1 mrg {
1824 1.1 mrg e.error("argument `%s` to __traits(getUnitTests) must be a module or aggregate, not a %s",
1825 1.1 mrg s.toChars(), s.kind());
1826 1.1 mrg return ErrorExp.get();
1827 1.1 mrg }
1828 1.1 mrg
1829 1.1 mrg auto exps = new Expressions();
1830 1.1 mrg if (global.params.useUnitTests)
1831 1.1 mrg {
1832 1.1 mrg bool[void*] uniqueUnitTests;
1833 1.1 mrg
1834 1.1 mrg void symbolDg(Dsymbol s)
1835 1.1 mrg {
1836 1.1 mrg if (auto ad = s.isAttribDeclaration())
1837 1.1 mrg {
1838 1.1 mrg ad.include(null).foreachDsymbol(&symbolDg);
1839 1.1 mrg }
1840 1.1 mrg else if (auto tm = s.isTemplateMixin())
1841 1.1 mrg {
1842 1.1 mrg tm.members.foreachDsymbol(&symbolDg);
1843 1.1 mrg }
1844 1.1 mrg else if (auto ud = s.isUnitTestDeclaration())
1845 1.1 mrg {
1846 1.1 mrg if (cast(void*)ud in uniqueUnitTests)
1847 1.1 mrg return;
1848 1.1 mrg
1849 1.1 mrg uniqueUnitTests[cast(void*)ud] = true;
1850 1.1 mrg
1851 1.1 mrg auto ad = new FuncAliasDeclaration(ud.ident, ud, false);
1852 1.1 mrg ad.visibility = ud.visibility;
1853 1.1 mrg
1854 1.1 mrg auto e = new DsymbolExp(Loc.initial, ad, false);
1855 1.1 mrg exps.push(e);
1856 1.1 mrg }
1857 1.1 mrg }
1858 1.1 mrg
1859 1.1 mrg sds.members.foreachDsymbol(&symbolDg);
1860 1.1 mrg }
1861 1.1 mrg auto te = new TupleExp(e.loc, exps);
1862 1.1 mrg return te.expressionSemantic(sc);
1863 1.1 mrg }
1864 1.1 mrg if (e.ident == Id.getVirtualIndex)
1865 1.1 mrg {
1866 1.1 mrg if (dim != 1)
1867 1.1 mrg return dimError(1);
1868 1.1 mrg
1869 1.1 mrg auto o = (*e.args)[0];
1870 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
1871 1.1 mrg
1872 1.1 mrg auto fd = s ? s.isFuncDeclaration() : null;
1873 1.1 mrg if (!fd)
1874 1.1 mrg {
1875 1.1 mrg e.error("first argument to __traits(getVirtualIndex) must be a function");
1876 1.1 mrg return ErrorExp.get();
1877 1.1 mrg }
1878 1.1 mrg
1879 1.1 mrg fd = fd.toAliasFunc(); // Necessary to support multiple overloads.
1880 1.1 mrg return new IntegerExp(e.loc, fd.vtblIndex, Type.tptrdiff_t);
1881 1.1 mrg }
1882 1.1 mrg if (e.ident == Id.getPointerBitmap)
1883 1.1 mrg {
1884 1.1 mrg return pointerBitmap(e);
1885 1.1 mrg }
1886 1.1 mrg if (e.ident == Id.initSymbol)
1887 1.1 mrg {
1888 1.1 mrg if (dim != 1)
1889 1.1 mrg return dimError(1);
1890 1.1 mrg
1891 1.1 mrg auto o = (*e.args)[0];
1892 1.1 mrg Type t = isType(o);
1893 1.1 mrg AggregateDeclaration ad = t ? isAggregate(t) : null;
1894 1.1 mrg
1895 1.1 mrg // Interfaces don't have an init symbol and hence cause linker errors
1896 1.1 mrg if (!ad || ad.isInterfaceDeclaration())
1897 1.1 mrg {
1898 1.1 mrg e.error("struct / class type expected as argument to __traits(initSymbol) instead of `%s`", o.toChars());
1899 1.1 mrg return ErrorExp.get();
1900 1.1 mrg }
1901 1.1 mrg
1902 1.1 mrg Declaration d = new SymbolDeclaration(ad.loc, ad);
1903 1.1 mrg d.type = Type.tvoid.arrayOf().constOf();
1904 1.1 mrg d.storage_class |= STC.rvalue;
1905 1.1 mrg return new VarExp(e.loc, d);
1906 1.1 mrg }
1907 1.1 mrg if (e.ident == Id.isZeroInit)
1908 1.1 mrg {
1909 1.1 mrg if (dim != 1)
1910 1.1 mrg return dimError(1);
1911 1.1 mrg
1912 1.1 mrg auto o = (*e.args)[0];
1913 1.1 mrg Type t = isType(o);
1914 1.1 mrg if (!t)
1915 1.1 mrg {
1916 1.1 mrg e.error("type expected as second argument of __traits `%s` instead of `%s`",
1917 1.1 mrg e.ident.toChars(), o.toChars());
1918 1.1 mrg return ErrorExp.get();
1919 1.1 mrg }
1920 1.1 mrg
1921 1.1 mrg Type tb = t.baseElemOf();
1922 1.1 mrg return tb.isZeroInit(e.loc) ? True() : False();
1923 1.1 mrg }
1924 1.1 mrg if (e.ident == Id.getTargetInfo)
1925 1.1 mrg {
1926 1.1 mrg if (dim != 1)
1927 1.1 mrg return dimError(1);
1928 1.1 mrg
1929 1.1 mrg auto ex = isExpression((*e.args)[0]);
1930 1.1 mrg StringExp se = ex ? ex.ctfeInterpret().toStringExp() : null;
1931 1.1 mrg if (!ex || !se || se.len == 0)
1932 1.1 mrg {
1933 1.1 mrg e.error("string expected as argument of __traits `%s` instead of `%s`", e.ident.toChars(), ex.toChars());
1934 1.1 mrg return ErrorExp.get();
1935 1.1 mrg }
1936 1.1 mrg se = se.toUTF8(sc);
1937 1.1 mrg
1938 1.1 mrg const slice = se.peekString();
1939 1.1 mrg Expression r = target.getTargetInfo(slice.ptr, e.loc); // BUG: reliance on terminating 0
1940 1.1 mrg if (!r)
1941 1.1 mrg {
1942 1.1 mrg e.error("`getTargetInfo` key `\"%.*s\"` not supported by this implementation",
1943 1.1 mrg cast(int)slice.length, slice.ptr);
1944 1.1 mrg return ErrorExp.get();
1945 1.1 mrg }
1946 1.1 mrg return r.expressionSemantic(sc);
1947 1.1 mrg }
1948 1.1 mrg if (e.ident == Id.getLocation)
1949 1.1 mrg {
1950 1.1 mrg if (dim != 1)
1951 1.1 mrg return dimError(1);
1952 1.1 mrg auto arg0 = (*e.args)[0];
1953 1.1 mrg Dsymbol s = getDsymbolWithoutExpCtx(arg0);
1954 1.1 mrg if (!s || !s.loc.isValid())
1955 1.1 mrg {
1956 1.1 mrg e.error("can only get the location of a symbol, not `%s`", arg0.toChars());
1957 1.1 mrg return ErrorExp.get();
1958 1.1 mrg }
1959 1.1 mrg
1960 1.1 mrg const fd = s.isFuncDeclaration();
1961 1.1 mrg // FIXME:td.overnext is always set, even when using an index on it
1962 1.1 mrg //const td = s.isTemplateDeclaration();
1963 1.1 mrg if ((fd && fd.overnext) /*|| (td && td.overnext)*/)
1964 1.1 mrg {
1965 1.1 mrg e.error("cannot get location of an overload set, " ~
1966 1.1 mrg "use `__traits(getOverloads, ..., \"%s\"%s)[N]` " ~
1967 1.1 mrg "to get the Nth overload",
1968 1.1 mrg arg0.toChars(), /*td ? ", true".ptr :*/ "".ptr);
1969 1.1 mrg return ErrorExp.get();
1970 1.1 mrg }
1971 1.1 mrg
1972 1.1 mrg auto exps = new Expressions(3);
1973 1.1 mrg (*exps)[0] = new StringExp(e.loc, s.loc.filename.toDString());
1974 1.1 mrg (*exps)[1] = new IntegerExp(e.loc, s.loc.linnum,Type.tint32);
1975 1.1 mrg (*exps)[2] = new IntegerExp(e.loc, s.loc.charnum,Type.tint32);
1976 1.1 mrg auto tup = new TupleExp(e.loc, exps);
1977 1.1 mrg return tup.expressionSemantic(sc);
1978 1.1 mrg }
1979 1.1 mrg if (e.ident == Id.getCppNamespaces)
1980 1.1 mrg {
1981 1.1 mrg auto o = (*e.args)[0];
1982 1.1 mrg auto s = getDsymbolWithoutExpCtx(o);
1983 1.1 mrg auto exps = new Expressions(0);
1984 1.1 mrg if (auto d = s.isDeclaration())
1985 1.1 mrg {
1986 1.1 mrg if (d.inuse)
1987 1.1 mrg {
1988 1.1 mrg d.error("circular reference in `__traits(GetCppNamespaces,...)`");
1989 1.1 mrg return ErrorExp.get();
1990 1.1 mrg }
1991 1.1 mrg d.inuse = 1;
1992 1.1 mrg }
1993 1.1 mrg
1994 1.1 mrg /**
1995 1.1 mrg Prepend the namespaces in the linked list `ns` to `es`.
1996 1.1 mrg
1997 1.1 mrg Returns: true if `ns` contains an `ErrorExp`.
1998 1.1 mrg */
1999 1.1 mrg bool prependNamespaces(Expressions* es, CPPNamespaceDeclaration ns)
2000 1.1 mrg {
2001 1.1 mrg // Semantic processing will convert `extern(C++, "a", "b", "c")`
2002 1.1 mrg // into `extern(C++, "a") extern(C++, "b") extern(C++, "c")`,
2003 1.1 mrg // creating a linked list what `a`'s `cppnamespace` points to `b`,
2004 1.1 mrg // and `b`'s points to `c`. Our entry point is `a`.
2005 1.1 mrg for (; ns !is null; ns = ns.cppnamespace)
2006 1.1 mrg {
2007 1.1 mrg ns.dsymbolSemantic(sc);
2008 1.1 mrg
2009 1.1 mrg if (ns.exp.isErrorExp())
2010 1.1 mrg return true;
2011 1.1 mrg
2012 1.1 mrg auto se = ns.exp.toStringExp();
2013 1.1 mrg // extern(C++, (emptyTuple))
2014 1.1 mrg // struct D {}
2015 1.1 mrg // will produce a blank ident
2016 1.1 mrg if (!se.len)
2017 1.1 mrg continue;
2018 1.1 mrg es.insert(0, se);
2019 1.1 mrg }
2020 1.1 mrg return false;
2021 1.1 mrg }
2022 1.1 mrg for (auto p = s; !p.isModule(); p = p.toParent())
2023 1.1 mrg {
2024 1.1 mrg p.dsymbolSemantic(sc);
2025 1.1 mrg auto pp = p.toParent();
2026 1.1 mrg if (pp.isTemplateInstance())
2027 1.1 mrg {
2028 1.1 mrg if (!p.cppnamespace)
2029 1.1 mrg continue;
2030 1.1 mrg //if (!p.toParent().cppnamespace)
2031 1.1 mrg // continue;
2032 1.1 mrg auto inner = new Expressions(0);
2033 1.1 mrg auto outer = new Expressions(0);
2034 1.1 mrg if (prependNamespaces(inner, p.cppnamespace)) return ErrorExp.get();
2035 1.1 mrg if (prependNamespaces(outer, pp.cppnamespace)) return ErrorExp.get();
2036 1.1 mrg
2037 1.1 mrg size_t i = 0;
2038 1.1 mrg while(i < outer.dim && ((*inner)[i]) == (*outer)[i])
2039 1.1 mrg i++;
2040 1.1 mrg
2041 1.1 mrg foreach_reverse (ns; (*inner)[][i .. $])
2042 1.1 mrg exps.insert(0, ns);
2043 1.1 mrg continue;
2044 1.1 mrg }
2045 1.1 mrg
2046 1.1 mrg if (p.isNspace())
2047 1.1 mrg exps.insert(0, new StringExp(p.loc, p.ident.toString()));
2048 1.1 mrg
2049 1.1 mrg if (prependNamespaces(exps, p.cppnamespace))
2050 1.1 mrg return ErrorExp.get();
2051 1.1 mrg }
2052 1.1 mrg if (auto d = s.isDeclaration())
2053 1.1 mrg d.inuse = 0;
2054 1.1 mrg auto tup = new TupleExp(e.loc, exps);
2055 1.1 mrg return tup.expressionSemantic(sc);
2056 1.1 mrg }
2057 1.1 mrg //https://issues.dlang.org/show_bug.cgi?id=22291
2058 1.1 mrg if (e.ident == Id.parameters)
2059 1.1 mrg {
2060 1.1 mrg //No args are valid
2061 1.1 mrg if (e.args)
2062 1.1 mrg {
2063 1.1 mrg char[] contents = cast(char[]) e.args.toString();
2064 1.1 mrg contents = contents[1..$];
2065 1.1 mrg contents[$-1] = '\0';
2066 1.1 mrg e.error("`__traits(parameters)` cannot have arguments, but `%s` was supplied", contents.ptr);
2067 1.1 mrg return ErrorExp.get();
2068 1.1 mrg }
2069 1.1 mrg
2070 1.1 mrg auto fd = sc.getEnclosingFunction();
2071 1.1 mrg if (!fd)
2072 1.1 mrg {
2073 1.1 mrg e.error("`__traits(parameters)` may only be used inside a function");
2074 1.1 mrg return ErrorExp.get();
2075 1.1 mrg }
2076 1.1 mrg
2077 1.1 mrg auto tf = fd.type.isTypeFunction();
2078 1.1 mrg assert(tf);
2079 1.1 mrg auto exps = new Expressions(0);
2080 1.1 mrg int addParameterDG(size_t idx, Parameter x)
2081 1.1 mrg {
2082 1.1 mrg assert(x.ident);
2083 1.1 mrg exps.push(new IdentifierExp(e.loc, x.ident));
2084 1.1 mrg return 0;
2085 1.1 mrg }
2086 1.1 mrg /*
2087 1.1 mrg This is required since not all "parameters" actually have a name
2088 1.1 mrg until they (tuples) are expanded e.g. an anonymous tuple parameter's
2089 1.1 mrg contents get given names but not the tuple itself.
2090 1.1 mrg */
2091 1.1 mrg Parameter._foreach(tf.parameterList.parameters, &addParameterDG);
2092 1.1 mrg auto tup = new TupleExp(e.loc, exps);
2093 1.1 mrg return tup.expressionSemantic(sc);
2094 1.1 mrg }
2095 1.1 mrg static const(char)[] trait_search_fp(const(char)[] seed, out int cost)
2096 1.1 mrg {
2097 1.1 mrg //printf("trait_search_fp('%s')\n", seed);
2098 1.1 mrg if (!seed.length)
2099 1.1 mrg return null;
2100 1.1 mrg cost = 0; // all the same cost
2101 1.1 mrg const sv = traitsStringTable.lookup(seed);
2102 1.1 mrg return sv ? sv.toString() : null;
2103 1.1 mrg }
2104 1.1 mrg
2105 1.1 mrg if (auto sub = speller!trait_search_fp(e.ident.toString()))
2106 1.1 mrg e.error("unrecognized trait `%s`, did you mean `%.*s`?", e.ident.toChars(), cast(int) sub.length, sub.ptr);
2107 1.1 mrg else
2108 1.1 mrg e.error("unrecognized trait `%s`", e.ident.toChars());
2109 1.1 mrg return ErrorExp.get();
2110 1.1 mrg }
2111 1.1 mrg
2112 1.1 mrg /// compare arguments of __traits(isSame)
2113 1.1 mrg private bool isSame(RootObject o1, RootObject o2, Scope* sc)
2114 1.1 mrg {
2115 1.1 mrg static FuncLiteralDeclaration isLambda(RootObject oarg)
2116 1.1 mrg {
2117 1.1 mrg if (auto t = isDsymbol(oarg))
2118 1.1 mrg {
2119 1.1 mrg if (auto td = t.isTemplateDeclaration())
2120 1.1 mrg {
2121 1.1 mrg if (td.members && td.members.dim == 1)
2122 1.1 mrg {
2123 1.1 mrg if (auto fd = (*td.members)[0].isFuncLiteralDeclaration())
2124 1.1 mrg return fd;
2125 1.1 mrg }
2126 1.1 mrg }
2127 1.1 mrg }
2128 1.1 mrg else if (auto ea = isExpression(oarg))
2129 1.1 mrg {
2130 1.1 mrg if (ea.op == EXP.function_)
2131 1.1 mrg {
2132 1.1 mrg if (auto fe = ea.isFuncExp())
2133 1.1 mrg return fe.fd;
2134 1.1 mrg }
2135 1.1 mrg }
2136 1.1 mrg return null;
2137 1.1 mrg }
2138 1.1 mrg
2139 1.1 mrg auto l1 = isLambda(o1);
2140 1.1 mrg auto l2 = isLambda(o2);
2141 1.1 mrg
2142 1.1 mrg if (l1 && l2)
2143 1.1 mrg {
2144 1.1 mrg import dmd.lambdacomp : isSameFuncLiteral;
2145 1.1 mrg if (isSameFuncLiteral(l1, l2, sc))
2146 1.1 mrg return true;
2147 1.1 mrg }
2148 1.1 mrg
2149 1.1 mrg // issue 12001, allow isSame, <BasicType>, <BasicType>
2150 1.1 mrg Type t1 = isType(o1);
2151 1.1 mrg Type t2 = isType(o2);
2152 1.1 mrg if (t1 && t2 && t1.equals(t2))
2153 1.1 mrg return true;
2154 1.1 mrg
2155 1.1 mrg auto s1 = getDsymbol(o1);
2156 1.1 mrg auto s2 = getDsymbol(o2);
2157 1.1 mrg //printf("isSame: %s, %s\n", o1.toChars(), o2.toChars());
2158 1.1 mrg version (none)
2159 1.1 mrg {
2160 1.1 mrg printf("o1: %p\n", o1);
2161 1.1 mrg printf("o2: %p\n", o2);
2162 1.1 mrg if (!s1)
2163 1.1 mrg {
2164 1.1 mrg if (auto ea = isExpression(o1))
2165 1.1 mrg printf("%s\n", ea.toChars());
2166 1.1 mrg if (auto ta = isType(o1))
2167 1.1 mrg printf("%s\n", ta.toChars());
2168 1.1 mrg return false;
2169 1.1 mrg }
2170 1.1 mrg else
2171 1.1 mrg printf("%s %s\n", s1.kind(), s1.toChars());
2172 1.1 mrg }
2173 1.1 mrg if (!s1 && !s2)
2174 1.1 mrg {
2175 1.1 mrg auto ea1 = isExpression(o1);
2176 1.1 mrg auto ea2 = isExpression(o2);
2177 1.1 mrg if (ea1 && ea2)
2178 1.1 mrg {
2179 1.1 mrg if (ea1.equals(ea2))
2180 1.1 mrg return true;
2181 1.1 mrg }
2182 1.1 mrg }
2183 1.1 mrg if (!s1 || !s2)
2184 1.1 mrg return false;
2185 1.1 mrg
2186 1.1 mrg s1 = s1.toAlias();
2187 1.1 mrg s2 = s2.toAlias();
2188 1.1 mrg
2189 1.1 mrg if (auto fa1 = s1.isFuncAliasDeclaration())
2190 1.1 mrg s1 = fa1.toAliasFunc();
2191 1.1 mrg if (auto fa2 = s2.isFuncAliasDeclaration())
2192 1.1 mrg s2 = fa2.toAliasFunc();
2193 1.1 mrg
2194 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=11259
2195 1.1 mrg // compare import symbol to a package symbol
2196 1.1 mrg static bool cmp(Dsymbol s1, Dsymbol s2)
2197 1.1 mrg {
2198 1.1 mrg auto imp = s1.isImport();
2199 1.1 mrg return imp && imp.pkg && imp.pkg == s2.isPackage();
2200 1.1 mrg }
2201 1.1 mrg
2202 1.1 mrg if (cmp(s1,s2) || cmp(s2,s1))
2203 1.1 mrg return true;
2204 1.1 mrg
2205 1.1 mrg if (s1 == s2)
2206 1.1 mrg return true;
2207 1.1 mrg
2208 1.1 mrg // https://issues.dlang.org/show_bug.cgi?id=18771
2209 1.1 mrg // OverloadSets are equal if they contain the same functions
2210 1.1 mrg auto overSet1 = s1.isOverloadSet();
2211 1.1 mrg if (!overSet1)
2212 1.1 mrg return false;
2213 1.1 mrg
2214 1.1 mrg auto overSet2 = s2.isOverloadSet();
2215 1.1 mrg if (!overSet2)
2216 1.1 mrg return false;
2217 1.1 mrg
2218 1.1 mrg if (overSet1.a.dim != overSet2.a.dim)
2219 1.1 mrg return false;
2220 1.1 mrg
2221 1.1 mrg // OverloadSets contain array of Dsymbols => O(n*n)
2222 1.1 mrg // to compare for equality as the order of overloads
2223 1.1 mrg // might not be the same
2224 1.1 mrg Lnext:
2225 1.1 mrg foreach(overload1; overSet1.a)
2226 1.1 mrg {
2227 1.1 mrg foreach(overload2; overSet2.a)
2228 1.1 mrg {
2229 1.1 mrg if (overload1 == overload2)
2230 1.1 mrg continue Lnext;
2231 1.1 mrg }
2232 1.1 mrg return false;
2233 1.1 mrg }
2234 1.1 mrg return true;
2235 1.1 mrg }
2236