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