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/StmtVisitor.h"
21#include "clang/AST/VTableBuilder.h"
22#include "clang/Basic/ABI.h"
23#include "clang/Basic/Builtins.h"
24#include "clang/Basic/TargetInfo.h"
25#include "llvm/ADT/StringExtras.h"
26#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/Mangler.h"
28#include "llvm/Support/ErrorHandling.h"
29#include "llvm/Support/Format.h"
30#include "llvm/Support/raw_ostream.h"
31
32using namespace clang;
33
34void clang::mangleObjCMethodName(raw_ostream &OS, bool includePrefixByte,
35 bool isInstanceMethod, StringRef ClassName,
36 std::optional<StringRef> CategoryName,
37 StringRef MethodName, bool useDirectABI) {
38 assert(
39 !(includePrefixByte && useDirectABI) &&
40 "includePrefixByte and useDirectABI shouldn't be set at the same time");
41 // \01+[ContainerName(CategoryName) SelectorName]
42 // Or for direct ABI: +[ContainerName(CategoryName) SelectorName]D
43 if (includePrefixByte)
44 OS << "\01";
45 OS << (isInstanceMethod ? '-' : '+');
46 OS << '[';
47 OS << ClassName;
48 if (CategoryName)
49 OS << "(" << *CategoryName << ")";
50 OS << " ";
51 OS << MethodName;
52 OS << ']';
53 if (useDirectABI)
54 OS << 'D';
55}
56
57// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
58// much to be desired. Come up with a better mangling scheme.
59
60static void mangleFunctionBlock(MangleContext &Context,
61 StringRef Outer,
62 const BlockDecl *BD,
63 raw_ostream &Out) {
64 unsigned discriminator = Context.getBlockId(BD, Local: true);
65 if (discriminator == 0)
66 Out << "__" << Outer << "_block_invoke";
67 else
68 Out << "__" << Outer << "_block_invoke_" << discriminator+1;
69}
70
71void MangleContext::anchor() { }
72
73enum CCMangling {
74 CCM_Other,
75 CCM_Fast,
76 CCM_RegCall,
77 CCM_Vector,
78 CCM_Std,
79 CCM_WasmMainArgcArgv
80};
81
82static bool isExternC(const NamedDecl *ND) {
83 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: ND))
84 return FD->isExternC();
85 if (const VarDecl *VD = dyn_cast<VarDecl>(Val: ND))
86 return VD->isExternC();
87 return false;
88}
89
90static CCMangling getCallingConvMangling(const ASTContext &Context,
91 const NamedDecl *ND) {
92 const TargetInfo &TI = Context.getTargetInfo();
93 const llvm::Triple &Triple = TI.getTriple();
94
95 // On wasm, the argc/argv form of "main" is renamed so that the startup code
96 // can call it with the correct function signature.
97 if (Triple.isWasm())
98 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: ND))
99 if (FD->isMain() && FD->getNumParams() == 2)
100 return CCM_WasmMainArgcArgv;
101
102 if (!TI.shouldUseMicrosoftCCforMangling())
103 return CCM_Other;
104
105 if (Context.getLangOpts().CPlusPlus && !isExternC(ND) &&
106 TI.getCXXABI() == TargetCXXABI::Microsoft)
107 return CCM_Other;
108
109 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: ND);
110 if (!FD)
111 return CCM_Other;
112 QualType T = FD->getType();
113
114 const FunctionType *FT = T->castAs<FunctionType>();
115
116 CallingConv CC = FT->getCallConv();
117 switch (CC) {
118 default:
119 return CCM_Other;
120 case CC_X86FastCall:
121 return CCM_Fast;
122 case CC_X86StdCall:
123 return CCM_Std;
124 case CC_X86VectorCall:
125 return CCM_Vector;
126 }
127}
128
129bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
130 const ASTContext &ASTContext = getASTContext();
131
132 CCMangling CC = getCallingConvMangling(Context: ASTContext, ND: D);
133 if (CC != CCM_Other)
134 return true;
135
136 // If the declaration has an owning module for linkage purposes that needs to
137 // be mangled, we must mangle its name.
138 if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())
139 return true;
140
141 // C functions with internal linkage have to be mangled with option
142 // -funique-internal-linkage-names.
143 if (!getASTContext().getLangOpts().CPlusPlus &&
144 isUniqueInternalLinkageDecl(ND: D))
145 return true;
146
147 // In C, functions with no attributes never need to be mangled. Fastpath them.
148 if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
149 return false;
150
151 // Any decl can be declared with __asm("foo") on it, and this takes precedence
152 // over all other naming in the .o file.
153 if (D->hasAttr<AsmLabelAttr>())
154 return true;
155
156 // Declarations that don't have identifier names always need to be mangled.
157 if (isa<MSGuidDecl>(Val: D))
158 return true;
159
160 return shouldMangleCXXName(D);
161}
162
163namespace {
164// Visits a function body looking for a direct call back to the symbol the
165// function will link as. Detects both asm-label aliases and __builtin_*
166// wrappers (PR9614 / glibc btowc pattern).
167struct FunctionIsDirectlyRecursive
168 : public ConstStmtVisitor<FunctionIsDirectlyRecursive, bool> {
169 const StringRef Name;
170 const Builtin::Context &BI;
171 FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C)
172 : Name(N), BI(C) {}
173
174 bool VisitCallExpr(const CallExpr *E) {
175 const FunctionDecl *FD = E->getDirectCallee();
176 if (!FD)
177 return false;
178 AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
179 if (Attr && Name == Attr->getLabel())
180 return true;
181 unsigned BuiltinID = FD->getBuiltinID();
182 if (!BuiltinID || !BI.isLibFunction(ID: BuiltinID))
183 return false;
184 std::string BuiltinNameStr = BI.getName(ID: BuiltinID);
185 StringRef BuiltinName = BuiltinNameStr;
186 return BuiltinName.consume_front(Prefix: "__builtin_") && Name == BuiltinName;
187 }
188
189 bool VisitStmt(const Stmt *S) {
190 for (const Stmt *Child : S->children())
191 if (Child && this->Visit(S: Child))
192 return true;
193 return false;
194 }
195};
196} // namespace
197
198bool MangleContext::isTriviallyRecursive(const FunctionDecl *FD) {
199 StringRef Name;
200 if (shouldMangleDeclName(D: FD)) {
201 // C++-mangled functions can only recurse into themselves through an
202 // asm label that bypasses the mangled name.
203 AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
204 if (!Attr)
205 return false;
206 Name = Attr->getLabel();
207 } else {
208 Name = FD->getName();
209 }
210
211 FunctionIsDirectlyRecursive Walker(Name, FD->getASTContext().BuiltinInfo);
212 const Stmt *Body = FD->getBody();
213 return Body ? Walker.Visit(S: Body) : false;
214}
215
216/// Given an LLDB function call label, this function prints the label
217/// into \c Out, together with the structor type of \c GD (if the
218/// decl is a constructor/destructor). LLDB knows how to handle mangled
219/// names with this encoding.
220///
221/// Example input label:
222/// $__lldb_func::123:456:~Foo
223///
224/// Example output:
225/// $__lldb_func:D1:123:456:~Foo
226///
227static void emitLLDBAsmLabel(llvm::StringRef label, GlobalDecl GD,
228 llvm::raw_ostream &Out) {
229 assert(label.starts_with(LLDBManglingABI::FunctionLabelPrefix));
230
231 Out << LLDBManglingABI::FunctionLabelPrefix;
232
233 if (auto *Ctor = llvm::dyn_cast<clang::CXXConstructorDecl>(Val: GD.getDecl())) {
234 Out << "C";
235 if (Ctor->getInheritedConstructor().getConstructor())
236 Out << "I";
237 Out << GD.getCtorType();
238 } else if (llvm::isa<clang::CXXDestructorDecl>(Val: GD.getDecl())) {
239 Out << "D" << GD.getDtorType();
240 }
241
242 Out << label.substr(Start: LLDBManglingABI::FunctionLabelPrefix.size());
243}
244
245void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
246 const ASTContext &ASTContext = getASTContext();
247 const NamedDecl *D = cast<NamedDecl>(Val: GD.getDecl());
248
249 // Any decl can be declared with __asm("foo") on it, and this takes precedence
250 // over all other naming in the .o file.
251 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
252 // If we have an asm name, then we use it as the mangling.
253
254 // If the label is an alias for an LLVM intrinsic,
255 // do not add a "\01" prefix.
256 if (ALA->getLabel().starts_with(Prefix: "llvm.")) {
257 Out << ALA->getLabel();
258 return;
259 }
260
261 // Adding the prefix can cause problems when one file has a "foo" and
262 // another has a "\01foo". That is known to happen on ELF with the
263 // tricks normally used for producing aliases (PR9177). Fortunately the
264 // llvm mangler on ELF is a nop, so we can just avoid adding the \01
265 // marker.
266 StringRef UserLabelPrefix =
267 getASTContext().getTargetInfo().getUserLabelPrefix();
268#ifndef NDEBUG
269 char GlobalPrefix =
270 llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())
271 .getGlobalPrefix();
272 assert((UserLabelPrefix.empty() && !GlobalPrefix) ||
273 (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));
274#endif
275 if (!UserLabelPrefix.empty())
276 Out << '\01'; // LLVM IR Marker for __asm("foo")
277
278 if (ALA->getLabel().starts_with(Prefix: LLDBManglingABI::FunctionLabelPrefix))
279 emitLLDBAsmLabel(label: ALA->getLabel(), GD, Out);
280 else
281 Out << ALA->getLabel();
282
283 return;
284 }
285
286 if (auto *GD = dyn_cast<MSGuidDecl>(Val: D))
287 return mangleMSGuidDecl(GD, Out);
288
289 CCMangling CC = getCallingConvMangling(Context: ASTContext, ND: D);
290
291 if (CC == CCM_WasmMainArgcArgv) {
292 Out << "__main_argc_argv";
293 return;
294 }
295
296 bool MCXX = shouldMangleCXXName(D);
297 const TargetInfo &TI = Context.getTargetInfo();
298 if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
299 if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D))
300 mangleObjCMethodNameAsSourceName(MD: OMD, Out);
301 else
302 mangleCXXName(GD, Out);
303 return;
304 }
305
306 Out << '\01';
307 if (CC == CCM_Std)
308 Out << '_';
309 else if (CC == CCM_Fast)
310 Out << '@';
311 else if (CC == CCM_RegCall) {
312 if (getASTContext().getLangOpts().RegCall4)
313 Out << "__regcall4__";
314 else
315 Out << "__regcall3__";
316 }
317
318 if (!MCXX)
319 Out << D->getIdentifier()->getName();
320 else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D))
321 mangleObjCMethodNameAsSourceName(MD: OMD, Out);
322 else
323 mangleCXXName(GD, Out);
324
325 const FunctionDecl *FD = cast<FunctionDecl>(Val: D);
326 const FunctionType *FT = FD->getType()->castAs<FunctionType>();
327 const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Val: FT);
328 if (CC == CCM_Vector)
329 Out << '@';
330 Out << '@';
331 if (!Proto) {
332 Out << '0';
333 return;
334 }
335 assert(!Proto->isVariadic());
336 unsigned ArgWords = 0;
337 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Val: FD))
338 if (MD->isImplicitObjectMemberFunction())
339 ++ArgWords;
340 uint64_t DefaultPtrWidth = TI.getPointerWidth(AddrSpace: LangAS::Default);
341 for (const auto &AT : Proto->param_types()) {
342 // If an argument type is incomplete there is no way to get its size to
343 // correctly encode into the mangling scheme.
344 // Follow GCCs behaviour by simply breaking out of the loop.
345 if (AT->isIncompleteType())
346 break;
347 // Size should be aligned to pointer size.
348 ArgWords += llvm::alignTo(Value: ASTContext.getTypeSize(T: AT), Align: DefaultPtrWidth) /
349 DefaultPtrWidth;
350 }
351 Out << ((DefaultPtrWidth / 8) * ArgWords);
352}
353
354void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD,
355 raw_ostream &Out) const {
356 // For now, follow the MSVC naming convention for GUID objects on all
357 // targets.
358 MSGuidDecl::Parts P = GD->getParts();
359 Out << llvm::format(Fmt: "_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_",
360 Vals: P.Part1, Vals: P.Part2, Vals: P.Part3);
361 unsigned I = 0;
362 for (uint8_t C : P.Part4And5) {
363 Out << llvm::format(Fmt: "%02" PRIx8, Vals: C);
364 if (++I == 2)
365 Out << "_";
366 }
367}
368
369void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
370 const NamedDecl *ID,
371 raw_ostream &Out) {
372 unsigned discriminator = getBlockId(BD, Local: false);
373 if (ID) {
374 if (shouldMangleDeclName(D: ID))
375 mangleName(GD: ID, Out);
376 else {
377 Out << ID->getIdentifier()->getName();
378 }
379 }
380 if (discriminator == 0)
381 Out << "_block_invoke";
382 else
383 Out << "_block_invoke_" << discriminator+1;
384}
385
386void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
387 CXXCtorType CT, const BlockDecl *BD,
388 raw_ostream &ResStream) {
389 SmallString<64> Buffer;
390 llvm::raw_svector_ostream Out(Buffer);
391 mangleName(GD: GlobalDecl(CD, CT), Out);
392 mangleFunctionBlock(Context&: *this, Outer: Buffer, BD, Out&: ResStream);
393}
394
395void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
396 CXXDtorType DT, const BlockDecl *BD,
397 raw_ostream &ResStream) {
398 SmallString<64> Buffer;
399 llvm::raw_svector_ostream Out(Buffer);
400 mangleName(GD: GlobalDecl(DD, DT), Out);
401 mangleFunctionBlock(Context&: *this, Outer: Buffer, BD, Out&: ResStream);
402}
403
404void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
405 raw_ostream &Out) {
406 assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
407
408 SmallString<64> Buffer;
409 llvm::raw_svector_ostream Stream(Buffer);
410 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Val: DC)) {
411 mangleObjCMethodNameAsSourceName(MD: Method, Stream);
412 } else {
413 assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
414 "expected a NamedDecl or BlockDecl");
415 for (; isa_and_nonnull<BlockDecl>(Val: DC); DC = DC->getParent())
416 (void)getBlockId(BD: cast<BlockDecl>(Val: DC), Local: true);
417 assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
418 "expected a TranslationUnitDecl or a NamedDecl");
419 if (const auto *CD = dyn_cast<CXXConstructorDecl>(Val: DC))
420 mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, ResStream&: Out);
421 else if (const auto *DD = dyn_cast<CXXDestructorDecl>(Val: DC))
422 mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, ResStream&: Out);
423 else if (auto ND = dyn_cast<NamedDecl>(Val: DC)) {
424 if (!shouldMangleDeclName(D: ND) && ND->getIdentifier())
425 Stream << ND->getIdentifier()->getName();
426 else {
427 // FIXME: We were doing a mangleUnqualifiedName() before, but that's
428 // a private member of a class that will soon itself be private to the
429 // Itanium C++ ABI object. What should we do now? Right now, I'm just
430 // calling the mangleName() method on the MangleContext; is there a
431 // better way?
432 mangleName(GD: ND, Out&: Stream);
433 }
434 }
435 }
436 mangleFunctionBlock(Context&: *this, Outer: Buffer, BD, Out);
437}
438
439void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
440 raw_ostream &OS,
441 bool includePrefixByte,
442 bool includeCategoryNamespace,
443 bool useDirectABI) const {
444 if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) {
445 // This is the mangling we've always used on the GNU runtimes, but it
446 // has obvious collisions in the face of underscores within class
447 // names, category names, and selectors; maybe we should improve it.
448
449 OS << (MD->isClassMethod() ? "_c_" : "_i_")
450 << MD->getClassInterface()->getName() << '_';
451
452 if (includeCategoryNamespace) {
453 if (auto category = MD->getCategory())
454 OS << category->getName();
455 }
456 OS << '_';
457
458 auto selector = MD->getSelector();
459 for (unsigned slotIndex = 0,
460 numArgs = selector.getNumArgs(),
461 slotEnd = std::max(a: numArgs, b: 1U);
462 slotIndex != slotEnd; ++slotIndex) {
463 if (auto name = selector.getIdentifierInfoForSlot(argIndex: slotIndex))
464 OS << name->getName();
465
466 // Replace all the positions that would've been ':' with '_'.
467 // That's after each slot except that a unary selector doesn't
468 // end in ':'.
469 if (numArgs)
470 OS << '_';
471 }
472
473 return;
474 }
475
476 // \01+[ContainerName(CategoryName) SelectorName]
477 auto CategoryName = std::optional<StringRef>();
478 StringRef ClassName = "";
479 if (const auto *CID = MD->getCategory()) {
480 if (const auto *CI = CID->getClassInterface()) {
481 ClassName = CI->getName();
482 if (includeCategoryNamespace) {
483 CategoryName = CID->getName();
484 }
485 }
486 } else if (const auto *CD =
487 dyn_cast<ObjCContainerDecl>(Val: MD->getDeclContext())) {
488 ClassName = CD->getName();
489 } else {
490 llvm_unreachable("Unexpected ObjC method decl context");
491 }
492 std::string MethodName;
493 llvm::raw_string_ostream MethodNameOS(MethodName);
494 MD->getSelector().print(OS&: MethodNameOS);
495 // Normal methods always have internal linkage, and we prefix them with '\01'
496 // for reasons that are somewhat lost to time. We suppress this for direct
497 // methods because they have non-internal linkage and we don't want to make it
498 // unnecessarily difficult to refer to them, e.g. in things like export lists.
499 // Direct methods also have a distinct ABI, so we add a suffix to make them
500 // obvious to tools like debuggers and to elevate incompatible uses into
501 // linker errors.
502 clang::mangleObjCMethodName(OS, includePrefixByte: includePrefixByte && !useDirectABI,
503 isInstanceMethod: MD->isInstanceMethod(), ClassName, CategoryName,
504 MethodName, useDirectABI);
505}
506
507void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
508 raw_ostream &Out) const {
509 SmallString<64> Name;
510 llvm::raw_svector_ostream OS(Name);
511
512 mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
513 /*includeCategoryNamespace=*/true);
514 Out << OS.str().size() << OS.str();
515}
516
517class ASTNameGenerator::Implementation {
518 std::unique_ptr<MangleContext> MC;
519 llvm::DataLayout DL;
520
521public:
522 explicit Implementation(ASTContext &Ctx)
523 : MC(Ctx.createMangleContext()),
524 DL(Ctx.getTargetInfo().getDataLayoutString()) {}
525
526 bool writeName(const Decl *D, raw_ostream &OS) {
527 // First apply frontend mangling.
528 SmallString<128> FrontendBuf;
529 llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
530 if (auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
531 if (FD->isDependentContext())
532 return true;
533 if (writeFuncOrVarName(D: FD, OS&: FrontendBufOS))
534 return true;
535 } else if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
536 if (writeFuncOrVarName(D: VD, OS&: FrontendBufOS))
537 return true;
538 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(Val: D)) {
539 MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false,
540 /*includeCategoryNamespace=*/true);
541 return false;
542 } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(Val: D)) {
543 writeObjCClassName(D: ID, OS&: FrontendBufOS);
544 } else {
545 return true;
546 }
547
548 // Now apply backend mangling.
549 llvm::Mangler::getNameWithPrefix(OS, GVName: FrontendBufOS.str(), DL);
550 return false;
551 }
552
553 std::string getName(const Decl *D) {
554 std::string Name;
555 {
556 llvm::raw_string_ostream OS(Name);
557 writeName(D, OS);
558 }
559 return Name;
560 }
561
562 enum ObjCKind {
563 ObjCClass,
564 ObjCMetaclass,
565 };
566
567 static StringRef getClassSymbolPrefix(ObjCKind Kind,
568 const ASTContext &Context) {
569 if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
570 return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
571 return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
572 }
573
574 std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
575 StringRef ClassName;
576 if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(Val: OCD))
577 ClassName = OID->getObjCRuntimeNameAsString();
578 else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(Val: OCD))
579 ClassName = OID->getObjCRuntimeNameAsString();
580
581 if (ClassName.empty())
582 return {};
583
584 auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
585 SmallString<40> Mangled;
586 auto Prefix = getClassSymbolPrefix(Kind, Context: OCD->getASTContext());
587 llvm::Mangler::getNameWithPrefix(OutName&: Mangled, GVName: Prefix + ClassName, DL);
588 return std::string(Mangled);
589 };
590
591 return {
592 Mangle(ObjCClass, ClassName),
593 Mangle(ObjCMetaclass, ClassName),
594 };
595 }
596
597 std::vector<std::string> getAllManglings(const Decl *D) {
598 if (const auto *OCD = dyn_cast<ObjCContainerDecl>(Val: D))
599 return getAllManglings(OCD);
600
601 if (!(isa<CXXRecordDecl>(Val: D) || isa<CXXMethodDecl>(Val: D)))
602 return {};
603
604 const NamedDecl *ND = cast<NamedDecl>(Val: D);
605
606 ASTContext &Ctx = ND->getASTContext();
607 std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
608
609 std::vector<std::string> Manglings;
610
611 auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
612 auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
613 /*IsCXXMethod=*/true);
614 auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv();
615 return CC == DefaultCC;
616 };
617
618 if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Val: ND)) {
619 Manglings.emplace_back(args: getMangledStructor(ND: CD, StructorType: Ctor_Base));
620
621 if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
622 if (!CD->getParent()->isAbstract())
623 Manglings.emplace_back(args: getMangledStructor(ND: CD, StructorType: Ctor_Complete));
624
625 if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
626 if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
627 if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
628 Manglings.emplace_back(args: getMangledStructor(ND: CD, StructorType: Ctor_DefaultClosure));
629 } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(Val: ND)) {
630 Manglings.emplace_back(args: getMangledStructor(ND: DD, StructorType: Dtor_Base));
631 if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
632 Manglings.emplace_back(args: getMangledStructor(ND: DD, StructorType: Dtor_Complete));
633 if (DD->isVirtual())
634 Manglings.emplace_back(args: getMangledStructor(ND: DD, StructorType: Dtor_Deleting));
635 }
636 } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Val: ND)) {
637 Manglings.emplace_back(args: getName(D: ND));
638 if (MD->isVirtual()) {
639 if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(GD: MD)) {
640 for (const auto &T : *TIV) {
641 std::string ThunkName;
642 std::string ContextualizedName =
643 getMangledThunk(MD, T, /* ElideOverrideInfo */ false);
644 if (Ctx.useAbbreviatedThunkName(VirtualMethodDecl: MD, MangledName: ContextualizedName))
645 ThunkName = getMangledThunk(MD, T, /* ElideOverrideInfo */ true);
646 else
647 ThunkName = ContextualizedName;
648 Manglings.emplace_back(args&: ThunkName);
649 }
650 }
651 }
652 }
653
654 return Manglings;
655 }
656
657private:
658 bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
659 if (MC->shouldMangleDeclName(D)) {
660 GlobalDecl GD;
661 if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(Val: D))
662 GD = GlobalDecl(CtorD, Ctor_Complete);
663 else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(Val: D))
664 GD = GlobalDecl(DtorD, Dtor_Complete);
665 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) {
666 GD = FD->isReferenceableKernel() ? GlobalDecl(FD) : GlobalDecl(D);
667 } else
668 GD = GlobalDecl(D);
669 MC->mangleName(GD, Out&: OS);
670 return false;
671 } else {
672 IdentifierInfo *II = D->getIdentifier();
673 if (!II)
674 return true;
675 OS << II->getName();
676 return false;
677 }
678 }
679
680 void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
681 OS << getClassSymbolPrefix(Kind: ObjCClass, Context: D->getASTContext());
682 OS << D->getObjCRuntimeNameAsString();
683 }
684
685 std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
686 std::string FrontendBuf;
687 llvm::raw_string_ostream FOS(FrontendBuf);
688
689 GlobalDecl GD;
690 if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Val: ND))
691 GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
692 else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(Val: ND))
693 GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
694 MC->mangleName(GD, Out&: FOS);
695
696 std::string BackendBuf;
697 llvm::raw_string_ostream BOS(BackendBuf);
698
699 llvm::Mangler::getNameWithPrefix(OS&: BOS, GVName: FrontendBuf, DL);
700
701 return BackendBuf;
702 }
703
704 std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T,
705 bool ElideOverrideInfo) {
706 std::string FrontendBuf;
707 llvm::raw_string_ostream FOS(FrontendBuf);
708
709 MC->mangleThunk(MD, Thunk: T, ElideOverrideInfo, FOS);
710
711 std::string BackendBuf;
712 llvm::raw_string_ostream BOS(BackendBuf);
713
714 llvm::Mangler::getNameWithPrefix(OS&: BOS, GVName: FrontendBuf, DL);
715
716 return BackendBuf;
717 }
718};
719
720ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)
721 : Impl(std::make_unique<Implementation>(args&: Ctx)) {}
722
723ASTNameGenerator::~ASTNameGenerator() {}
724
725bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
726 return Impl->writeName(D, OS);
727}
728
729std::string ASTNameGenerator::getName(const Decl *D) {
730 return Impl->getName(D);
731}
732
733std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {
734 return Impl->getAllManglings(D);
735}
736