1 /** 2 * "new" C++ name mangling scheme 3 * 4 * Compiler implementation of the 5 * $(LINK2 https://www.dlang.org, D programming language). 6 * 7 * Copyright: Copyright (C) 1992-1998 by Symantec 8 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 9 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 10 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/newman.c, backend/newman.c) 12 */ 13 14 module dmd.backend.newman; 15 16 version (SCPP) 17 { 18 version = COMPILE; 19 version = SCPPorMARS; 20 version = SCPPorHTOD; 21 } 22 version (HTOD) 23 { 24 version = COMPILE; 25 version = SCPPorMARS; 26 version = SCPPorHTOD; 27 } 28 version (MARS) 29 { 30 version = COMPILE; 31 version = SCPPorMARS; 32 } 33 34 version (COMPILE) 35 { 36 37 import core.stdc.ctype; 38 import core.stdc.stdio; 39 import core.stdc.stdlib; 40 import core.stdc.string; 41 42 import dmd.backend.cc; 43 import dmd.backend.cdef; 44 import dmd.backend.code; 45 import dmd.backend.code_x86; 46 import dmd.backend.mem; 47 import dmd.backend.el; 48 import dmd.backend.exh; 49 import dmd.backend.global; 50 import dmd.backend.obj; 51 import dmd.backend.oper; 52 import dmd.backend.rtlsym; 53 import dmd.backend.ty; 54 import dmd.backend.type; 55 import dmd.backend.xmm; 56 57 version (SCPPorHTOD) 58 { 59 import cpp; 60 import dtoken; 61 import msgs2; 62 import parser; 63 import scopeh; 64 } 65 66 version (MARS) 67 struct token_t; 68 69 extern (C++): 70 71 nothrow: 72 73 bool NEWTEMPMANGLE() { return !(config.flags4 & CFG4oldtmangle); } // do new template mangling 74 75 enum BUFIDMAX = 2 * IDMAX; 76 77 struct Mangle 78 { 79 char[BUFIDMAX + 2] buf; 80 81 char *np; // index into buf[] 82 83 // Used for compression of redundant znames 84 const(char)*[10] zname; 85 int znamei; 86 87 type*[10] arg; // argument_replicator 88 int argi; // number used in arg[] 89 } 90 91 private __gshared 92 { 93 Mangle mangle; 94 95 int mangle_inuse; 96 } 97 98 struct MangleInuse 99 { 100 static if (0) 101 { 102 this(int i) 103 { 104 assert(mangle_inuse == 0); 105 mangle_inuse++; 106 } 107 108 ~this() 109 { 110 assert(mangle_inuse == 1); 111 mangle_inuse--; 112 } 113 } 114 } 115 116 /* Names for special variables */ 117 __gshared 118 { 119 char[3] cpp_name_new = "?2"; 120 char[3] cpp_name_delete = "?3"; 121 char[4] cpp_name_anew = "?_P"; 122 char[4] cpp_name_adelete = "?_Q"; 123 char[3] cpp_name_ct = "?0"; 124 char[3] cpp_name_dt = "?1"; 125 char[3] cpp_name_as = "?4"; 126 char[4] cpp_name_vc = "?_H"; 127 char[4] cpp_name_primdt = "?_D"; 128 char[4] cpp_name_scaldeldt = "?_G"; 129 char[4] cpp_name_priminv = "?_R"; 130 } 131 132 133 /**************************** 134 */ 135 136 version (MARS) 137 { 138 struct OPTABLE 139 { 140 ubyte tokn; 141 ubyte oper; 142 const(char)* string; 143 const(char)* pretty; 144 } 145 } 146 147 version (SCPPorHTOD) 148 { 149 __gshared OPTABLE[57] oparray = [ 150 { TKnew, OPnew, cpp_name_new.ptr, "new" }, 151 { TKdelete, OPdelete, cpp_name_delete.ptr,"del" }, 152 { TKadd, OPadd, "?H", "+" }, 153 { TKadd, OPuadd, "?H", "+" }, 154 { TKmin, OPmin, "?G", "-" }, 155 { TKmin, OPneg, "?G", "-" }, 156 { TKstar, OPmul, "?D", "*" }, 157 { TKstar, OPind, "?D", "*" }, 158 { TKdiv, OPdiv, "?K", "/" }, 159 { TKmod, OPmod, "?L", "%" }, 160 { TKxor, OPxor, "?T", "^" }, 161 { TKand, OPand, "?I", "&" }, 162 { TKand, OPaddr, "?I", "&" }, 163 { TKor, OPor, "?U", "|" }, 164 { TKcom, OPcom, "?S", "~" }, 165 { TKnot, OPnot, "?7", "!" }, 166 { TKeq, OPeq, cpp_name_as.ptr, "=" }, 167 { TKeq, OPstreq, "?4", "=" }, 168 { TKlt, OPlt, "?M", "<" }, 169 { TKgt, OPgt, "?O", ">" }, 170 { TKnew, OPanew, cpp_name_anew.ptr, "n[]" }, 171 { TKdelete, OPadelete, cpp_name_adelete.ptr,"d[]" }, 172 { TKunord, OPunord, "?_S", "!<>=" }, 173 { TKlg, OPlg, "?_T", "<>" }, 174 { TKleg, OPleg, "?_U", "<>=" }, 175 { TKule, OPule, "?_V", "!>" }, 176 { TKul, OPul, "?_W", "!>=" }, 177 { TKuge, OPuge, "?_X", "!<" }, 178 { TKug, OPug, "?_Y", "!<=" }, 179 { TKue, OPue, "?_Z", "!<>" }, 180 { TKaddass, OPaddass, "?Y", "+=" }, 181 { TKminass, OPminass, "?Z", "-=" }, 182 { TKmulass, OPmulass, "?X", "*=" }, 183 { TKdivass, OPdivass, "?_0", "/=" }, 184 { TKmodass, OPmodass, "?_1", "%=" }, 185 { TKxorass, OPxorass, "?_6", "^=" }, 186 { TKandass, OPandass, "?_4", "&=" }, 187 { TKorass, OPorass, "?_5", "|=" }, 188 { TKshl, OPshl, "?6", "<<" }, 189 { TKshr, OPshr, "?5", ">>" }, 190 { TKshrass, OPshrass, "?_2", ">>=" }, 191 { TKshlass, OPshlass, "?_3", "<<=" }, 192 { TKeqeq, OPeqeq, "?8", "==" }, 193 { TKne, OPne, "?9", "!=" }, 194 { TKle, OPle, "?N", "<=" }, 195 { TKge, OPge, "?P", ">=" }, 196 { TKandand, OPandand, "?V", "&&" }, 197 { TKoror, OPoror, "?W", "||" }, 198 { TKplpl, OPpostinc, "?E", "++" }, 199 { TKplpl, OPpreinc, "?E", "++" }, 200 { TKmimi, OPpostdec, "?F", "--" }, 201 { TKmimi, OPpredec, "?F", "--" }, 202 { TKlpar, OPcall, "?R", "()" }, 203 { TKlbra, OPbrack, "?A", "[]" }, 204 { TKarrow, OParrow, "?C", "->" }, 205 { TKcomma, OPcomma, "?Q", "," }, 206 { TKarrowstar, OParrowstar, "?J", "->*" }, 207 ]; 208 } 209 210 /**************************************** 211 * Convert from identifier to operator 212 */ 213 version (SCPPorHTOD) 214 { 215 216 static if (0) //__GNUC__ // NOT DONE - FIX 217 { 218 char * unmangle_pt(const(char)** s) 219 { 220 return cast(char *)*s; 221 } 222 } 223 else 224 { 225 extern (C) char *unmangle_pt(const(char)**); 226 } 227 228 char *cpp_unmangleident(const(char)* p) 229 { 230 MangleInuse m; 231 232 //printf("cpp_unmangleident('%s')\n", p); 233 if (*p == '$') // if template name 234 { 235 L1: 236 const(char)* q = p; 237 char* s = unmangle_pt(&q); 238 if (s) 239 { if (strlen(s) <= BUFIDMAX) 240 p = strcpy(mangle.buf.ptr, s); 241 free(s); 242 } 243 } 244 else if (*p == '?') // if operator name 245 { int i; 246 247 if (NEWTEMPMANGLE && p[1] == '$') // if template name 248 goto L1; 249 for (i = 0; i < oparray.length; i++) 250 { if (strcmp(p,oparray[i].string) == 0) 251 { const(char)* s; 252 253 strcpy(mangle.buf.ptr, "operator "); 254 switch (oparray[i].oper) 255 { case OPanew: 256 s = "new[]"; 257 break; 258 case OPadelete: 259 s = "delete[]"; 260 break; 261 case OPdelete: 262 s = "delete"; 263 break; 264 default: 265 s = oparray[i].pretty.ptr; 266 break; 267 } 268 strcat(mangle.buf.ptr,s); 269 p = mangle.buf.ptr; 270 break; 271 } 272 } 273 } 274 //printf("-cpp_unmangleident() = '%s'\n", p); 275 return cast(char *)p; 276 } 277 } 278 279 /**************************************** 280 * Find index in oparray[] for operator. 281 * Returns: 282 * index or -1 if not found 283 */ 284 285 version (SCPPorHTOD) 286 { 287 288 int cpp_opidx(int op) 289 { int i; 290 291 for (i = 0; i < oparray.length; i++) 292 if (oparray[i].oper == op) 293 return i; 294 return -1; 295 } 296 297 } 298 299 /*************************************** 300 * Find identifier string associated with operator. 301 * Returns: 302 * null if not found 303 */ 304 305 version (SCPPorHTOD) 306 { 307 308 char *cpp_opident(int op) 309 { int i; 310 311 i = cpp_opidx(op); 312 return (i == -1) ? null : cast(char*)oparray[i].string; 313 } 314 315 } 316 317 /********************************** 318 * Convert from operator token to name. 319 * Output: 320 * *poper OPxxxx 321 * *pt set to type for user defined conversion 322 * Returns: 323 * pointer to corresponding name 324 */ 325 326 version (SCPPorHTOD) 327 { 328 329 char *cpp_operator(int *poper,type **pt) 330 { 331 int i; 332 type *typ_spec; 333 char *s; 334 335 *pt = null; 336 stoken(); /* skip over operator keyword */ 337 for (i = 0; i < oparray.length; i++) 338 { if (oparray[i].tokn == tok.TKval) 339 goto L1; 340 } 341 342 /* Look for type conversion */ 343 if (type_specifier(&typ_spec)) 344 { type *t; 345 346 t = ptr_operator(typ_spec); // parse ptr-operator 347 fixdeclar(t); 348 type_free(typ_spec); 349 *pt = t; 350 return cpp_typetostring(t,cast(char*)"?B".ptr); 351 } 352 353 cpperr(EM_not_overloadable); // that token cannot be overloaded 354 s = cast(char*)"_".ptr; 355 goto L2; 356 357 L1: 358 s = cast(char*)oparray[i].string; 359 *poper = oparray[i].oper; 360 switch (*poper) 361 { case OPcall: 362 if (stoken() != TKrpar) 363 synerr(EM_rpar); /* ')' expected */ 364 break; 365 366 case OPbrack: 367 if (stoken() != TKrbra) 368 synerr(EM_rbra); /* ']' expected */ 369 break; 370 371 case OPnew: 372 if (stoken() != TKlbra) 373 goto Lret; 374 *poper = OPanew; // operator new[] 375 s = cpp_name_anew.ptr; 376 goto L3; 377 378 case OPdelete: 379 if (stoken() != TKlbra) 380 goto Lret; 381 *poper = OPadelete; // operator delete[] 382 s = cpp_name_adelete.ptr; 383 L3: 384 if (stoken() != TKrbra) 385 synerr(EM_rbra); // ']' expected 386 if (!(config.flags4 & CFG4anew)) 387 { cpperr(EM_enable_anew); // throw -Aa to support this 388 config.flags4 |= CFG4anew; 389 } 390 break; 391 392 default: 393 break; 394 } 395 L2: 396 stoken(); 397 Lret: 398 return s; 399 } 400 401 /****************************************** 402 * Alternate version that works on a list of token's. 403 * Input: 404 * to list of tokens 405 * Output: 406 * *pcastoverload 1 if user defined type conversion 407 */ 408 409 char *cpp_operator2(token_t *to, int *pcastoverload) 410 { 411 int i; 412 char *s; 413 token_t *tn; 414 int oper; 415 416 *pcastoverload = 0; 417 if (!to || !to.TKnext) 418 return null; 419 420 for (i = 0; i < oparray.length; i++) 421 { 422 //printf("[%d] %d, %d\n", i, oparray[i].tokn, tok.TKval); 423 if (oparray[i].tokn == to.TKval) 424 goto L1; 425 } 426 427 //printf("cpp_operator2(): castoverload\n"); 428 *pcastoverload = 1; 429 return null; 430 431 L1: 432 tn = to.TKnext; 433 s = cast(char*)oparray[i].string; 434 oper = oparray[i].oper; 435 switch (oper) 436 { case OPcall: 437 if (tn.TKval != TKrpar) 438 synerr(EM_rpar); // ')' expected 439 break; 440 441 case OPbrack: 442 if (tn.TKval != TKrbra) 443 synerr(EM_rbra); // ']' expected 444 break; 445 446 case OPnew: 447 if (tn.TKval != TKlbra) 448 break; 449 oper = OPanew; // operator new[] 450 s = cpp_name_anew.ptr; 451 goto L3; 452 453 case OPdelete: 454 if (tn.TKval != TKlbra) 455 break; 456 oper = OPadelete; // operator delete[] 457 s = cpp_name_adelete.ptr; 458 L3: 459 if (tn.TKval != TKrbra) 460 synerr(EM_rbra); // ']' expected 461 if (!(config.flags4 & CFG4anew)) 462 { cpperr(EM_enable_anew); // throw -Aa to support this 463 config.flags4 |= CFG4anew; 464 } 465 break; 466 467 default: 468 break; 469 } 470 return s; 471 } 472 473 } 474 475 /*********************************** 476 * Generate and return a pointer to a string constructed from 477 * the type, appended to the prefix. 478 * Since these generated strings determine the uniqueness of names, 479 * they are also used to determine if two types are the same. 480 * Returns: 481 * pointer to static name[] 482 */ 483 484 char *cpp_typetostring(type *t,char *prefix) 485 { int i; 486 487 if (prefix) 488 { strcpy(mangle.buf.ptr,prefix); 489 i = cast(int)strlen(prefix); 490 } 491 else 492 i = 0; 493 //dbg_printf("cpp_typetostring:\n"); 494 //type_print(t); 495 MangleInuse m; 496 mangle.znamei = 0; 497 mangle.argi = 0; 498 mangle.np = mangle.buf.ptr + i; 499 mangle.buf[BUFIDMAX + 1] = 0x55; 500 cpp_data_type(t); 501 *mangle.np = 0; // 0-terminate mangle.buf[] 502 //dbg_printf("cpp_typetostring: '%s'\n", mangle.buf); 503 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 504 assert(mangle.buf[BUFIDMAX + 1] == 0x55); 505 return mangle.buf.ptr; 506 } 507 508 version (MARS) { } else 509 { 510 511 /******************************** 512 * 'Mangle' a name for output. 513 * Returns: 514 * pointer to mangled name (a static buffer) 515 */ 516 517 char *cpp_mangle(Symbol *s) 518 { 519 symbol_debug(s); 520 //printf("cpp_mangle(s = %p, '%s')\n", s, s.Sident); 521 //type_print(s.Stype); 522 523 version (SCPPorHTOD) 524 { 525 if (!CPP) 526 return symbol_ident(s); 527 } 528 529 if (type_mangle(s.Stype) != mTYman_cpp) 530 return symbol_ident(s); 531 else 532 { 533 MangleInuse m; 534 535 mangle.znamei = 0; 536 mangle.argi = 0; 537 mangle.np = mangle.buf.ptr; 538 mangle.buf[BUFIDMAX + 1] = 0x55; 539 cpp_decorated_name(s); 540 *mangle.np = 0; // 0-terminate cpp_name[] 541 //dbg_printf("cpp_mangle() = '%s'\n", mangle.buf); 542 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 543 assert(mangle.buf[BUFIDMAX + 1] == 0x55); 544 return mangle.buf.ptr; 545 } 546 } 547 548 } 549 /////////////////////////////////////////////////////// 550 551 /********************************* 552 * Add char into cpp_name[]. 553 */ 554 555 private void CHAR(int c) 556 { 557 if (mangle.np < &mangle.buf[BUFIDMAX]) 558 *mangle.np++ = cast(char)c; 559 } 560 561 /********************************* 562 * Add char into cpp_name[]. 563 */ 564 565 private void STR(const(char)* p) 566 { 567 size_t len; 568 569 len = strlen(p); 570 if (mangle.np + len <= &mangle.buf[BUFIDMAX]) 571 { memcpy(mangle.np,p,len); 572 mangle.np += len; 573 } 574 else 575 for (; *p; p++) 576 CHAR(*p); 577 } 578 579 /*********************************** 580 * Convert const volatile combinations into 0..3 581 */ 582 583 private int cpp_cvidx(tym_t ty) 584 { int i; 585 586 i = (ty & mTYconst) ? 1 : 0; 587 i |= (ty & mTYvolatile) ? 2 : 0; 588 return i; 589 } 590 591 /****************************** 592 * Turn visibility into 0..2 593 */ 594 595 private int cpp_protection(Symbol *s) 596 { int i; 597 598 switch (s.Sflags & SFLpmask) 599 { case SFLprivate: i = 0; break; 600 case SFLprotected: i = 1; break; 601 case SFLpublic: i = 2; break; 602 default: 603 symbol_print(s); 604 assert(0); 605 } 606 return i; 607 } 608 609 /*********************************** 610 * Create mangled name for template instantiation. 611 */ 612 613 version (SCPPorHTOD) 614 { 615 616 char *template_mangle(Symbol *s,param_t *arglist) 617 { 618 /* mangling ::= '$' template_name { type | expr } 619 type ::= "T" mangled type 620 expr ::= integer | string | address | float | double | long_double 621 integer ::= "I" dimension 622 string ::= "S" string 623 address ::= "R" zname 624 float ::= "F" hex_digits 625 double ::= "D" hex_digits 626 long_double ::= "L" hex_digits 627 */ 628 param_t *p; 629 630 assert(s); 631 symbol_debug(s); 632 //assert(s.Sclass == SCtemplate); 633 634 //printf("\ntemplate_mangle(s = '%s', arglist = %p)\n", s.Sident, arglist); 635 //arglist.print_list(); 636 637 MangleInuse m; 638 mangle.znamei = 0; 639 mangle.argi = 0; 640 mangle.np = mangle.buf.ptr; 641 mangle.buf[BUFIDMAX + 1] = 0x55; 642 643 if (NEWTEMPMANGLE) 644 STR("?$"); 645 else 646 CHAR('$'); 647 648 // BUG: this is for templates nested inside class scopes. 649 // Need to check if it creates names that are properly unmanglable. 650 cpp_zname(s.Sident.ptr); 651 if (s.Sscope) 652 cpp_scope(s.Sscope); 653 654 for (p = arglist; p; p = p.Pnext) 655 { 656 if (p.Ptype) 657 { /* Argument is a type */ 658 if (!NEWTEMPMANGLE) 659 CHAR('T'); 660 cpp_argument_list(p.Ptype, 1); 661 } 662 else if (p.Psym) 663 { 664 CHAR('V'); // this is a 'class' name, but it should be a 'template' name 665 cpp_ecsu_name(p.Psym); 666 } 667 else 668 { /* Argument is an expression */ 669 elem *e = p.Pelem; 670 tym_t ty = tybasic(e.ET.Tty); 671 char *p2; 672 char[2] a = void; 673 int ni; 674 char c; 675 676 L2: 677 switch (e.Eoper) 678 { case OPconst: 679 switch (ty) 680 { case TYfloat: ni = FLOATSIZE; c = 'F'; goto L1; 681 case TYdouble_alias: 682 case TYdouble: ni = DOUBLESIZE; c = 'D'; goto L1; 683 case TYldouble: ni = tysize(TYldouble); c = 'L'; goto L1; 684 L1: 685 if (NEWTEMPMANGLE) 686 CHAR('$'); 687 CHAR(c); 688 p2 = cast(char *)&e.EV.Vdouble; 689 while (ni--) 690 { char ch; 691 static immutable char[16] hex = "0123456789ABCDEF"; 692 693 ch = *p2++; 694 CHAR(hex[ch & 15]); 695 CHAR(hex[(ch >> 4) & 15]); 696 } 697 break; 698 default: 699 debug 700 { 701 if (!tyintegral(ty) && !tymptr(ty)) 702 elem_print(e); 703 } 704 assert(tyintegral(ty) || tymptr(ty)); 705 if (NEWTEMPMANGLE) 706 STR("$0"); 707 else 708 CHAR('I'); 709 cpp_dimension(el_tolongt(e)); 710 break; 711 } 712 break; 713 case OPstring: 714 if (NEWTEMPMANGLE) 715 STR("$S"); 716 else 717 CHAR('S'); 718 if (e.EV.Voffset) 719 synerr(EM_const_init); // constant initializer expected 720 cpp_string(e.EV.Vstring,e.EV.Vstrlen); 721 break; 722 case OPrelconst: 723 if (e.EV.Voffset) 724 synerr(EM_const_init); // constant initializer expected 725 s = e.EV.Vsym; 726 if (NEWTEMPMANGLE) 727 { STR("$1"); 728 cpp_decorated_name(s); 729 } 730 else 731 { CHAR('R'); 732 cpp_zname(s.Sident.ptr); 733 } 734 break; 735 case OPvar: 736 if (e.EV.Vsym.Sflags & SFLvalue && 737 tybasic(e.ET.Tty) != TYstruct) 738 { 739 e = e.EV.Vsym.Svalue; 740 goto L2; 741 } 742 else if (e.EV.Vsym.Sclass == SC.const_ /*&& 743 pstate.STintemplate*/) 744 { 745 CHAR('V'); // pretend to be a class name 746 cpp_zname(e.EV.Vsym.Sident.ptr); 747 break; 748 } 749 goto default; 750 751 default: 752 version (SCPPorHTOD) 753 { 754 debug 755 { 756 if (!errcnt) 757 elem_print(e); 758 } 759 synerr(EM_const_init); // constant initializer expected 760 assert(errcnt); 761 } 762 break; 763 } 764 } 765 } 766 *mangle.np = 0; 767 //printf("template_mangle() = '%s'\n", mangle.buf); 768 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 769 assert(mangle.buf[BUFIDMAX + 1] == 0x55); 770 return mangle.buf.ptr; 771 } 772 773 } 774 775 ////////////////////////////////////////////////////// 776 // Functions corresponding to the name mangling grammar in the 777 // "Microsoft Object Mapping Specification" 778 779 private void cpp_string(char *s,size_t len) 780 { char c; 781 782 for (; --len; s++) 783 { static immutable char[11] special_char = ",/\\:. \n\t'-"; 784 char *p; 785 786 c = *s; 787 if (c & 0x80 && isalpha(c & 0x7F)) 788 { CHAR('?'); 789 c &= 0x7F; 790 } 791 else if (isalnum(c)) 792 { } 793 else 794 { 795 CHAR('?'); 796 if ((p = cast(char *)strchr(special_char.ptr,c)) != null) 797 c = cast(char)('0' + (p - special_char.ptr)); 798 else 799 { 800 CHAR('$'); 801 CHAR('A' + ((c >> 4) & 0x0F)); 802 c = 'A' + (c & 0x0F); 803 } 804 } 805 CHAR(c); 806 } 807 CHAR('@'); 808 } 809 810 private void cpp_dimension(targ_ullong u) 811 { 812 if (u && u <= 10) 813 CHAR('0' + cast(char)u - 1); 814 else 815 { char[u.sizeof * 2 + 1] buffer = void; 816 char *p; 817 818 buffer[buffer.length - 1] = 0; 819 for (p = &buffer[buffer.length - 1]; u; u >>= 4) 820 { 821 *--p = 'A' + (u & 0x0F); 822 } 823 STR(p); 824 CHAR('@'); 825 } 826 } 827 828 static if (0) 829 { 830 private void cpp_dimension_ld(targ_ldouble ld) 831 { ubyte[targ_ldouble.sizeof] ldbuf = void; 832 833 memcpy(ldbuf.ptr,&ld,ld.sizeof); 834 if (u && u <= 10) 835 CHAR('0' + cast(char)u - 1); 836 else 837 { char[u.sizeof * 2 + 1] buffer = void; 838 char *p; 839 840 buffer[buffer.length - 1] = 0; 841 for (p = &buffer[buffer.length - 1]; u; u >>= 4) 842 { 843 *--p = 'A' + (u & 0x0F); 844 } 845 STR(p); 846 CHAR('@'); 847 } 848 } 849 } 850 851 private void cpp_enum_name(Symbol *s) 852 { type *t; 853 char c; 854 855 t = tstypes[TYint]; 856 switch (tybasic(t.Tty)) 857 { 858 case TYschar: c = '0'; break; 859 case TYuchar: c = '1'; break; 860 case TYshort: c = '2'; break; 861 case TYushort: c = '3'; break; 862 case TYint: c = '4'; break; 863 case TYuint: c = '5'; break; 864 case TYlong: c = '6'; break; 865 case TYulong: c = '7'; break; 866 default: assert(0); 867 } 868 CHAR(c); 869 cpp_ecsu_name(s); 870 } 871 872 private void cpp_reference_data_type(type *t, int flag) 873 { 874 if (tybasic(t.Tty) == TYarray) 875 { 876 int ndim; 877 type *tn; 878 int i; 879 880 CHAR('Y'); 881 882 // Compute number of dimensions (we have at least one) 883 ndim = 0; 884 tn = t; 885 do 886 { ndim++; 887 tn = tn.Tnext; 888 } while (tybasic(tn.Tty) == TYarray); 889 890 cpp_dimension(ndim); 891 for (; tybasic(t.Tty) == TYarray; t = t.Tnext) 892 { 893 if (t.Tflags & TFvla) 894 CHAR('X'); // DMC++ extension 895 else 896 cpp_dimension(t.Tdim); 897 } 898 899 // DMC++ extension 900 if (flag) // if template type argument 901 { 902 i = cpp_cvidx(t.Tty); 903 if (i) 904 { CHAR('_'); 905 //CHAR('X' + i - 1); // _X, _Y, _Z 906 CHAR('O' + i - 1); // _O, _P, _Q 907 } 908 } 909 910 cpp_basic_data_type(t); 911 } 912 else 913 cpp_basic_data_type(t); 914 } 915 916 private void cpp_pointer_data_type(type *t) 917 { 918 if (tybasic(t.Tty) == TYvoid) 919 CHAR('X'); 920 else 921 cpp_reference_data_type(t, 0); 922 } 923 924 private void cpp_ecsu_data_type(type *t) 925 { char c; 926 Symbol *stag; 927 int i; 928 929 type_debug(t); 930 switch (tybasic(t.Tty)) 931 { 932 case TYstruct: 933 stag = t.Ttag; 934 switch (stag.Sstruct.Sflags & (STRclass | STRunion)) 935 { case 0: c = 'U'; break; 936 case STRunion: c = 'T'; break; 937 case STRclass: c = 'V'; break; 938 default: 939 assert(0); 940 } 941 CHAR(c); 942 cpp_ecsu_name(stag); 943 break; 944 case TYenum: 945 CHAR('W'); 946 cpp_enum_name(t.Ttag); 947 break; 948 default: 949 debug 950 type_print(t); 951 952 assert(0); 953 } 954 } 955 956 private void cpp_basic_data_type(type *t) 957 { char c; 958 int i; 959 960 //printf("cpp_basic_data_type(t)\n"); 961 //type_print(t); 962 switch (tybasic(t.Tty)) 963 { 964 case TYschar: c = 'C'; goto dochar; 965 case TYchar: c = 'D'; goto dochar; 966 case TYuchar: c = 'E'; goto dochar; 967 case TYshort: c = 'F'; goto dochar; 968 case TYushort: c = 'G'; goto dochar; 969 case TYint: c = 'H'; goto dochar; 970 case TYuint: c = 'I'; goto dochar; 971 case TYlong: c = 'J'; goto dochar; 972 case TYulong: c = 'K'; goto dochar; 973 case TYfloat: c = 'M'; goto dochar; 974 case TYdouble: c = 'N'; goto dochar; 975 976 case TYdouble_alias: 977 if (_tysize[TYint] == 4) 978 { c = 'O'; 979 goto dochar; 980 } 981 c = 'Z'; 982 goto dochar2; 983 984 case TYldouble: 985 if (_tysize[TYint] == 2) 986 { c = 'O'; 987 goto dochar; 988 } 989 c = 'Z'; 990 goto dochar2; 991 dochar: 992 CHAR(c); 993 break; 994 995 case TYllong: c = 'J'; goto dochar2; 996 case TYullong: c = 'K'; goto dochar2; 997 case TYbool: c = 'N'; goto dochar2; // was 'X' prior to 8.1b8 998 case TYwchar_t: 999 if (config.flags4 & CFG4nowchar_t) 1000 { 1001 c = 'G'; 1002 goto dochar; // same as TYushort 1003 } 1004 else 1005 { 1006 pstate.STflags |= PFLmfc; 1007 c = 'Y'; 1008 goto dochar2; 1009 } 1010 1011 // Digital Mars extensions 1012 case TYifloat: c = 'R'; goto dochar2; 1013 case TYidouble: c = 'S'; goto dochar2; 1014 case TYildouble: c = 'T'; goto dochar2; 1015 case TYcfloat: c = 'U'; goto dochar2; 1016 case TYcdouble: c = 'V'; goto dochar2; 1017 case TYcldouble: c = 'W'; goto dochar2; 1018 1019 case TYchar16: c = 'X'; goto dochar2; 1020 case TYdchar: c = 'Y'; goto dochar2; 1021 case TYnullptr: c = 'Z'; goto dochar2; 1022 1023 dochar2: 1024 CHAR('_'); 1025 goto dochar; 1026 1027 case TYsptr: 1028 case TYcptr: 1029 case TYf16ptr: 1030 case TYfptr: 1031 case TYhptr: 1032 case TYvptr: 1033 case TYmemptr: 1034 case TYnptr: 1035 case TYimmutPtr: 1036 case TYsharePtr: 1037 case TYrestrictPtr: 1038 case TYfgPtr: 1039 c = cast(char)('P' + cpp_cvidx(t.Tty)); 1040 CHAR(c); 1041 if(I64) 1042 CHAR('E'); // __ptr64 modifier 1043 cpp_pointer_type(t); 1044 break; 1045 case TYstruct: 1046 case TYenum: 1047 cpp_ecsu_data_type(t); 1048 break; 1049 case TYarray: 1050 i = cpp_cvidx(t.Tty); 1051 i |= 1; // always const 1052 CHAR('P' + i); 1053 cpp_pointer_type(t); 1054 break; 1055 case TYvoid: 1056 c = 'X'; 1057 goto dochar; 1058 version (SCPPorHTOD) 1059 { 1060 case TYident: 1061 if (pstate.STintemplate) 1062 { 1063 CHAR('V'); // pretend to be a class name 1064 cpp_zname(t.Tident); 1065 } 1066 else 1067 { 1068 version (SCPPorHTOD) 1069 { 1070 cpperr(EM_no_type,t.Tident); // no type for argument 1071 } 1072 c = 'X'; 1073 goto dochar; 1074 } 1075 break; 1076 case TYtemplate: 1077 if (pstate.STintemplate) 1078 { 1079 CHAR('V'); // pretend to be a class name 1080 cpp_zname((cast(typetemp_t *)t).Tsym.Sident.ptr); 1081 } 1082 else 1083 goto Ldefault; 1084 break; 1085 } 1086 1087 default: 1088 Ldefault: 1089 if (tyfunc(t.Tty)) 1090 cpp_function_type(t); 1091 else 1092 { 1093 version (SCPPorHTOD) 1094 { 1095 debug 1096 if (!errcnt) 1097 type_print(t); 1098 assert(errcnt); 1099 } 1100 } 1101 } 1102 } 1103 1104 private void cpp_function_indirect_type(type *t) 1105 { int farfunc; 1106 1107 farfunc = tyfarfunc(t.Tnext.Tty) != 0; 1108 version (SCPPorHTOD) 1109 { 1110 if (tybasic(t.Tty) == TYmemptr) 1111 { 1112 CHAR('8' + farfunc); 1113 cpp_scope(t.Ttag); 1114 CHAR('@'); 1115 //cpp_this_type(t.Tnext,t.Ttag); // MSC doesn't do this 1116 } 1117 else 1118 CHAR('6' + farfunc); 1119 } 1120 else 1121 CHAR('6' + farfunc); 1122 } 1123 1124 private void cpp_data_indirect_type(type *t) 1125 { int i; 1126 version (SCPPorHTOD) 1127 { 1128 if (tybasic(t.Tty) == TYmemptr) // if pointer to member 1129 { 1130 i = cpp_cvidx(t.Tty); 1131 if (t.Tty & mTYfar) 1132 i += 4; 1133 CHAR('Q' + i); 1134 cpp_scope(t.Ttag); 1135 CHAR('@'); 1136 } 1137 else 1138 cpp_ecsu_data_indirect_type(t); 1139 } 1140 else 1141 { 1142 cpp_ecsu_data_indirect_type(t); 1143 } 1144 } 1145 1146 private void cpp_ecsu_data_indirect_type(type *t) 1147 { int i; 1148 tym_t ty; 1149 1150 i = 0; 1151 if (t.Tnext) 1152 { ty = t.Tnext.Tty & (mTYconst | mTYvolatile); 1153 switch (tybasic(t.Tty)) 1154 { 1155 case TYfptr: 1156 case TYvptr: 1157 case TYfref: 1158 ty |= mTYfar; 1159 break; 1160 1161 case TYhptr: 1162 i += 8; 1163 break; 1164 case TYref: 1165 case TYarray: 1166 if (LARGEDATA && !(ty & mTYLINK)) 1167 ty |= mTYfar; 1168 break; 1169 1170 default: 1171 break; 1172 } 1173 } 1174 else 1175 ty = t.Tty & (mTYLINK | mTYconst | mTYvolatile); 1176 i |= cpp_cvidx(ty); 1177 if (ty & (mTYcs | mTYfar)) 1178 i += 4; 1179 CHAR('A' + i); 1180 } 1181 1182 private void cpp_pointer_type(type *t) 1183 { tym_t ty; 1184 1185 if (tyfunc(t.Tnext.Tty)) 1186 { 1187 cpp_function_indirect_type(t); 1188 cpp_function_type(t.Tnext); 1189 } 1190 else 1191 { 1192 cpp_data_indirect_type(t); 1193 cpp_pointer_data_type(t.Tnext); 1194 } 1195 } 1196 1197 private void cpp_reference_type(type *t) 1198 { 1199 cpp_data_indirect_type(t); 1200 cpp_reference_data_type(t.Tnext, 0); 1201 } 1202 1203 private void cpp_primary_data_type(type *t) 1204 { 1205 if (tyref(t.Tty)) 1206 { 1207 static if (1) 1208 { 1209 // C++98 8.3.2 says cv-qualified references are ignored 1210 CHAR('A'); 1211 } 1212 else 1213 { 1214 switch (t.Tty & (mTYconst | mTYvolatile)) 1215 { 1216 case 0: CHAR('A'); break; 1217 case mTYvolatile: CHAR('B'); break; 1218 1219 // Digital Mars extensions 1220 case mTYconst | mTYvolatile: CHAR('_'); CHAR('L'); break; 1221 case mTYconst: CHAR('_'); CHAR('M'); break; 1222 1223 default: 1224 break; 1225 } 1226 } 1227 cpp_reference_type(t); 1228 } 1229 else 1230 cpp_basic_data_type(t); 1231 } 1232 1233 /***** 1234 * flag: 1 = template argument 1235 */ 1236 1237 private void cpp_argument_list(type *t, int flag) 1238 { int i; 1239 tym_t ty; 1240 1241 //printf("cpp_argument_list(flag = %d)\n", flag); 1242 // If a data type that encodes only into one character 1243 ty = tybasic(t.Tty); 1244 if (ty <= TYldouble && ty != TYenum 1245 && ty != TYbool // added for versions >= 8.1b9 1246 && !(t.Tty & (mTYconst | mTYvolatile)) 1247 ) 1248 { 1249 cpp_primary_data_type(t); 1250 } 1251 else 1252 { 1253 // See if a match with a previously used type 1254 for (i = 0; 1; i++) 1255 { 1256 if (i == mangle.argi) // no match 1257 { 1258 if (ty <= TYcldouble || ty == TYstruct) 1259 { 1260 int cvidx = cpp_cvidx(t.Tty); 1261 if (cvidx) 1262 { 1263 // Digital Mars extensions 1264 CHAR('_'); 1265 CHAR('N' + cvidx); // _O, _P, _Q prefix 1266 } 1267 } 1268 if (flag && tybasic(t.Tty) == TYarray) 1269 { 1270 cpp_reference_data_type(t, flag); 1271 } 1272 else 1273 cpp_primary_data_type(t); 1274 if (mangle.argi < 10) 1275 mangle.arg[mangle.argi++] = t; 1276 break; 1277 } 1278 if (typematch(t,mangle.arg[i],0)) 1279 { 1280 CHAR('0' + i); // argument_replicator 1281 break; 1282 } 1283 } 1284 } 1285 } 1286 1287 private void cpp_argument_types(type *t) 1288 { param_t *p; 1289 char c; 1290 1291 //printf("cpp_argument_types()\n"); 1292 //type_debug(t); 1293 for (p = t.Tparamtypes; p; p = p.Pnext) 1294 cpp_argument_list(p.Ptype, 0); 1295 if (t.Tflags & TFfixed) 1296 c = t.Tparamtypes ? '@' : 'X'; 1297 else 1298 c = 'Z'; 1299 CHAR(c); 1300 } 1301 1302 private void cpp_calling_convention(type *t) 1303 { char c; 1304 1305 switch (tybasic(t.Tty)) 1306 { 1307 case TYnfunc: 1308 case TYhfunc: 1309 case TYffunc: 1310 c = 'A'; break; 1311 case TYf16func: 1312 case TYfpfunc: 1313 case TYnpfunc: 1314 c = 'C'; break; 1315 case TYnsfunc: 1316 case TYfsfunc: 1317 c = 'G'; break; 1318 case TYjfunc: 1319 case TYmfunc: 1320 case TYnsysfunc: 1321 case TYfsysfunc: 1322 c = 'E'; break; 1323 case TYifunc: 1324 c = 'K'; break; 1325 default: 1326 assert(0); 1327 } 1328 CHAR(c); 1329 } 1330 1331 private void cpp_vcall_model_type() 1332 { 1333 } 1334 1335 version (SCPPorMARS) 1336 { 1337 1338 private void cpp_this_type(type *tfunc,Classsym *stag) 1339 { type *t; 1340 1341 type_debug(tfunc); 1342 symbol_debug(stag); 1343 1344 version (MARS) 1345 t = type_pointer(stag.Stype); 1346 else 1347 t = cpp_thistype(tfunc,stag); 1348 1349 //cpp_data_indirect_type(t); 1350 cpp_ecsu_data_indirect_type(t); 1351 type_free(t); 1352 } 1353 1354 } 1355 1356 private void cpp_storage_convention(Symbol *s) 1357 { tym_t ty; 1358 type *t = s.Stype; 1359 1360 ty = t.Tty; 1361 if (LARGEDATA && !(ty & mTYLINK)) 1362 t.Tty |= mTYfar; 1363 cpp_data_indirect_type(t); 1364 t.Tty = ty; 1365 } 1366 1367 private void cpp_data_type(type *t) 1368 { 1369 type_debug(t); 1370 switch (tybasic(t.Tty)) 1371 { case TYvoid: 1372 CHAR('X'); 1373 break; 1374 case TYstruct: 1375 case TYenum: 1376 CHAR('?'); 1377 cpp_ecsu_data_indirect_type(t); 1378 cpp_ecsu_data_type(t); 1379 break; 1380 default: 1381 cpp_primary_data_type(t); 1382 break; 1383 } 1384 } 1385 1386 private void cpp_return_type(Symbol *s) 1387 { 1388 if (s.Sfunc.Fflags & (Fctor | Fdtor)) // if ctor or dtor 1389 CHAR('@'); // no type 1390 else 1391 cpp_data_type(s.Stype.Tnext); 1392 } 1393 1394 private void cpp_ecsu_name(Symbol *s) 1395 { 1396 //printf("cpp_ecsu_name(%s)\n", symbol_ident(s)); 1397 cpp_zname(symbol_ident(s)); 1398 version (SCPPorMARS) 1399 { 1400 if (s.Sscope) 1401 cpp_scope(s.Sscope); 1402 } 1403 CHAR('@'); 1404 } 1405 1406 private void cpp_throw_types(type *t) 1407 { 1408 //cpp_argument_types(?); 1409 CHAR('Z'); 1410 } 1411 1412 private void cpp_function_type(type *t) 1413 { tym_t ty; 1414 type *tn; 1415 1416 //printf("cpp_function_type()\n"); 1417 //type_debug(t); 1418 assert(tyfunc(t.Tty)); 1419 cpp_calling_convention(t); 1420 //cpp_return_type(s); 1421 tn = t.Tnext; 1422 ty = tn.Tty; 1423 if (LARGEDATA && (tybasic(ty) == TYstruct || tybasic(ty) == TYenum) && 1424 !(ty & mTYLINK)) 1425 tn.Tty |= mTYfar; 1426 cpp_data_type(tn); 1427 tn.Tty = ty; 1428 cpp_argument_types(t); 1429 cpp_throw_types(t); 1430 } 1431 1432 private void cpp_adjustor_thunk_type(Symbol *s) 1433 { 1434 } 1435 1436 private void cpp_vftable_type(Symbol *s) 1437 { 1438 cpp_ecsu_data_indirect_type(s.Stype); 1439 // vpath_name(); 1440 CHAR('@'); 1441 } 1442 1443 private void cpp_local_static_data_type(Symbol *s) 1444 { 1445 //cpp_lexical_frame(?); 1446 cpp_external_data_type(s); 1447 } 1448 1449 private void cpp_static_member_data_type(Symbol *s) 1450 { 1451 cpp_external_data_type(s); 1452 } 1453 1454 private void cpp_static_member_function_type(Symbol *s) 1455 { 1456 cpp_function_type(s.Stype); 1457 } 1458 1459 version (SCPPorMARS) 1460 { 1461 private void cpp_member_function_type(Symbol *s) 1462 { 1463 assert(tyfunc(s.Stype.Tty)); 1464 cpp_this_type(s.Stype,cast(Classsym *)s.Sscope); 1465 if (s.Sfunc.Fflags & (Fctor | Fdtor)) 1466 { type *t = s.Stype; 1467 1468 cpp_calling_convention(t); 1469 CHAR('@'); // return_type for ctors & dtors 1470 cpp_argument_types(t); 1471 cpp_throw_types(t); 1472 } 1473 else 1474 cpp_static_member_function_type(s); 1475 } 1476 } 1477 1478 private void cpp_external_data_type(Symbol *s) 1479 { 1480 cpp_primary_data_type(s.Stype); 1481 cpp_storage_convention(s); 1482 } 1483 1484 private void cpp_external_function_type(Symbol *s) 1485 { 1486 cpp_function_type(s.Stype); 1487 } 1488 1489 private void cpp_type_encoding(Symbol *s) 1490 { char c; 1491 1492 //printf("cpp_type_encoding()\n"); 1493 if (tyfunc(s.Stype.Tty)) 1494 { int farfunc; 1495 1496 farfunc = tyfarfunc(s.Stype.Tty) != 0; 1497 version (SCPPorMARS) 1498 { 1499 if (isclassmember(s)) 1500 { // Member function 1501 int visibility; 1502 int ftype; 1503 1504 visibility = cpp_protection(s); 1505 if (s.Sfunc.Fthunk && !(s.Sfunc.Fflags & Finstance)) 1506 ftype = 3; 1507 else 1508 switch (s.Sfunc.Fflags & (Fvirtual | Fstatic)) 1509 { case Fvirtual: ftype = 2; break; 1510 case Fstatic: ftype = 1; break; 1511 case 0: ftype = 0; break; 1512 default: assert(0); 1513 } 1514 CHAR('A' + farfunc + visibility * 8 + ftype * 2); 1515 switch (ftype) 1516 { case 0: cpp_member_function_type(s); break; 1517 case 1: cpp_static_member_function_type(s); break; 1518 case 2: cpp_member_function_type(s); break; 1519 case 3: cpp_adjustor_thunk_type(s); break; 1520 default: 1521 break; 1522 } 1523 } 1524 else 1525 { // Non-member function 1526 CHAR('Y' + farfunc); 1527 cpp_external_function_type(s); 1528 } 1529 } 1530 else 1531 { 1532 // Non-member function 1533 CHAR('Y' + farfunc); 1534 cpp_external_function_type(s); 1535 } 1536 } 1537 else 1538 { 1539 version (SCPPorMARS) 1540 { 1541 if (isclassmember(s)) 1542 { 1543 // Static data member 1544 CHAR(cpp_protection(s) + '0'); 1545 cpp_static_member_data_type(s); 1546 } 1547 else 1548 { 1549 if (s.Sclass == SC.static_ || 1550 (s.Sscope && 1551 s.Sscope.Sclass != SC.struct_ && 1552 s.Sscope.Sclass != SC.namespace)) 1553 { 1554 CHAR('4'); 1555 cpp_local_static_data_type(s); 1556 } 1557 else 1558 { 1559 CHAR('3'); 1560 cpp_external_data_type(s); 1561 } 1562 } 1563 } 1564 else 1565 { 1566 if (s.Sclass == SC.static_) 1567 { 1568 CHAR('4'); 1569 cpp_local_static_data_type(s); 1570 } 1571 else 1572 { 1573 CHAR('3'); 1574 cpp_external_data_type(s); 1575 } 1576 } 1577 } 1578 } 1579 1580 private void cpp_scope(Symbol *s) 1581 { 1582 /* scope ::= 1583 zname [ scope ] 1584 '?' decorated_name [ scope ] 1585 '?' lexical_frame [ scope ] 1586 '?' '$' template_name [ scope ] 1587 */ 1588 while (s) 1589 { char *p; 1590 1591 symbol_debug(s); 1592 switch (s.Sclass) 1593 { 1594 case SC.namespace: 1595 cpp_zname(s.Sident.ptr); 1596 break; 1597 1598 case SC.struct_: 1599 cpp_zname(symbol_ident(s)); 1600 break; 1601 1602 default: 1603 STR("?1?"); // Why? Who knows. 1604 cpp_decorated_name(s); 1605 break; 1606 } 1607 1608 version (SCPPorMARS) 1609 s = s.Sscope; 1610 else 1611 break; 1612 1613 } 1614 } 1615 1616 private void cpp_zname(const(char)* p) 1617 { 1618 //printf("cpp_zname(%s)\n", p); 1619 if (*p != '?' || // if not operator_name 1620 (NEWTEMPMANGLE && p[1] == '$')) // ?$ is a template name 1621 { 1622 version (MARS) 1623 { 1624 /* Scan forward past any dots 1625 */ 1626 for (const(char)* q = p; *q; q++) 1627 { 1628 if (*q == '.') 1629 p = q + 1; 1630 } 1631 } 1632 1633 for (int i = 0; i < mangle.znamei; i++) 1634 { 1635 if (strcmp(p,mangle.zname[i]) == 0) 1636 { CHAR('0' + i); 1637 return; 1638 } 1639 } 1640 if (mangle.znamei < 10) 1641 mangle.zname[mangle.znamei++] = p; 1642 STR(p); 1643 CHAR('@'); 1644 } 1645 else if (p[1] == 'B') 1646 STR("?B"); // skip return value encoding 1647 else 1648 { 1649 STR(p); 1650 } 1651 } 1652 1653 private void cpp_symbol_name(Symbol *s) 1654 { char *p; 1655 1656 p = s.Sident.ptr; 1657 version (SCPPorHTOD) 1658 { 1659 if (tyfunc(s.Stype.Tty) && s.Sfunc) 1660 { 1661 if (s.Sfunc.Fflags & Finstance) 1662 { 1663 Mangle save = mangle; 1664 char *q; 1665 int len; 1666 1667 p = template_mangle(s, s.Sfunc.Fptal); 1668 len = strlen(p); 1669 q = cast(char *)alloca(len + 1); 1670 assert(q); 1671 memcpy(q, p, len + 1); 1672 mangle = save; 1673 p = q; 1674 } 1675 else if (s.Sfunc.Fflags & Foperator) 1676 { // operator_name ::= '?' operator_code 1677 //CHAR('?'); // already there 1678 STR(p); 1679 return; 1680 } 1681 } 1682 } 1683 version (none) //#if MARS && 0 1684 { 1685 //It mangles correctly, but the ABI doesn't match, 1686 // leading to copious segfaults. At least with the 1687 // wrong mangling you get link errors. 1688 if (tyfunc(s.Stype.Tty) && s.Sfunc) 1689 { 1690 if (s.Sfunc.Fflags & Fctor) 1691 { 1692 cpp_zname(cpp_name_ct); 1693 return; 1694 } 1695 if (s.Sfunc.Fflags & Fdtor) 1696 { 1697 cpp_zname(cpp_name_dt); 1698 return; 1699 } 1700 } 1701 } 1702 cpp_zname(p); 1703 } 1704 1705 private void cpp_decorated_name(Symbol *s) 1706 { char *p; 1707 1708 CHAR('?'); 1709 cpp_symbol_name(s); 1710 version (SCPPorMARS) 1711 { 1712 if (s.Sscope) 1713 cpp_scope(s.Sscope); 1714 } 1715 CHAR('@'); 1716 cpp_type_encoding(s); 1717 } 1718 1719 /********************************* 1720 * Mangle a vtbl or vbtbl name. 1721 * Returns: 1722 * pointer to generated symbol with mangled name 1723 */ 1724 1725 version (SCPPorHTOD) 1726 { 1727 1728 Symbol *mangle_tbl( 1729 int flag, // 0: vtbl, 1: vbtbl 1730 type *t, // type for symbol 1731 Classsym *stag, // class we're putting tbl in 1732 baseclass_t *b) // base class (null if none) 1733 { const(char)* id; 1734 Symbol *s; 1735 1736 static if (0) 1737 { 1738 printf("mangle_tbl(stag = '%s', sbase = '%s', parent = '%s')\n", 1739 stag.Sident.ptr,b ? b.BCbase.Sident.ptr : "null", b ? b.parent.Sident.ptr : "null"); 1740 } 1741 if (flag == 0) 1742 id = config.flags3 & CFG3rtti ? "?_Q" : "?_7"; 1743 else 1744 id = "?_8"; 1745 MangleInuse m; 1746 mangle.znamei = 0; 1747 mangle.argi = 0; 1748 mangle.np = mangle.buf.ptr; 1749 CHAR('?'); 1750 cpp_zname(id); 1751 cpp_scope(stag); 1752 CHAR('@'); 1753 CHAR('6' + flag); 1754 cpp_ecsu_data_indirect_type(t); 1755 static if (1) 1756 { 1757 while (b) 1758 { 1759 cpp_scope(b.BCbase); 1760 CHAR('@'); 1761 b = b.BCpbase; 1762 } 1763 } 1764 else 1765 { 1766 if (b) 1767 { cpp_scope(b.BCbase); 1768 CHAR('@'); 1769 // BUG: what if b is more than one level down? 1770 if (b.parent != stag) 1771 { cpp_scope(b.BCparent); 1772 CHAR('@'); 1773 } 1774 } 1775 } 1776 CHAR('@'); 1777 *mangle.np = 0; // 0-terminate mangle.buf[] 1778 assert(strlen(mangle.buf.ptr) <= BUFIDMAX); 1779 s = scope_define(mangle.buf.ptr,SCTglobal | SCTnspace | SCTlocal,SC.unde); 1780 s.Stype = t; 1781 t.Tcount++; 1782 return s; 1783 } 1784 1785 } 1786 1787 }