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