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