ItaniumDemangle.cpp revision 360660
1209734Sjkim//===------------------------- ItaniumDemangle.cpp ------------------------===// 2209734Sjkim// 3209734Sjkim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4209734Sjkim// See https://llvm.org/LICENSE.txt for license information. 5209734Sjkim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6209734Sjkim// 7209734Sjkim//===----------------------------------------------------------------------===// 8209734Sjkim 9209734Sjkim// FIXME: (possibly) incomplete list of features that clang mangles that this 10209734Sjkim// file does not yet support: 11209734Sjkim// - C++ modules TS 12209734Sjkim 13209734Sjkim#include "llvm/Demangle/Demangle.h" 14209734Sjkim#include "llvm/Demangle/ItaniumDemangle.h" 15209734Sjkim 16209734Sjkim#include <cassert> 17209734Sjkim#include <cctype> 18209734Sjkim#include <cstdio> 19209734Sjkim#include <cstdlib> 20209734Sjkim#include <cstring> 21209734Sjkim#include <functional> 22209734Sjkim#include <numeric> 23209734Sjkim#include <utility> 24209734Sjkim#include <vector> 25209734Sjkim 26209734Sjkimusing namespace llvm; 27209734Sjkimusing namespace llvm::itanium_demangle; 28209734Sjkim 29209734Sjkimconstexpr const char *itanium_demangle::FloatData<float>::spec; 30209734Sjkimconstexpr const char *itanium_demangle::FloatData<double>::spec; 31209734Sjkimconstexpr const char *itanium_demangle::FloatData<long double>::spec; 32209734Sjkim 33209734Sjkim// <discriminator> := _ <non-negative number> # when number < 10 34209734Sjkim// := __ <non-negative number> _ # when number >= 10 35209734Sjkim// extension := decimal-digit+ # at the end of string 36209734Sjkimconst char *itanium_demangle::parse_discriminator(const char *first, 37209734Sjkim const char *last) { 38209734Sjkim // parse but ignore discriminator 39209734Sjkim if (first != last) { 40209734Sjkim if (*first == '_') { 41209734Sjkim const char *t1 = first + 1; 42209734Sjkim if (t1 != last) { 43209734Sjkim if (std::isdigit(*t1)) 44209734Sjkim first = t1 + 1; 45209734Sjkim else if (*t1 == '_') { 46209734Sjkim for (++t1; t1 != last && std::isdigit(*t1); ++t1) 47209734Sjkim ; 48209734Sjkim if (t1 != last && *t1 == '_') 49209734Sjkim first = t1 + 1; 50209734Sjkim } 51209734Sjkim } 52209734Sjkim } else if (std::isdigit(*first)) { 53209734Sjkim const char *t1 = first + 1; 54209734Sjkim for (; t1 != last && std::isdigit(*t1); ++t1) 55209734Sjkim ; 56209734Sjkim if (t1 == last) 57209734Sjkim first = last; 58209734Sjkim } 59209734Sjkim } 60209734Sjkim return first; 61209734Sjkim} 62209734Sjkim 63209734Sjkim#ifndef NDEBUG 64209734Sjkimnamespace { 65209734Sjkimstruct DumpVisitor { 66209734Sjkim unsigned Depth = 0; 67209734Sjkim bool PendingNewline = false; 68209734Sjkim 69209734Sjkim template<typename NodeT> static constexpr bool wantsNewline(const NodeT *) { 70209734Sjkim return true; 71209734Sjkim } 72209734Sjkim static bool wantsNewline(NodeArray A) { return !A.empty(); } 73209734Sjkim static constexpr bool wantsNewline(...) { return false; } 74209734Sjkim 75209734Sjkim template<typename ...Ts> static bool anyWantNewline(Ts ...Vs) { 76209734Sjkim for (bool B : {wantsNewline(Vs)...}) 77209734Sjkim if (B) 78209734Sjkim return true; 79209734Sjkim return false; 80209734Sjkim } 81209734Sjkim 82209734Sjkim void printStr(const char *S) { fprintf(stderr, "%s", S); } 83209734Sjkim void print(StringView SV) { 84209734Sjkim fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin()); 85209734Sjkim } 86209734Sjkim void print(const Node *N) { 87209734Sjkim if (N) 88209734Sjkim N->visit(std::ref(*this)); 89209734Sjkim else 90209734Sjkim printStr("<null>"); 91209734Sjkim } 92209734Sjkim void print(NodeOrString NS) { 93209734Sjkim if (NS.isNode()) 94209734Sjkim print(NS.asNode()); 95209734Sjkim else if (NS.isString()) 96209734Sjkim print(NS.asString()); 97209734Sjkim else 98209734Sjkim printStr("NodeOrString()"); 99209734Sjkim } 100209734Sjkim void print(NodeArray A) { 101209734Sjkim ++Depth; 102209734Sjkim printStr("{"); 103209734Sjkim bool First = true; 104209734Sjkim for (const Node *N : A) { 105209734Sjkim if (First) 106209734Sjkim print(N); 107209734Sjkim else 108209734Sjkim printWithComma(N); 109209734Sjkim First = false; 110209734Sjkim } 111209734Sjkim printStr("}"); 112209734Sjkim --Depth; 113209734Sjkim } 114209734Sjkim 115209734Sjkim // Overload used when T is exactly 'bool', not merely convertible to 'bool'. 116209746Sjkim void print(bool B) { printStr(B ? "true" : "false"); } 117209746Sjkim 118209746Sjkim template <class T> 119209746Sjkim typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) { 120209734Sjkim fprintf(stderr, "%llu", (unsigned long long)N); 121209734Sjkim } 122209734Sjkim 123209734Sjkim template <class T> 124209734Sjkim typename std::enable_if<std::is_signed<T>::value>::type print(T N) { 125209734Sjkim fprintf(stderr, "%lld", (long long)N); 126209734Sjkim } 127209734Sjkim 128209734Sjkim void print(ReferenceKind RK) { 129209734Sjkim switch (RK) { 130209734Sjkim case ReferenceKind::LValue: 131209734Sjkim return printStr("ReferenceKind::LValue"); 132209734Sjkim case ReferenceKind::RValue: 133209734Sjkim return printStr("ReferenceKind::RValue"); 134209734Sjkim } 135209734Sjkim } 136209734Sjkim void print(FunctionRefQual RQ) { 137209734Sjkim switch (RQ) { 138209734Sjkim case FunctionRefQual::FrefQualNone: 139209734Sjkim return printStr("FunctionRefQual::FrefQualNone"); 140209734Sjkim case FunctionRefQual::FrefQualLValue: 141209734Sjkim return printStr("FunctionRefQual::FrefQualLValue"); 142209734Sjkim case FunctionRefQual::FrefQualRValue: 143209734Sjkim return printStr("FunctionRefQual::FrefQualRValue"); 144209734Sjkim } 145209734Sjkim } 146209734Sjkim void print(Qualifiers Qs) { 147209734Sjkim if (!Qs) return printStr("QualNone"); 148209734Sjkim struct QualName { Qualifiers Q; const char *Name; } Names[] = { 149209734Sjkim {QualConst, "QualConst"}, 150209734Sjkim {QualVolatile, "QualVolatile"}, 151209734Sjkim {QualRestrict, "QualRestrict"}, 152209734Sjkim }; 153209734Sjkim for (QualName Name : Names) { 154209734Sjkim if (Qs & Name.Q) { 155209734Sjkim printStr(Name.Name); 156209734Sjkim Qs = Qualifiers(Qs & ~Name.Q); 157209734Sjkim if (Qs) printStr(" | "); 158209734Sjkim } 159209734Sjkim } 160209734Sjkim } 161209734Sjkim void print(SpecialSubKind SSK) { 162209734Sjkim switch (SSK) { 163209734Sjkim case SpecialSubKind::allocator: 164209734Sjkim return printStr("SpecialSubKind::allocator"); 165209734Sjkim case SpecialSubKind::basic_string: 166209734Sjkim return printStr("SpecialSubKind::basic_string"); 167209734Sjkim case SpecialSubKind::string: 168209734Sjkim return printStr("SpecialSubKind::string"); 169209734Sjkim case SpecialSubKind::istream: 170209734Sjkim return printStr("SpecialSubKind::istream"); 171209734Sjkim case SpecialSubKind::ostream: 172209734Sjkim return printStr("SpecialSubKind::ostream"); 173209734Sjkim case SpecialSubKind::iostream: 174209734Sjkim return printStr("SpecialSubKind::iostream"); 175209734Sjkim } 176209734Sjkim } 177209734Sjkim 178209734Sjkim void newLine() { 179209734Sjkim printStr("\n"); 180209734Sjkim for (unsigned I = 0; I != Depth; ++I) 181209734Sjkim printStr(" "); 182209734Sjkim PendingNewline = false; 183209734Sjkim } 184209734Sjkim 185209734Sjkim template<typename T> void printWithPendingNewline(T V) { 186209734Sjkim print(V); 187209734Sjkim if (wantsNewline(V)) 188209734Sjkim PendingNewline = true; 189209734Sjkim } 190209734Sjkim 191209734Sjkim template<typename T> void printWithComma(T V) { 192209734Sjkim if (PendingNewline || wantsNewline(V)) { 193209734Sjkim printStr(","); 194209734Sjkim newLine(); 195209734Sjkim } else { 196209734Sjkim printStr(", "); 197209734Sjkim } 198209734Sjkim 199209734Sjkim printWithPendingNewline(V); 200209734Sjkim } 201209734Sjkim 202209734Sjkim struct CtorArgPrinter { 203209734Sjkim DumpVisitor &Visitor; 204209734Sjkim 205209734Sjkim template<typename T, typename ...Rest> void operator()(T V, Rest ...Vs) { 206209734Sjkim if (Visitor.anyWantNewline(V, Vs...)) 207209734Sjkim Visitor.newLine(); 208209734Sjkim Visitor.printWithPendingNewline(V); 209209734Sjkim int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 }; 210209734Sjkim (void)PrintInOrder; 211209734Sjkim } 212209734Sjkim }; 213209734Sjkim 214209734Sjkim template<typename NodeT> void operator()(const NodeT *Node) { 215209734Sjkim Depth += 2; 216209734Sjkim fprintf(stderr, "%s(", itanium_demangle::NodeKind<NodeT>::name()); 217209734Sjkim Node->match(CtorArgPrinter{*this}); 218209734Sjkim fprintf(stderr, ")"); 219209734Sjkim Depth -= 2; 220209734Sjkim } 221209734Sjkim 222209734Sjkim void operator()(const ForwardTemplateReference *Node) { 223209734Sjkim Depth += 2; 224209734Sjkim fprintf(stderr, "ForwardTemplateReference("); 225209734Sjkim if (Node->Ref && !Node->Printing) { 226209734Sjkim Node->Printing = true; 227209734Sjkim CtorArgPrinter{*this}(Node->Ref); 228209734Sjkim Node->Printing = false; 229209734Sjkim } else { 230209734Sjkim CtorArgPrinter{*this}(Node->Index); 231209734Sjkim } 232209734Sjkim fprintf(stderr, ")"); 233209734Sjkim Depth -= 2; 234209734Sjkim } 235209734Sjkim}; 236209734Sjkim} 237209734Sjkim 238209734Sjkimvoid itanium_demangle::Node::dump() const { 239209734Sjkim DumpVisitor V; 240209734Sjkim visit(std::ref(V)); 241209734Sjkim V.newLine(); 242209734Sjkim} 243209734Sjkim#endif 244209734Sjkim 245209734Sjkimnamespace { 246209734Sjkimclass BumpPointerAllocator { 247209734Sjkim struct BlockMeta { 248209734Sjkim BlockMeta* Next; 249209734Sjkim size_t Current; 250209734Sjkim }; 251209734Sjkim 252209734Sjkim static constexpr size_t AllocSize = 4096; 253209734Sjkim static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta); 254209734Sjkim 255209734Sjkim alignas(long double) char InitialBuffer[AllocSize]; 256209734Sjkim BlockMeta* BlockList = nullptr; 257209734Sjkim 258209734Sjkim void grow() { 259209734Sjkim char* NewMeta = static_cast<char *>(std::malloc(AllocSize)); 260209734Sjkim if (NewMeta == nullptr) 261209734Sjkim std::terminate(); 262209734Sjkim BlockList = new (NewMeta) BlockMeta{BlockList, 0}; 263209734Sjkim } 264209734Sjkim 265209734Sjkim void* allocateMassive(size_t NBytes) { 266209734Sjkim NBytes += sizeof(BlockMeta); 267209734Sjkim BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes)); 268209734Sjkim if (NewMeta == nullptr) 269209734Sjkim std::terminate(); 270209734Sjkim BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0}; 271209734Sjkim return static_cast<void*>(NewMeta + 1); 272209734Sjkim } 273209734Sjkim 274209734Sjkimpublic: 275209734Sjkim BumpPointerAllocator() 276209734Sjkim : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {} 277209734Sjkim 278209734Sjkim void* allocate(size_t N) { 279209734Sjkim N = (N + 15u) & ~15u; 280209734Sjkim if (N + BlockList->Current >= UsableAllocSize) { 281209734Sjkim if (N > UsableAllocSize) 282209734Sjkim return allocateMassive(N); 283209734Sjkim grow(); 284209734Sjkim } 285209734Sjkim BlockList->Current += N; 286209734Sjkim return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) + 287209734Sjkim BlockList->Current - N); 288209734Sjkim } 289209734Sjkim 290209734Sjkim void reset() { 291209734Sjkim while (BlockList) { 292209734Sjkim BlockMeta* Tmp = BlockList; 293209734Sjkim BlockList = BlockList->Next; 294209734Sjkim if (reinterpret_cast<char*>(Tmp) != InitialBuffer) 295209734Sjkim std::free(Tmp); 296209734Sjkim } 297209734Sjkim BlockList = new (InitialBuffer) BlockMeta{nullptr, 0}; 298209734Sjkim } 299209734Sjkim 300209734Sjkim ~BumpPointerAllocator() { reset(); } 301209734Sjkim}; 302209734Sjkim 303209734Sjkimclass DefaultAllocator { 304209734Sjkim BumpPointerAllocator Alloc; 305209734Sjkim 306209734Sjkimpublic: 307209734Sjkim void reset() { Alloc.reset(); } 308209734Sjkim 309209734Sjkim template<typename T, typename ...Args> T *makeNode(Args &&...args) { 310209734Sjkim return new (Alloc.allocate(sizeof(T))) 311209734Sjkim T(std::forward<Args>(args)...); 312209734Sjkim } 313209734Sjkim 314209734Sjkim void *allocateNodeArray(size_t sz) { 315209734Sjkim return Alloc.allocate(sizeof(Node *) * sz); 316209734Sjkim } 317209734Sjkim}; 318209734Sjkim} // unnamed namespace 319209734Sjkim 320209734Sjkim//===----------------------------------------------------------------------===// 321209734Sjkim// Code beyond this point should not be synchronized with libc++abi. 322209734Sjkim//===----------------------------------------------------------------------===// 323209734Sjkim 324209734Sjkimusing Demangler = itanium_demangle::ManglingParser<DefaultAllocator>; 325209734Sjkim 326209734Sjkimchar *llvm::itaniumDemangle(const char *MangledName, char *Buf, 327209734Sjkim size_t *N, int *Status) { 328209734Sjkim if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) { 329209734Sjkim if (Status) 330209734Sjkim *Status = demangle_invalid_args; 331209734Sjkim return nullptr; 332209734Sjkim } 333209734Sjkim 334209734Sjkim int InternalStatus = demangle_success; 335209734Sjkim Demangler Parser(MangledName, MangledName + std::strlen(MangledName)); 336209734Sjkim OutputStream S; 337209734Sjkim 338209734Sjkim Node *AST = Parser.parse(); 339209734Sjkim 340209734Sjkim if (AST == nullptr) 341209734Sjkim InternalStatus = demangle_invalid_mangled_name; 342209734Sjkim else if (!initializeOutputStream(Buf, N, S, 1024)) 343209734Sjkim InternalStatus = demangle_memory_alloc_failure; 344209734Sjkim else { 345209734Sjkim assert(Parser.ForwardTemplateRefs.empty()); 346209734Sjkim AST->print(S); 347209734Sjkim S += '\0'; 348209734Sjkim if (N != nullptr) 349209734Sjkim *N = S.getCurrentPosition(); 350209734Sjkim Buf = S.getBuffer(); 351209734Sjkim } 352209734Sjkim 353209734Sjkim if (Status) 354209734Sjkim *Status = InternalStatus; 355209734Sjkim return InternalStatus == demangle_success ? Buf : nullptr; 356209734Sjkim} 357209734Sjkim 358209734SjkimItaniumPartialDemangler::ItaniumPartialDemangler() 359209734Sjkim : RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {} 360209734Sjkim 361209734SjkimItaniumPartialDemangler::~ItaniumPartialDemangler() { 362209734Sjkim delete static_cast<Demangler *>(Context); 363209734Sjkim} 364209734Sjkim 365209734SjkimItaniumPartialDemangler::ItaniumPartialDemangler( 366209734Sjkim ItaniumPartialDemangler &&Other) 367209734Sjkim : RootNode(Other.RootNode), Context(Other.Context) { 368209734Sjkim Other.Context = Other.RootNode = nullptr; 369209734Sjkim} 370209734Sjkim 371209734SjkimItaniumPartialDemangler &ItaniumPartialDemangler:: 372209734Sjkimoperator=(ItaniumPartialDemangler &&Other) { 373209734Sjkim std::swap(RootNode, Other.RootNode); 374209734Sjkim std::swap(Context, Other.Context); 375209734Sjkim return *this; 376209734Sjkim} 377209734Sjkim 378209734Sjkim// Demangle MangledName into an AST, storing it into this->RootNode. 379209734Sjkimbool ItaniumPartialDemangler::partialDemangle(const char *MangledName) { 380209734Sjkim Demangler *Parser = static_cast<Demangler *>(Context); 381209734Sjkim size_t Len = std::strlen(MangledName); 382209734Sjkim Parser->reset(MangledName, MangledName + Len); 383209734Sjkim RootNode = Parser->parse(); 384209734Sjkim return RootNode == nullptr; 385209734Sjkim} 386209734Sjkim 387209734Sjkimstatic char *printNode(const Node *RootNode, char *Buf, size_t *N) { 388209734Sjkim OutputStream S; 389209734Sjkim if (!initializeOutputStream(Buf, N, S, 128)) 390209734Sjkim return nullptr; 391209734Sjkim RootNode->print(S); 392209734Sjkim S += '\0'; 393209734Sjkim if (N != nullptr) 394209734Sjkim *N = S.getCurrentPosition(); 395209734Sjkim return S.getBuffer(); 396209734Sjkim} 397209734Sjkim 398209734Sjkimchar *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const { 399209734Sjkim if (!isFunction()) 400209734Sjkim return nullptr; 401209734Sjkim 402209734Sjkim const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName(); 403209734Sjkim 404209734Sjkim while (true) { 405209734Sjkim switch (Name->getKind()) { 406209734Sjkim case Node::KAbiTagAttr: 407209734Sjkim Name = static_cast<const AbiTagAttr *>(Name)->Base; 408209734Sjkim continue; 409209734Sjkim case Node::KStdQualifiedName: 410209734Sjkim Name = static_cast<const StdQualifiedName *>(Name)->Child; 411209734Sjkim continue; 412209734Sjkim case Node::KNestedName: 413209734Sjkim Name = static_cast<const NestedName *>(Name)->Name; 414209734Sjkim continue; 415209734Sjkim case Node::KLocalName: 416209734Sjkim Name = static_cast<const LocalName *>(Name)->Entity; 417209734Sjkim continue; 418209734Sjkim case Node::KNameWithTemplateArgs: 419209734Sjkim Name = static_cast<const NameWithTemplateArgs *>(Name)->Name; 420209734Sjkim continue; 421209734Sjkim default: 422209734Sjkim return printNode(Name, Buf, N); 423209734Sjkim } 424209734Sjkim } 425209734Sjkim} 426209734Sjkim 427209734Sjkimchar *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf, 428209734Sjkim size_t *N) const { 429209734Sjkim if (!isFunction()) 430209734Sjkim return nullptr; 431209734Sjkim const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName(); 432209734Sjkim 433209734Sjkim OutputStream S; 434209734Sjkim if (!initializeOutputStream(Buf, N, S, 128)) 435209734Sjkim return nullptr; 436209734Sjkim 437209734Sjkim KeepGoingLocalFunction: 438209734Sjkim while (true) { 439209734Sjkim if (Name->getKind() == Node::KAbiTagAttr) { 440209734Sjkim Name = static_cast<const AbiTagAttr *>(Name)->Base; 441209734Sjkim continue; 442209734Sjkim } 443209734Sjkim if (Name->getKind() == Node::KNameWithTemplateArgs) { 444209734Sjkim Name = static_cast<const NameWithTemplateArgs *>(Name)->Name; 445209734Sjkim continue; 446 } 447 break; 448 } 449 450 switch (Name->getKind()) { 451 case Node::KStdQualifiedName: 452 S += "std"; 453 break; 454 case Node::KNestedName: 455 static_cast<const NestedName *>(Name)->Qual->print(S); 456 break; 457 case Node::KLocalName: { 458 auto *LN = static_cast<const LocalName *>(Name); 459 LN->Encoding->print(S); 460 S += "::"; 461 Name = LN->Entity; 462 goto KeepGoingLocalFunction; 463 } 464 default: 465 break; 466 } 467 S += '\0'; 468 if (N != nullptr) 469 *N = S.getCurrentPosition(); 470 return S.getBuffer(); 471} 472 473char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const { 474 if (!isFunction()) 475 return nullptr; 476 auto *Name = static_cast<FunctionEncoding *>(RootNode)->getName(); 477 return printNode(Name, Buf, N); 478} 479 480char *ItaniumPartialDemangler::getFunctionParameters(char *Buf, 481 size_t *N) const { 482 if (!isFunction()) 483 return nullptr; 484 NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams(); 485 486 OutputStream S; 487 if (!initializeOutputStream(Buf, N, S, 128)) 488 return nullptr; 489 490 S += '('; 491 Params.printWithComma(S); 492 S += ')'; 493 S += '\0'; 494 if (N != nullptr) 495 *N = S.getCurrentPosition(); 496 return S.getBuffer(); 497} 498 499char *ItaniumPartialDemangler::getFunctionReturnType( 500 char *Buf, size_t *N) const { 501 if (!isFunction()) 502 return nullptr; 503 504 OutputStream S; 505 if (!initializeOutputStream(Buf, N, S, 128)) 506 return nullptr; 507 508 if (const Node *Ret = 509 static_cast<const FunctionEncoding *>(RootNode)->getReturnType()) 510 Ret->print(S); 511 512 S += '\0'; 513 if (N != nullptr) 514 *N = S.getCurrentPosition(); 515 return S.getBuffer(); 516} 517 518char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const { 519 assert(RootNode != nullptr && "must call partialDemangle()"); 520 return printNode(static_cast<Node *>(RootNode), Buf, N); 521} 522 523bool ItaniumPartialDemangler::hasFunctionQualifiers() const { 524 assert(RootNode != nullptr && "must call partialDemangle()"); 525 if (!isFunction()) 526 return false; 527 auto *E = static_cast<const FunctionEncoding *>(RootNode); 528 return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone; 529} 530 531bool ItaniumPartialDemangler::isCtorOrDtor() const { 532 const Node *N = static_cast<const Node *>(RootNode); 533 while (N) { 534 switch (N->getKind()) { 535 default: 536 return false; 537 case Node::KCtorDtorName: 538 return true; 539 540 case Node::KAbiTagAttr: 541 N = static_cast<const AbiTagAttr *>(N)->Base; 542 break; 543 case Node::KFunctionEncoding: 544 N = static_cast<const FunctionEncoding *>(N)->getName(); 545 break; 546 case Node::KLocalName: 547 N = static_cast<const LocalName *>(N)->Entity; 548 break; 549 case Node::KNameWithTemplateArgs: 550 N = static_cast<const NameWithTemplateArgs *>(N)->Name; 551 break; 552 case Node::KNestedName: 553 N = static_cast<const NestedName *>(N)->Name; 554 break; 555 case Node::KStdQualifiedName: 556 N = static_cast<const StdQualifiedName *>(N)->Child; 557 break; 558 } 559 } 560 return false; 561} 562 563bool ItaniumPartialDemangler::isFunction() const { 564 assert(RootNode != nullptr && "must call partialDemangle()"); 565 return static_cast<const Node *>(RootNode)->getKind() == 566 Node::KFunctionEncoding; 567} 568 569bool ItaniumPartialDemangler::isSpecialName() const { 570 assert(RootNode != nullptr && "must call partialDemangle()"); 571 auto K = static_cast<const Node *>(RootNode)->getKind(); 572 return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName; 573} 574 575bool ItaniumPartialDemangler::isData() const { 576 return !isFunction() && !isSpecialName(); 577} 578