1 /** 2 * Performs the semantic2 stage, which deals with initializer expressions. 3 * 4 * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic2.d, _semantic2.d) 8 * Documentation: https://dlang.org/phobos/dmd_semantic2.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/semantic2.d 10 */ 11 12 module dmd.semantic2; 13 14 import core.stdc.stdio; 15 import core.stdc.string; 16 17 import dmd.aggregate; 18 import dmd.aliasthis; 19 import dmd.arraytypes; 20 import dmd.astcodegen; 21 import dmd.attrib; 22 import dmd.blockexit; 23 import dmd.clone; 24 import dmd.dcast; 25 import dmd.dclass; 26 import dmd.declaration; 27 import dmd.denum; 28 import dmd.dimport; 29 import dmd.dinterpret; 30 import dmd.dmodule; 31 import dmd.dscope; 32 import dmd.dstruct; 33 import dmd.dsymbol; 34 import dmd.dsymbolsem; 35 import dmd.dtemplate; 36 import dmd.dversion; 37 import dmd.errors; 38 import dmd.escape; 39 import dmd.expression; 40 import dmd.expressionsem; 41 import dmd.func; 42 import dmd.globals; 43 import dmd.id; 44 import dmd.identifier; 45 import dmd.init; 46 import dmd.initsem; 47 import dmd.hdrgen; 48 import dmd.mtype; 49 import dmd.nogc; 50 import dmd.nspace; 51 import dmd.objc; 52 import dmd.opover; 53 import dmd.parse; 54 import dmd.root.filename; 55 import dmd.root.outbuffer; 56 import dmd.root.rmem; 57 import dmd.root.rootobject; 58 import dmd.sideeffect; 59 import dmd.statementsem; 60 import dmd.staticassert; 61 import dmd.tokens; 62 import dmd.utf; 63 import dmd.statement; 64 import dmd.target; 65 import dmd.templateparamsem; 66 import dmd.typesem; 67 import dmd.visitor; 68 69 enum LOG = false; 70 71 72 /************************************* 73 * Does semantic analysis on initializers and members of aggregates. 74 */ 75 extern(C++) void semantic2(Dsymbol dsym, Scope* sc) 76 { 77 scope v = new Semantic2Visitor(sc); 78 dsym.accept(v); 79 } 80 81 private extern(C++) final class Semantic2Visitor : Visitor 82 { 83 alias visit = Visitor.visit; 84 Scope* sc; 85 this(Scope* sc) 86 { 87 this.sc = sc; 88 } 89 90 override void visit(Dsymbol) {} 91 92 override void visit(StaticAssert sa) 93 { 94 //printf("StaticAssert::semantic2() %s\n", sa.toChars()); 95 auto sds = new ScopeDsymbol(); 96 sc = sc.push(sds); 97 sc.tinst = null; 98 sc.minst = null; 99 100 import dmd.staticcond; 101 bool errors; 102 bool result = evalStaticCondition(sc, sa.exp, sa.exp, errors); 103 sc = sc.pop(); 104 if (errors) 105 { 106 errorSupplemental(sa.loc, "while evaluating: `static assert(%s)`", sa.exp.toChars()); 107 } 108 else if (!result) 109 { 110 if (sa.msg) 111 { 112 sc = sc.startCTFE(); 113 sa.msg = sa.msg.expressionSemantic(sc); 114 sa.msg = resolveProperties(sc, sa.msg); 115 sc = sc.endCTFE(); 116 sa.msg = sa.msg.ctfeInterpret(); 117 if (StringExp se = sa.msg.toStringExp()) 118 { 119 // same with pragma(msg) 120 const slice = se.toUTF8(sc).peekString(); 121 error(sa.loc, "static assert: \"%.*s\"", cast(int)slice.length, slice.ptr); 122 } 123 else 124 error(sa.loc, "static assert: %s", sa.msg.toChars()); 125 } 126 else 127 error(sa.loc, "static assert: `%s` is false", sa.exp.toChars()); 128 if (sc.tinst) 129 sc.tinst.printInstantiationTrace(); 130 if (!global.gag) 131 fatal(); 132 } 133 } 134 135 override void visit(TemplateInstance tempinst) 136 { 137 if (tempinst.semanticRun >= PASS.semantic2) 138 return; 139 tempinst.semanticRun = PASS.semantic2; 140 static if (LOG) 141 { 142 printf("+TemplateInstance.semantic2('%s')\n", tempinst.toChars()); 143 } 144 if (!tempinst.errors && tempinst.members) 145 { 146 TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration(); 147 assert(tempdecl); 148 149 sc = tempdecl._scope; 150 assert(sc); 151 sc = sc.push(tempinst.argsym); 152 sc = sc.push(tempinst); 153 sc.tinst = tempinst; 154 sc.minst = tempinst.minst; 155 156 int needGagging = (tempinst.gagged && !global.gag); 157 uint olderrors = global.errors; 158 int oldGaggedErrors = -1; // dead-store to prevent spurious warning 159 if (needGagging) 160 oldGaggedErrors = global.startGagging(); 161 162 for (size_t i = 0; i < tempinst.members.dim; i++) 163 { 164 Dsymbol s = (*tempinst.members)[i]; 165 static if (LOG) 166 { 167 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); 168 } 169 s.semantic2(sc); 170 if (tempinst.gagged && global.errors != olderrors) 171 break; 172 } 173 174 if (global.errors != olderrors) 175 { 176 if (!tempinst.errors) 177 { 178 if (!tempdecl.literal) 179 tempinst.error(tempinst.loc, "error instantiating"); 180 if (tempinst.tinst) 181 tempinst.tinst.printInstantiationTrace(); 182 } 183 tempinst.errors = true; 184 } 185 if (needGagging) 186 global.endGagging(oldGaggedErrors); 187 188 sc = sc.pop(); 189 sc.pop(); 190 } 191 static if (LOG) 192 { 193 printf("-TemplateInstance.semantic2('%s')\n", tempinst.toChars()); 194 } 195 } 196 197 override void visit(TemplateMixin tmix) 198 { 199 if (tmix.semanticRun >= PASS.semantic2) 200 return; 201 tmix.semanticRun = PASS.semantic2; 202 static if (LOG) 203 { 204 printf("+TemplateMixin.semantic2('%s')\n", tmix.toChars()); 205 } 206 if (tmix.members) 207 { 208 assert(sc); 209 sc = sc.push(tmix.argsym); 210 sc = sc.push(tmix); 211 for (size_t i = 0; i < tmix.members.dim; i++) 212 { 213 Dsymbol s = (*tmix.members)[i]; 214 static if (LOG) 215 { 216 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); 217 } 218 s.semantic2(sc); 219 } 220 sc = sc.pop(); 221 sc.pop(); 222 } 223 static if (LOG) 224 { 225 printf("-TemplateMixin.semantic2('%s')\n", tmix.toChars()); 226 } 227 } 228 229 override void visit(VarDeclaration vd) 230 { 231 if (vd.semanticRun < PASS.semanticdone && vd.inuse) 232 return; 233 234 //printf("VarDeclaration::semantic2('%s')\n", toChars()); 235 236 if (vd.aliassym) // if it's a tuple 237 { 238 vd.aliassym.accept(this); 239 vd.semanticRun = PASS.semantic2done; 240 return; 241 } 242 243 UserAttributeDeclaration.checkGNUABITag(vd, vd.linkage); 244 245 if (vd._init && !vd.toParent().isFuncDeclaration()) 246 { 247 vd.inuse++; 248 249 /* https://issues.dlang.org/show_bug.cgi?id=20280 250 * 251 * Template instances may import modules that have not 252 * finished semantic1. 253 */ 254 if (!vd.type) 255 vd.dsymbolSemantic(sc); 256 257 258 // https://issues.dlang.org/show_bug.cgi?id=14166 259 // https://issues.dlang.org/show_bug.cgi?id=20417 260 // Don't run CTFE for the temporary variables inside typeof or __traits(compiles) 261 vd._init = vd._init.initializerSemantic(sc, vd.type, sc.intypeof == 1 || sc.flags & SCOPE.compile ? INITnointerpret : INITinterpret); 262 vd.inuse--; 263 } 264 if (vd._init && vd.storage_class & STC.manifest) 265 { 266 /* Cannot initializer enums with CTFE classreferences and addresses of struct literals. 267 * Scan initializer looking for them. Issue error if found. 268 */ 269 if (ExpInitializer ei = vd._init.isExpInitializer()) 270 { 271 static bool hasInvalidEnumInitializer(Expression e) 272 { 273 static bool arrayHasInvalidEnumInitializer(Expressions* elems) 274 { 275 foreach (e; *elems) 276 { 277 if (e && hasInvalidEnumInitializer(e)) 278 return true; 279 } 280 return false; 281 } 282 283 if (e.op == TOK.classReference) 284 return true; 285 if (e.op == TOK.address && (cast(AddrExp)e).e1.op == TOK.structLiteral) 286 return true; 287 if (e.op == TOK.arrayLiteral) 288 return arrayHasInvalidEnumInitializer((cast(ArrayLiteralExp)e).elements); 289 if (e.op == TOK.structLiteral) 290 return arrayHasInvalidEnumInitializer((cast(StructLiteralExp)e).elements); 291 if (e.op == TOK.assocArrayLiteral) 292 { 293 AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e; 294 return arrayHasInvalidEnumInitializer(ae.values) || 295 arrayHasInvalidEnumInitializer(ae.keys); 296 } 297 return false; 298 } 299 300 if (hasInvalidEnumInitializer(ei.exp)) 301 vd.error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead."); 302 } 303 } 304 else if (vd._init && vd.isThreadlocal()) 305 { 306 // Cannot initialize a thread-local class or pointer to struct variable with a literal 307 // that itself is a thread-local reference and would need dynamic initialization also. 308 if ((vd.type.ty == Tclass) && vd.type.isMutable() && !vd.type.isShared()) 309 { 310 ExpInitializer ei = vd._init.isExpInitializer(); 311 if (ei && ei.exp.op == TOK.classReference) 312 vd.error("is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead."); 313 } 314 else if (vd.type.ty == Tpointer && vd.type.nextOf().ty == Tstruct && vd.type.nextOf().isMutable() && !vd.type.nextOf().isShared()) 315 { 316 ExpInitializer ei = vd._init.isExpInitializer(); 317 if (ei && ei.exp.op == TOK.address && (cast(AddrExp)ei.exp).e1.op == TOK.structLiteral) 318 vd.error("is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead."); 319 } 320 } 321 vd.semanticRun = PASS.semantic2done; 322 } 323 324 override void visit(Module mod) 325 { 326 //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); 327 if (mod.semanticRun != PASS.semanticdone) // semantic() not completed yet - could be recursive call 328 return; 329 mod.semanticRun = PASS.semantic2; 330 // Note that modules get their own scope, from scratch. 331 // This is so regardless of where in the syntax a module 332 // gets imported, it is unaffected by context. 333 Scope* sc = Scope.createGlobal(mod); // create root scope 334 //printf("Module = %p\n", sc.scopesym); 335 // Pass 2 semantic routines: do initializers and function bodies 336 for (size_t i = 0; i < mod.members.dim; i++) 337 { 338 Dsymbol s = (*mod.members)[i]; 339 s.semantic2(sc); 340 } 341 if (mod.userAttribDecl) 342 { 343 mod.userAttribDecl.semantic2(sc); 344 } 345 sc = sc.pop(); 346 sc.pop(); 347 mod.semanticRun = PASS.semantic2done; 348 //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); 349 } 350 351 override void visit(FuncDeclaration fd) 352 { 353 if (fd.semanticRun >= PASS.semantic2done) 354 return; 355 356 if (fd.semanticRun < PASS.semanticdone && !fd.errors) 357 { 358 /* https://issues.dlang.org/show_bug.cgi?id=21614 359 * 360 * Template instances may import modules that have not 361 * finished semantic1. 362 */ 363 fd.dsymbolSemantic(sc); 364 } 365 assert(fd.semanticRun <= PASS.semantic2); 366 fd.semanticRun = PASS.semantic2; 367 368 //printf("FuncDeclaration::semantic2 [%s] fd0 = %s %s\n", loc.toChars(), toChars(), type.toChars()); 369 370 // Only check valid functions which have a body to avoid errors 371 // for multiple declarations, e.g. 372 // void foo(); 373 // void foo(); 374 if (fd.fbody && fd.overnext && !fd.errors) 375 { 376 // Always starts the lookup from 'this', because the conflicts with 377 // previous overloads are already reported. 378 alias f1 = fd; 379 auto tf1 = cast(TypeFunction) f1.type; 380 auto parent1 = f1.toParent2(); 381 382 overloadApply(f1, (Dsymbol s) 383 { 384 auto f2 = s.isFuncDeclaration(); 385 if (!f2 || f1 == f2 || f2.errors) 386 return 0; 387 388 // Don't have to check conflict between declaration and definition. 389 if (f2.fbody is null) 390 return 0; 391 392 // Functions with different manglings can never conflict 393 if (f1.linkage != f2.linkage) 394 return 0; 395 396 // Functions with different names never conflict 397 // (they can form overloads sets introduced by an alias) 398 if (f1.ident != f2.ident) 399 return 0; 400 401 // Functions with different parents never conflict 402 // (E.g. when aliasing a free function into a struct) 403 if (parent1 != f2.toParent2()) 404 return 0; 405 406 /* Check for overload merging with base class member functions. 407 * 408 * class B { void foo() {} } 409 * class D : B { 410 * override void foo() {} // B.foo appears as f2 411 * alias foo = B.foo; 412 * } 413 */ 414 if (f1.overrides(f2)) 415 return 0; 416 417 auto tf2 = cast(TypeFunction) f2.type; 418 419 // Overloading based on storage classes 420 if (tf1.mod != tf2.mod || ((f1.storage_class ^ f2.storage_class) & STC.static_)) 421 return 0; 422 423 const sameAttr = tf1.attributesEqual(tf2); 424 const sameParams = tf1.parameterList == tf2.parameterList; 425 426 // Allow the hack to declare overloads with different parameters/STC's 427 // @@@DEPRECATED_2.094@@@ 428 // Deprecated in 2020-08, make this an error in 2.104 429 if (parent1.isModule() && 430 f1.linkage != LINK.d && f1.linkage != LINK.cpp && 431 (!sameAttr || !sameParams) 432 ) 433 { 434 f2.deprecation("cannot overload `extern(%s)` function at %s", 435 linkageToChars(f1.linkage), 436 f1.loc.toChars()); 437 return 0; 438 } 439 440 // Different parameters don't conflict in extern(C++/D) 441 if (!sameParams) 442 return 0; 443 444 // Different attributes don't conflict in extern(D) 445 if (!sameAttr && f1.linkage == LINK.d) 446 return 0; 447 448 error(f2.loc, "%s `%s%s` conflicts with previous declaration at %s", 449 f2.kind(), 450 f2.toPrettyChars(), 451 parametersTypeToChars(tf2.parameterList), 452 f1.loc.toChars()); 453 f2.type = Type.terror; 454 f2.errors = true; 455 return 0; 456 }); 457 } 458 if (!fd.type || fd.type.ty != Tfunction) 459 return; 460 TypeFunction f = cast(TypeFunction) fd.type; 461 462 UserAttributeDeclaration.checkGNUABITag(fd, fd.linkage); 463 //semantic for parameters' UDAs 464 foreach (i, param; f.parameterList) 465 { 466 if (param && param.userAttribDecl) 467 param.userAttribDecl.semantic2(sc); 468 } 469 } 470 471 override void visit(Import i) 472 { 473 //printf("Import::semantic2('%s')\n", toChars()); 474 if (i.mod) 475 { 476 i.mod.semantic2(null); 477 if (i.mod.needmoduleinfo) 478 { 479 //printf("module5 %s because of %s\n", sc.module.toChars(), mod.toChars()); 480 if (sc) 481 sc._module.needmoduleinfo = 1; 482 } 483 } 484 } 485 486 override void visit(Nspace ns) 487 { 488 if (ns.semanticRun >= PASS.semantic2) 489 return; 490 ns.semanticRun = PASS.semantic2; 491 static if (LOG) 492 { 493 printf("+Nspace::semantic2('%s')\n", ns.toChars()); 494 } 495 UserAttributeDeclaration.checkGNUABITag(ns, LINK.cpp); 496 if (ns.members) 497 { 498 assert(sc); 499 sc = sc.push(ns); 500 sc.linkage = LINK.cpp; 501 foreach (s; *ns.members) 502 { 503 static if (LOG) 504 { 505 printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); 506 } 507 s.semantic2(sc); 508 } 509 sc.pop(); 510 } 511 static if (LOG) 512 { 513 printf("-Nspace::semantic2('%s')\n", ns.toChars()); 514 } 515 } 516 517 override void visit(AttribDeclaration ad) 518 { 519 Dsymbols* d = ad.include(sc); 520 if (d) 521 { 522 Scope* sc2 = ad.newScope(sc); 523 for (size_t i = 0; i < d.dim; i++) 524 { 525 Dsymbol s = (*d)[i]; 526 s.semantic2(sc2); 527 } 528 if (sc2 != sc) 529 sc2.pop(); 530 } 531 } 532 533 /** 534 * Run the DeprecatedDeclaration's semantic2 phase then its members. 535 * 536 * The message set via a `DeprecatedDeclaration` can be either of: 537 * - a string literal 538 * - an enum 539 * - a static immutable 540 * So we need to call ctfe to resolve it. 541 * Afterward forwards to the members' semantic2. 542 */ 543 override void visit(DeprecatedDeclaration dd) 544 { 545 getMessage(dd); 546 visit(cast(AttribDeclaration)dd); 547 } 548 549 override void visit(AlignDeclaration ad) 550 { 551 ad.getAlignment(sc); 552 visit(cast(AttribDeclaration)ad); 553 } 554 555 override void visit(CPPNamespaceDeclaration decl) 556 { 557 UserAttributeDeclaration.checkGNUABITag(decl, LINK.cpp); 558 visit(cast(AttribDeclaration)decl); 559 } 560 561 override void visit(UserAttributeDeclaration uad) 562 { 563 if (uad.decl && uad.atts && uad.atts.dim && uad._scope) 564 { 565 Expression* lastTag; 566 static void eval(Scope* sc, Expressions* exps, ref Expression* lastTag) 567 { 568 foreach (ref Expression e; *exps) 569 { 570 if (e) 571 { 572 e = e.expressionSemantic(sc); 573 if (definitelyValueParameter(e)) 574 e = e.ctfeInterpret(); 575 if (e.op == TOK.tuple) 576 { 577 TupleExp te = cast(TupleExp)e; 578 eval(sc, te.exps, lastTag); 579 } 580 581 // Handles compiler-recognized `core.attribute.gnuAbiTag` 582 if (UserAttributeDeclaration.isGNUABITag(e)) 583 doGNUABITagSemantic(e, lastTag); 584 } 585 } 586 } 587 588 uad._scope = null; 589 eval(sc, uad.atts, lastTag); 590 } 591 visit(cast(AttribDeclaration)uad); 592 } 593 594 override void visit(AggregateDeclaration ad) 595 { 596 //printf("AggregateDeclaration::semantic2(%s) type = %s, errors = %d\n", ad.toChars(), ad.type.toChars(), ad.errors); 597 if (!ad.members) 598 return; 599 600 if (ad._scope) 601 { 602 ad.error("has forward references"); 603 return; 604 } 605 606 UserAttributeDeclaration.checkGNUABITag( 607 ad, ad.classKind == ClassKind.cpp ? LINK.cpp : LINK.d); 608 609 auto sc2 = ad.newScope(sc); 610 611 ad.determineSize(ad.loc); 612 613 for (size_t i = 0; i < ad.members.dim; i++) 614 { 615 Dsymbol s = (*ad.members)[i]; 616 //printf("\t[%d] %s\n", i, s.toChars()); 617 s.semantic2(sc2); 618 } 619 620 sc2.pop(); 621 } 622 623 override void visit(ClassDeclaration cd) 624 { 625 /// Checks that the given class implements all methods of its interfaces. 626 static void checkInterfaceImplementations(ClassDeclaration cd) 627 { 628 foreach (base; cd.interfaces) 629 { 630 // first entry is ClassInfo reference 631 auto methods = base.sym.vtbl[base.sym.vtblOffset .. $]; 632 633 foreach (m; methods) 634 { 635 auto ifd = m.isFuncDeclaration; 636 assert(ifd); 637 638 if (ifd.objc.isOptional) 639 continue; 640 641 auto type = ifd.type.toTypeFunction(); 642 auto fd = cd.findFunc(ifd.ident, type); 643 644 if (fd && !fd.isAbstract) 645 { 646 //printf(" found\n"); 647 // Check that calling conventions match 648 if (fd.linkage != ifd.linkage) 649 fd.error("linkage doesn't match interface function"); 650 651 // Check that it is current 652 //printf("newinstance = %d fd.toParent() = %s ifd.toParent() = %s\n", 653 //newinstance, fd.toParent().toChars(), ifd.toParent().toChars()); 654 if (fd.toParent() != cd && ifd.toParent() == base.sym) 655 cd.error("interface function `%s` is not implemented", ifd.toFullSignature()); 656 } 657 658 else 659 { 660 //printf(" not found %p\n", fd); 661 // BUG: should mark this class as abstract? 662 if (!cd.isAbstract()) 663 cd.error("interface function `%s` is not implemented", ifd.toFullSignature()); 664 } 665 } 666 } 667 } 668 669 if (cd.semanticRun >= PASS.semantic2done) 670 return; 671 assert(cd.semanticRun <= PASS.semantic2); 672 cd.semanticRun = PASS.semantic2; 673 674 checkInterfaceImplementations(cd); 675 visit(cast(AggregateDeclaration) cd); 676 } 677 678 override void visit(InterfaceDeclaration cd) 679 { 680 visit(cast(AggregateDeclaration) cd); 681 } 682 } 683 684 /** 685 * Perform semantic analysis specific to the GNU ABI tags 686 * 687 * The GNU ABI tags are a feature introduced in C++11, specific to g++ 688 * and the Itanium ABI. 689 * They are mandatory for C++ interfacing, simply because the templated struct 690 *`std::basic_string`, of which the ubiquitous `std::string` is a instantiation 691 * of, uses them. 692 * 693 * Params: 694 * e = Expression to perform semantic on 695 * See `Semantic2Visitor.visit(UserAttributeDeclaration)` 696 * lastTag = When `!is null`, we already saw an ABI tag. 697 * To simplify implementation and reflection code, 698 * only one ABI tag object is allowed per symbol 699 * (but it can have multiple tags as it's an array exp). 700 */ 701 private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag) 702 { 703 import dmd.dmangle; 704 705 // When `@gnuAbiTag` is used, the type will be the UDA, not the struct literal 706 if (e.op == TOK.type) 707 { 708 e.error("`@%s` at least one argument expected", Id.udaGNUAbiTag.toChars()); 709 return; 710 } 711 712 // Definition is in `core.attributes`. If it's not a struct literal, 713 // it shouldn't have passed semantic, hence the `assert`. 714 auto sle = e.isStructLiteralExp(); 715 if (sle is null) 716 { 717 assert(global.errors); 718 return; 719 } 720 // The definition of `gnuAttributes` only have 1 member, `string[] tags` 721 assert(sle.elements && sle.elements.length == 1); 722 // `gnuAbiTag`'s constructor is defined as `this(string[] tags...)` 723 auto ale = (*sle.elements)[0].isArrayLiteralExp(); 724 if (ale is null) 725 { 726 e.error("`@%s` at least one argument expected", Id.udaGNUAbiTag.toChars()); 727 return; 728 } 729 730 // Check that it's the only tag on the symbol 731 if (lastTag !is null) 732 { 733 const str1 = (*lastTag.isStructLiteralExp().elements)[0].toString(); 734 const str2 = ale.toString(); 735 e.error("only one `@%s` allowed per symbol", Id.udaGNUAbiTag.toChars()); 736 e.errorSupplemental("instead of `@%s @%s`, use `@%s(%.*s, %.*s)`", 737 lastTag.toChars(), e.toChars(), Id.udaGNUAbiTag.toChars(), 738 // Avoid [ ... ] 739 cast(int)str1.length - 2, str1.ptr + 1, 740 cast(int)str2.length - 2, str2.ptr + 1); 741 return; 742 } 743 lastTag = &e; 744 745 // We already know we have a valid array literal of strings. 746 // Now checks that elements are valid. 747 foreach (idx, elem; *ale.elements) 748 { 749 const str = elem.toStringExp().peekString(); 750 if (!str.length) 751 { 752 e.error("argument `%d` to `@%s` cannot be %s", cast(int)(idx + 1), 753 Id.udaGNUAbiTag.toChars(), 754 elem.isNullExp() ? "`null`".ptr : "empty".ptr); 755 continue; 756 } 757 758 foreach (c; str) 759 { 760 if (!c.isValidMangling()) 761 { 762 e.error("`@%s` char `0x%02x` not allowed in mangling", 763 Id.udaGNUAbiTag.toChars(), c); 764 break; 765 } 766 } 767 // Valid element 768 } 769 // Since ABI tags need to be sorted, we sort them in place 770 // It might be surprising for users that inspects the UDAs, 771 // but it's a concession to practicality. 772 // Casts are unfortunately necessary as `implicitConvTo` is not 773 // `const` (and nor is `StringExp`, by extension). 774 static int predicate(const scope Expression* e1, const scope Expression* e2) nothrow 775 { 776 scope(failure) assert(0, "An exception was thrown"); 777 return (cast(Expression*)e1).toStringExp().compare((cast(Expression*)e2).toStringExp()); 778 } 779 ale.elements.sort!predicate; 780 }