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