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
mangleFunctionBlock(MangleContext & Context,StringRef Outer,const BlockDecl * BD,raw_ostream & Out)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
anchor()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
isExternC(const NamedDecl * ND)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
getCallingConvMangling(const ASTContext & Context,const NamedDecl * ND)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
shouldMangleDeclName(const NamedDecl * D)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
mangleName(GlobalDecl GD,raw_ostream & Out)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
mangleMSGuidDecl(const MSGuidDecl * GD,raw_ostream & Out)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
mangleGlobalBlock(const BlockDecl * BD,const NamedDecl * ID,raw_ostream & Out)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
mangleCtorBlock(const CXXConstructorDecl * CD,CXXCtorType CT,const BlockDecl * BD,raw_ostream & ResStream)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
mangleDtorBlock(const CXXDestructorDecl * DD,CXXDtorType DT,const BlockDecl * BD,raw_ostream & ResStream)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
mangleBlock(const DeclContext * DC,const BlockDecl * BD,raw_ostream & Out)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
mangleObjCMethodName(const ObjCMethodDecl * MD,raw_ostream & OS,bool includePrefixByte,bool includeCategoryNamespace)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
mangleObjCMethodNameAsSourceName(const ObjCMethodDecl * MD,raw_ostream & Out)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:
Implementation(ASTContext & Ctx)393 explicit Implementation(ASTContext &Ctx)
394 : MC(Ctx.createMangleContext()),
395 DL(Ctx.getTargetInfo().getDataLayoutString()) {}
396
writeName(const Decl * D,raw_ostream & OS)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
getName(const Decl * D)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
getClassSymbolPrefix(ObjCKind Kind,const ASTContext & Context)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
getAllManglings(const ObjCContainerDecl * OCD)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
getAllManglings(const Decl * D)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:
writeFuncOrVarName(const NamedDecl * D,raw_ostream & OS)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
writeObjCClassName(const ObjCInterfaceDecl * D,raw_ostream & OS)541 void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
542 OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
543 OS << D->getObjCRuntimeNameAsString();
544 }
545
getMangledStructor(const NamedDecl * ND,unsigned StructorType)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
getMangledThunk(const CXXMethodDecl * MD,const ThunkInfo & T)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
ASTNameGenerator(ASTContext & Ctx)580 ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)
581 : Impl(std::make_unique<Implementation>(Ctx)) {}
582
~ASTNameGenerator()583 ASTNameGenerator::~ASTNameGenerator() {}
584
writeName(const Decl * D,raw_ostream & OS)585 bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
586 return Impl->writeName(D, OS);
587 }
588
getName(const Decl * D)589 std::string ASTNameGenerator::getName(const Decl *D) {
590 return Impl->getName(D);
591 }
592
getAllManglings(const Decl * D)593 std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {
594 return Impl->getAllManglings(D);
595 }
596