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