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