brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.3 KiB · 780b2c5 Raw
668 lines · cpp
1//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Implements generic name mangling support for blocks and Objective-C.10//11//===----------------------------------------------------------------------===//12#include "clang/AST/Mangle.h"13#include "clang/AST/ASTContext.h"14#include "clang/AST/Attr.h"15#include "clang/AST/Decl.h"16#include "clang/AST/DeclCXX.h"17#include "clang/AST/DeclObjC.h"18#include "clang/AST/DeclTemplate.h"19#include "clang/AST/ExprCXX.h"20#include "clang/AST/VTableBuilder.h"21#include "clang/Basic/ABI.h"22#include "clang/Basic/TargetInfo.h"23#include "llvm/ADT/StringExtras.h"24#include "llvm/IR/DataLayout.h"25#include "llvm/IR/Mangler.h"26#include "llvm/Support/ErrorHandling.h"27#include "llvm/Support/Format.h"28#include "llvm/Support/raw_ostream.h"29 30using namespace clang;31 32void clang::mangleObjCMethodName(raw_ostream &OS, bool includePrefixByte,33                                 bool isInstanceMethod, StringRef ClassName,34                                 std::optional<StringRef> CategoryName,35                                 StringRef MethodName) {36  // \01+[ContainerName(CategoryName) SelectorName]37  if (includePrefixByte)38    OS << "\01";39  OS << (isInstanceMethod ? '-' : '+');40  OS << '[';41  OS << ClassName;42  if (CategoryName)43    OS << "(" << *CategoryName << ")";44  OS << " ";45  OS << MethodName;46  OS << ']';47}48 49// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves50// much to be desired. Come up with a better mangling scheme.51 52static void mangleFunctionBlock(MangleContext &Context,53                                StringRef Outer,54                                const BlockDecl *BD,55                                raw_ostream &Out) {56  unsigned discriminator = Context.getBlockId(BD, true);57  if (discriminator == 0)58    Out << "__" << Outer << "_block_invoke";59  else60    Out << "__" << Outer << "_block_invoke_" << discriminator+1;61}62 63void MangleContext::anchor() { }64 65enum CCMangling {66  CCM_Other,67  CCM_Fast,68  CCM_RegCall,69  CCM_Vector,70  CCM_Std,71  CCM_WasmMainArgcArgv72};73 74static bool isExternC(const NamedDecl *ND) {75  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))76    return FD->isExternC();77  if (const VarDecl *VD = dyn_cast<VarDecl>(ND))78    return VD->isExternC();79  return false;80}81 82static CCMangling getCallingConvMangling(const ASTContext &Context,83                                         const NamedDecl *ND) {84  const TargetInfo &TI = Context.getTargetInfo();85  const llvm::Triple &Triple = TI.getTriple();86 87  // On wasm, the argc/argv form of "main" is renamed so that the startup code88  // can call it with the correct function signature.89  if (Triple.isWasm())90    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))91      if (FD->isMain() && FD->getNumParams() == 2)92        return CCM_WasmMainArgcArgv;93 94  if (!TI.shouldUseMicrosoftCCforMangling())95    return CCM_Other;96 97  if (Context.getLangOpts().CPlusPlus && !isExternC(ND) &&98      TI.getCXXABI() == TargetCXXABI::Microsoft)99    return CCM_Other;100 101  const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);102  if (!FD)103    return CCM_Other;104  QualType T = FD->getType();105 106  const FunctionType *FT = T->castAs<FunctionType>();107 108  CallingConv CC = FT->getCallConv();109  switch (CC) {110  default:111    return CCM_Other;112  case CC_X86FastCall:113    return CCM_Fast;114  case CC_X86StdCall:115    return CCM_Std;116  case CC_X86VectorCall:117    return CCM_Vector;118  }119}120 121bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {122  const ASTContext &ASTContext = getASTContext();123 124  CCMangling CC = getCallingConvMangling(ASTContext, D);125  if (CC != CCM_Other)126    return true;127 128  // If the declaration has an owning module for linkage purposes that needs to129  // be mangled, we must mangle its name.130  if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())131    return true;132 133  // C functions with internal linkage have to be mangled with option134  // -funique-internal-linkage-names.135  if (!getASTContext().getLangOpts().CPlusPlus &&136      isUniqueInternalLinkageDecl(D))137    return true;138 139  // In C, functions with no attributes never need to be mangled. Fastpath them.140  if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())141    return false;142 143  // Any decl can be declared with __asm("foo") on it, and this takes precedence144  // over all other naming in the .o file.145  if (D->hasAttr<AsmLabelAttr>())146    return true;147 148  // Declarations that don't have identifier names always need to be mangled.149  if (isa<MSGuidDecl>(D))150    return true;151 152  return shouldMangleCXXName(D);153}154 155static llvm::StringRef g_lldb_func_call_label_prefix = "$__lldb_func:";156 157/// Given an LLDB function call label, this function prints the label158/// into \c Out, together with the structor type of \c GD (if the159/// decl is a constructor/destructor). LLDB knows how to handle mangled160/// names with this encoding.161///162/// Example input label:163///   $__lldb_func::123:456:~Foo164///165/// Example output:166///   $__lldb_func:D1:123:456:~Foo167///168static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,169                             llvm::raw_ostream &Out) {170  assert(label.starts_with(g_lldb_func_call_label_prefix));171 172  Out << g_lldb_func_call_label_prefix;173 174  if (auto *Ctor = llvm::dyn_cast<clang::CXXConstructorDecl>(GD.getDecl())) {175    Out << "C";176    if (Ctor->getInheritedConstructor().getConstructor())177      Out << "I";178    Out << GD.getCtorType();179  } else if (llvm::isa<clang::CXXDestructorDecl>(GD.getDecl())) {180    Out << "D" << GD.getDtorType();181  }182 183  Out << label.substr(g_lldb_func_call_label_prefix.size());184}185 186void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {187  const ASTContext &ASTContext = getASTContext();188  const NamedDecl *D = cast<NamedDecl>(GD.getDecl());189 190  // Any decl can be declared with __asm("foo") on it, and this takes precedence191  // over all other naming in the .o file.192  if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {193    // If we have an asm name, then we use it as the mangling.194 195    // If the label is an alias for an LLVM intrinsic,196    // do not add a "\01" prefix.197    if (ALA->getLabel().starts_with("llvm.")) {198      Out << ALA->getLabel();199      return;200    }201 202    // Adding the prefix can cause problems when one file has a "foo" and203    // another has a "\01foo". That is known to happen on ELF with the204    // tricks normally used for producing aliases (PR9177). Fortunately the205    // llvm mangler on ELF is a nop, so we can just avoid adding the \01206    // marker.207    StringRef UserLabelPrefix =208        getASTContext().getTargetInfo().getUserLabelPrefix();209#ifndef NDEBUG210    char GlobalPrefix =211        llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())212            .getGlobalPrefix();213    assert((UserLabelPrefix.empty() && !GlobalPrefix) ||214           (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));215#endif216    if (!UserLabelPrefix.empty())217      Out << '\01'; // LLVM IR Marker for __asm("foo")218 219    if (ALA->getLabel().starts_with(g_lldb_func_call_label_prefix))220      emitLLDBAsmLabel(ALA->getLabel(), GD, Out);221    else222      Out << ALA->getLabel();223 224    return;225  }226 227  if (auto *GD = dyn_cast<MSGuidDecl>(D))228    return mangleMSGuidDecl(GD, Out);229 230  CCMangling CC = getCallingConvMangling(ASTContext, D);231 232  if (CC == CCM_WasmMainArgcArgv) {233    Out << "__main_argc_argv";234    return;235  }236 237  bool MCXX = shouldMangleCXXName(D);238  const TargetInfo &TI = Context.getTargetInfo();239  if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {240    if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))241      mangleObjCMethodNameAsSourceName(OMD, Out);242    else243      mangleCXXName(GD, Out);244    return;245  }246 247  Out << '\01';248  if (CC == CCM_Std)249    Out << '_';250  else if (CC == CCM_Fast)251    Out << '@';252  else if (CC == CCM_RegCall) {253    if (getASTContext().getLangOpts().RegCall4)254      Out << "__regcall4__";255    else256      Out << "__regcall3__";257  }258 259  if (!MCXX)260    Out << D->getIdentifier()->getName();261  else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))262    mangleObjCMethodNameAsSourceName(OMD, Out);263  else264    mangleCXXName(GD, Out);265 266  const FunctionDecl *FD = cast<FunctionDecl>(D);267  const FunctionType *FT = FD->getType()->castAs<FunctionType>();268  const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);269  if (CC == CCM_Vector)270    Out << '@';271  Out << '@';272  if (!Proto) {273    Out << '0';274    return;275  }276  assert(!Proto->isVariadic());277  unsigned ArgWords = 0;278  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))279    if (MD->isImplicitObjectMemberFunction())280      ++ArgWords;281  uint64_t DefaultPtrWidth = TI.getPointerWidth(LangAS::Default);282  for (const auto &AT : Proto->param_types()) {283    // If an argument type is incomplete there is no way to get its size to284    // correctly encode into the mangling scheme.285    // Follow GCCs behaviour by simply breaking out of the loop.286    if (AT->isIncompleteType())287      break;288    // Size should be aligned to pointer size.289    ArgWords += llvm::alignTo(ASTContext.getTypeSize(AT), DefaultPtrWidth) /290                DefaultPtrWidth;291  }292  Out << ((DefaultPtrWidth / 8) * ArgWords);293}294 295void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD,296                                     raw_ostream &Out) const {297  // For now, follow the MSVC naming convention for GUID objects on all298  // targets.299  MSGuidDecl::Parts P = GD->getParts();300  Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",301                      P.Part1, P.Part2, P.Part3);302  unsigned I = 0;303  for (uint8_t C : P.Part4And5) {304    Out << llvm::format("%02" PRIx8, C);305    if (++I == 2)306      Out << "_";307  }308}309 310void MangleContext::mangleGlobalBlock(const BlockDecl *BD,311                                      const NamedDecl *ID,312                                      raw_ostream &Out) {313  unsigned discriminator = getBlockId(BD, false);314  if (ID) {315    if (shouldMangleDeclName(ID))316      mangleName(ID, Out);317    else {318      Out << ID->getIdentifier()->getName();319    }320  }321  if (discriminator == 0)322    Out << "_block_invoke";323  else324    Out << "_block_invoke_" << discriminator+1;325}326 327void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,328                                    CXXCtorType CT, const BlockDecl *BD,329                                    raw_ostream &ResStream) {330  SmallString<64> Buffer;331  llvm::raw_svector_ostream Out(Buffer);332  mangleName(GlobalDecl(CD, CT), Out);333  mangleFunctionBlock(*this, Buffer, BD, ResStream);334}335 336void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,337                                    CXXDtorType DT, const BlockDecl *BD,338                                    raw_ostream &ResStream) {339  SmallString<64> Buffer;340  llvm::raw_svector_ostream Out(Buffer);341  mangleName(GlobalDecl(DD, DT), Out);342  mangleFunctionBlock(*this, Buffer, BD, ResStream);343}344 345void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,346                                raw_ostream &Out) {347  assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));348 349  SmallString<64> Buffer;350  llvm::raw_svector_ostream Stream(Buffer);351  if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {352    mangleObjCMethodNameAsSourceName(Method, Stream);353  } else {354    assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&355           "expected a NamedDecl or BlockDecl");356    for (; isa_and_nonnull<BlockDecl>(DC); DC = DC->getParent())357      (void)getBlockId(cast<BlockDecl>(DC), true);358    assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&359           "expected a TranslationUnitDecl or a NamedDecl");360    if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))361      mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);362    else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))363      mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);364    else if (auto ND = dyn_cast<NamedDecl>(DC)) {365      if (!shouldMangleDeclName(ND) && ND->getIdentifier())366        Stream << ND->getIdentifier()->getName();367      else {368        // FIXME: We were doing a mangleUnqualifiedName() before, but that's369        // a private member of a class that will soon itself be private to the370        // Itanium C++ ABI object. What should we do now? Right now, I'm just371        // calling the mangleName() method on the MangleContext; is there a372        // better way?373        mangleName(ND, Stream);374      }375    }376  }377  mangleFunctionBlock(*this, Buffer, BD, Out);378}379 380void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,381                                         raw_ostream &OS,382                                         bool includePrefixByte,383                                         bool includeCategoryNamespace) const {384  if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) {385    // This is the mangling we've always used on the GNU runtimes, but it386    // has obvious collisions in the face of underscores within class387    // names, category names, and selectors; maybe we should improve it.388 389    OS << (MD->isClassMethod() ? "_c_" : "_i_")390       << MD->getClassInterface()->getName() << '_';391 392    if (includeCategoryNamespace) {393      if (auto category = MD->getCategory())394        OS << category->getName();395    }396    OS << '_';397 398    auto selector = MD->getSelector();399    for (unsigned slotIndex = 0,400                  numArgs = selector.getNumArgs(),401                  slotEnd = std::max(numArgs, 1U);402           slotIndex != slotEnd; ++slotIndex) {403      if (auto name = selector.getIdentifierInfoForSlot(slotIndex))404        OS << name->getName();405 406      // Replace all the positions that would've been ':' with '_'.407      // That's after each slot except that a unary selector doesn't408      // end in ':'.409      if (numArgs)410        OS << '_';411    }412 413    return;414  }415 416  // \01+[ContainerName(CategoryName) SelectorName]417  auto CategoryName = std::optional<StringRef>();418  StringRef ClassName = "";419  if (const auto *CID = MD->getCategory()) {420    if (const auto *CI = CID->getClassInterface()) {421      ClassName = CI->getName();422      if (includeCategoryNamespace) {423        CategoryName = CID->getName();424      }425    }426  } else if (const auto *CD =427                 dyn_cast<ObjCContainerDecl>(MD->getDeclContext())) {428    ClassName = CD->getName();429  } else {430    llvm_unreachable("Unexpected ObjC method decl context");431  }432  std::string MethodName;433  llvm::raw_string_ostream MethodNameOS(MethodName);434  MD->getSelector().print(MethodNameOS);435  clang::mangleObjCMethodName(OS, includePrefixByte, MD->isInstanceMethod(),436                              ClassName, CategoryName, MethodName);437}438 439void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,440                                                     raw_ostream &Out) const {441  SmallString<64> Name;442  llvm::raw_svector_ostream OS(Name);443 444  mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,445                       /*includeCategoryNamespace=*/true);446  Out << OS.str().size() << OS.str();447}448 449class ASTNameGenerator::Implementation {450  std::unique_ptr<MangleContext> MC;451  llvm::DataLayout DL;452 453public:454  explicit Implementation(ASTContext &Ctx)455      : MC(Ctx.createMangleContext()),456        DL(Ctx.getTargetInfo().getDataLayoutString()) {}457 458  bool writeName(const Decl *D, raw_ostream &OS) {459    // First apply frontend mangling.460    SmallString<128> FrontendBuf;461    llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);462    if (auto *FD = dyn_cast<FunctionDecl>(D)) {463      if (FD->isDependentContext())464        return true;465      if (writeFuncOrVarName(FD, FrontendBufOS))466        return true;467    } else if (auto *VD = dyn_cast<VarDecl>(D)) {468      if (writeFuncOrVarName(VD, FrontendBufOS))469        return true;470    } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {471      MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,472                               /*includeCategoryNamespace=*/true);473      return false;474    } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {475      writeObjCClassName(ID, FrontendBufOS);476    } else {477      return true;478    }479 480    // Now apply backend mangling.481    llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);482    return false;483  }484 485  std::string getName(const Decl *D) {486    std::string Name;487    {488      llvm::raw_string_ostream OS(Name);489      writeName(D, OS);490    }491    return Name;492  }493 494  enum ObjCKind {495    ObjCClass,496    ObjCMetaclass,497  };498 499  static StringRef getClassSymbolPrefix(ObjCKind Kind,500                                        const ASTContext &Context) {501    if (Context.getLangOpts().ObjCRuntime.isGNUFamily())502      return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";503    return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";504  }505 506  std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {507    StringRef ClassName;508    if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))509      ClassName = OID->getObjCRuntimeNameAsString();510    else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))511      ClassName = OID->getObjCRuntimeNameAsString();512 513    if (ClassName.empty())514      return {};515 516    auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {517      SmallString<40> Mangled;518      auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());519      llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);520      return std::string(Mangled);521    };522 523    return {524        Mangle(ObjCClass, ClassName),525        Mangle(ObjCMetaclass, ClassName),526    };527  }528 529  std::vector<std::string> getAllManglings(const Decl *D) {530    if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))531      return getAllManglings(OCD);532 533    if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))534      return {};535 536    const NamedDecl *ND = cast<NamedDecl>(D);537 538    ASTContext &Ctx = ND->getASTContext();539    std::unique_ptr<MangleContext> M(Ctx.createMangleContext());540 541    std::vector<std::string> Manglings;542 543    auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {544      auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,545                                                     /*IsCXXMethod=*/true);546      auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv();547      return CC == DefaultCC;548    };549 550    if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {551      Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));552 553      if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())554        if (!CD->getParent()->isAbstract())555          Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));556 557      if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())558        if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())559          if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))560            Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));561    } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {562      Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));563      if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {564        Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));565        if (DD->isVirtual())566          Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));567      }568    } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {569      Manglings.emplace_back(getName(ND));570      if (MD->isVirtual()) {571        if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) {572          for (const auto &T : *TIV) {573            std::string ThunkName;574            std::string ContextualizedName =575                getMangledThunk(MD, T, /* ElideOverrideInfo */ false);576            if (Ctx.useAbbreviatedThunkName(MD, ContextualizedName))577              ThunkName = getMangledThunk(MD, T, /* ElideOverrideInfo */ true);578            else579              ThunkName = ContextualizedName;580            Manglings.emplace_back(ThunkName);581          }582        }583      }584    }585 586    return Manglings;587  }588 589private:590  bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {591    if (MC->shouldMangleDeclName(D)) {592      GlobalDecl GD;593      if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))594        GD = GlobalDecl(CtorD, Ctor_Complete);595      else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))596        GD = GlobalDecl(DtorD, Dtor_Complete);597      else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {598        GD = FD->isReferenceableKernel() ? GlobalDecl(FD) : GlobalDecl(D);599      } else600        GD = GlobalDecl(D);601      MC->mangleName(GD, OS);602      return false;603    } else {604      IdentifierInfo *II = D->getIdentifier();605      if (!II)606        return true;607      OS << II->getName();608      return false;609    }610  }611 612  void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {613    OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());614    OS << D->getObjCRuntimeNameAsString();615  }616 617  std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {618    std::string FrontendBuf;619    llvm::raw_string_ostream FOS(FrontendBuf);620 621    GlobalDecl GD;622    if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))623      GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));624    else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))625      GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));626    MC->mangleName(GD, FOS);627 628    std::string BackendBuf;629    llvm::raw_string_ostream BOS(BackendBuf);630 631    llvm::Mangler::getNameWithPrefix(BOS, FrontendBuf, DL);632 633    return BackendBuf;634  }635 636  std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T,637                              bool ElideOverrideInfo) {638    std::string FrontendBuf;639    llvm::raw_string_ostream FOS(FrontendBuf);640 641    MC->mangleThunk(MD, T, ElideOverrideInfo, FOS);642 643    std::string BackendBuf;644    llvm::raw_string_ostream BOS(BackendBuf);645 646    llvm::Mangler::getNameWithPrefix(BOS, FrontendBuf, DL);647 648    return BackendBuf;649  }650};651 652ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)653    : Impl(std::make_unique<Implementation>(Ctx)) {}654 655ASTNameGenerator::~ASTNameGenerator() {}656 657bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {658  return Impl->writeName(D, OS);659}660 661std::string ASTNameGenerator::getName(const Decl *D) {662  return Impl->getName(D);663}664 665std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {666  return Impl->getAllManglings(D);667}668