//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Implements C++ name mangling according to the Itanium C++ ABI, // which is used in GCC 3.2 and newer (and many compilers that are // ABI-compatible with GCC): // // http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/Mangle.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/ABI.h" #include "clang/Basic/DiagnosticAST.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Thunk.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/RISCVTargetParser.h" #include using namespace clang; namespace { static bool isLocalContainerContext(const DeclContext *DC) { return isa(DC) || isa(DC) || isa(DC); } static const FunctionDecl *getStructor(const FunctionDecl *fn) { if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) return ftd->getTemplatedDecl(); return fn; } static const NamedDecl *getStructor(const NamedDecl *decl) { const FunctionDecl *fn = dyn_cast_or_null(decl); return (fn ? getStructor(fn) : decl); } static bool isLambda(const NamedDecl *ND) { const CXXRecordDecl *Record = dyn_cast(ND); if (!Record) return false; return Record->isLambda(); } static const unsigned UnknownArity = ~0U; class ItaniumMangleContextImpl : public ItaniumMangleContext { typedef std::pair DiscriminatorKeyTy; llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; const DiscriminatorOverrideTy DiscriminatorOverride = nullptr; NamespaceDecl *StdNamespace = nullptr; bool NeedsUniqueInternalLinkageNames = false; public: explicit ItaniumMangleContextImpl( ASTContext &Context, DiagnosticsEngine &Diags, DiscriminatorOverrideTy DiscriminatorOverride, bool IsAux = false) : ItaniumMangleContext(Context, Diags, IsAux), DiscriminatorOverride(DiscriminatorOverride) {} /// @name Mangler Entry Points /// @{ bool shouldMangleCXXName(const NamedDecl *D) override; bool shouldMangleStringLiteral(const StringLiteral *) override { return false; } bool isUniqueInternalLinkageDecl(const NamedDecl *ND) override; void needsUniqueInternalLinkageNames() override { NeedsUniqueInternalLinkageNames = true; } void mangleCXXName(GlobalDecl GD, raw_ostream &) override; void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, bool, raw_ostream &) override; void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThunkInfo &Thunk, bool, raw_ostream &) override; void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber, raw_ostream &) override; void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override; void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) override; void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, const CXXRecordDecl *Type, raw_ostream &) override; void mangleCXXRTTI(QualType T, raw_ostream &) override; void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers) override; void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers) override; void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override; void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override; void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) override; void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override; void mangleDynamicAtExitDestructor(const VarDecl *D, raw_ostream &Out) override; void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &Out) override; void mangleSEHFilterExpression(GlobalDecl EnclosingDecl, raw_ostream &Out) override; void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl, raw_ostream &Out) override; void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override; void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &) override; void mangleStringLiteral(const StringLiteral *, raw_ostream &) override; void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override; void mangleModuleInitializer(const Module *Module, raw_ostream &) override; bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { // Lambda closure types are already numbered. if (isLambda(ND)) return false; // Anonymous tags are already numbered. if (const TagDecl *Tag = dyn_cast(ND)) { if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl()) return false; } // Use the canonical number for externally visible decls. if (ND->isExternallyVisible()) { unsigned discriminator = getASTContext().getManglingNumber(ND, isAux()); if (discriminator == 1) return false; disc = discriminator - 2; return true; } // Make up a reasonable number for internal decls. unsigned &discriminator = Uniquifier[ND]; if (!discriminator) { const DeclContext *DC = getEffectiveDeclContext(ND); discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; } if (discriminator == 1) return false; disc = discriminator-2; return true; } std::string getLambdaString(const CXXRecordDecl *Lambda) override { // This function matches the one in MicrosoftMangle, which returns // the string that is used in lambda mangled names. assert(Lambda->isLambda() && "RD must be a lambda!"); std::string Name("getLambdaContextDecl(); unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber(); unsigned LambdaId; const ParmVarDecl *Parm = dyn_cast_or_null(LambdaContextDecl); const FunctionDecl *Func = Parm ? dyn_cast(Parm->getDeclContext()) : nullptr; if (Func) { unsigned DefaultArgNo = Func->getNumParams() - Parm->getFunctionScopeIndex(); Name += llvm::utostr(DefaultArgNo); Name += "_"; } if (LambdaManglingNumber) LambdaId = LambdaManglingNumber; else LambdaId = getAnonymousStructIdForDebugInfo(Lambda); Name += llvm::utostr(LambdaId); Name += '>'; return Name; } DiscriminatorOverrideTy getDiscriminatorOverride() const override { return DiscriminatorOverride; } NamespaceDecl *getStdNamespace(); const DeclContext *getEffectiveDeclContext(const Decl *D); const DeclContext *getEffectiveParentContext(const DeclContext *DC) { return getEffectiveDeclContext(cast(DC)); } bool isInternalLinkageDecl(const NamedDecl *ND); /// @} }; /// Manage the mangling of a single name. class CXXNameMangler { ItaniumMangleContextImpl &Context; raw_ostream &Out; /// Normalize integer types for cross-language CFI support with other /// languages that can't represent and encode C/C++ integer types. bool NormalizeIntegers = false; bool NullOut = false; /// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated. /// This mode is used when mangler creates another mangler recursively to /// calculate ABI tags for the function return value or the variable type. /// Also it is required to avoid infinite recursion in some cases. bool DisableDerivedAbiTags = false; /// The "structor" is the top-level declaration being mangled, if /// that's not a template specialization; otherwise it's the pattern /// for that specialization. const NamedDecl *Structor; unsigned StructorType = 0; // An offset to add to all template parameter depths while mangling. Used // when mangling a template parameter list to see if it matches a template // template parameter exactly. unsigned TemplateDepthOffset = 0; /// The next substitution sequence number. unsigned SeqID = 0; class FunctionTypeDepthState { unsigned Bits = 0; enum { InResultTypeMask = 1 }; public: FunctionTypeDepthState() = default; /// The number of function types we're inside. unsigned getDepth() const { return Bits >> 1; } /// True if we're in the return type of the innermost function type. bool isInResultType() const { return Bits & InResultTypeMask; } FunctionTypeDepthState push() { FunctionTypeDepthState tmp = *this; Bits = (Bits & ~InResultTypeMask) + 2; return tmp; } void enterResultType() { Bits |= InResultTypeMask; } void leaveResultType() { Bits &= ~InResultTypeMask; } void pop(FunctionTypeDepthState saved) { assert(getDepth() == saved.getDepth() + 1); Bits = saved.Bits; } } FunctionTypeDepth; // abi_tag is a gcc attribute, taking one or more strings called "tags". // The goal is to annotate against which version of a library an object was // built and to be able to provide backwards compatibility ("dual abi"). // For more information see docs/ItaniumMangleAbiTags.rst. typedef SmallVector AbiTagList; // State to gather all implicit and explicit tags used in a mangled name. // Must always have an instance of this while emitting any name to keep // track. class AbiTagState final { public: explicit AbiTagState(AbiTagState *&Head) : LinkHead(Head) { Parent = LinkHead; LinkHead = this; } // No copy, no move. AbiTagState(const AbiTagState &) = delete; AbiTagState &operator=(const AbiTagState &) = delete; ~AbiTagState() { pop(); } void write(raw_ostream &Out, const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) { ND = cast(ND->getCanonicalDecl()); if (!isa(ND) && !isa(ND)) { assert( !AdditionalAbiTags && "only function and variables need a list of additional abi tags"); if (const auto *NS = dyn_cast(ND)) { if (const auto *AbiTag = NS->getAttr()) { UsedAbiTags.insert(UsedAbiTags.end(), AbiTag->tags().begin(), AbiTag->tags().end()); } // Don't emit abi tags for namespaces. return; } } AbiTagList TagList; if (const auto *AbiTag = ND->getAttr()) { UsedAbiTags.insert(UsedAbiTags.end(), AbiTag->tags().begin(), AbiTag->tags().end()); TagList.insert(TagList.end(), AbiTag->tags().begin(), AbiTag->tags().end()); } if (AdditionalAbiTags) { UsedAbiTags.insert(UsedAbiTags.end(), AdditionalAbiTags->begin(), AdditionalAbiTags->end()); TagList.insert(TagList.end(), AdditionalAbiTags->begin(), AdditionalAbiTags->end()); } llvm::sort(TagList); TagList.erase(std::unique(TagList.begin(), TagList.end()), TagList.end()); writeSortedUniqueAbiTags(Out, TagList); } const AbiTagList &getUsedAbiTags() const { return UsedAbiTags; } void setUsedAbiTags(const AbiTagList &AbiTags) { UsedAbiTags = AbiTags; } const AbiTagList &getEmittedAbiTags() const { return EmittedAbiTags; } const AbiTagList &getSortedUniqueUsedAbiTags() { llvm::sort(UsedAbiTags); UsedAbiTags.erase(std::unique(UsedAbiTags.begin(), UsedAbiTags.end()), UsedAbiTags.end()); return UsedAbiTags; } private: //! All abi tags used implicitly or explicitly. AbiTagList UsedAbiTags; //! All explicit abi tags (i.e. not from namespace). AbiTagList EmittedAbiTags; AbiTagState *&LinkHead; AbiTagState *Parent = nullptr; void pop() { assert(LinkHead == this && "abi tag link head must point to us on destruction"); if (Parent) { Parent->UsedAbiTags.insert(Parent->UsedAbiTags.end(), UsedAbiTags.begin(), UsedAbiTags.end()); Parent->EmittedAbiTags.insert(Parent->EmittedAbiTags.end(), EmittedAbiTags.begin(), EmittedAbiTags.end()); } LinkHead = Parent; } void writeSortedUniqueAbiTags(raw_ostream &Out, const AbiTagList &AbiTags) { for (const auto &Tag : AbiTags) { EmittedAbiTags.push_back(Tag); Out << "B"; Out << Tag.size(); Out << Tag; } } }; AbiTagState *AbiTags = nullptr; AbiTagState AbiTagsRoot; llvm::DenseMap Substitutions; llvm::DenseMap ModuleSubstitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } bool isCompatibleWith(LangOptions::ClangABI Ver) { return Context.getASTContext().getLangOpts().getClangABICompat() <= Ver; } bool isStd(const NamespaceDecl *NS); bool isStdNamespace(const DeclContext *DC); const RecordDecl *GetLocalClassDecl(const Decl *D); bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A); bool isStdCharSpecialization(const ClassTemplateSpecializationDecl *SD, llvm::StringRef Name, bool HasAllocator); public: CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const NamedDecl *D = nullptr, bool NullOut_ = false) : Context(C), Out(Out_), NullOut(NullOut_), Structor(getStructor(D)), AbiTagsRoot(AbiTags) { // These can't be mangled without a ctor type or dtor type. assert(!D || (!isa(D) && !isa(D))); } CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXConstructorDecl *D, CXXCtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), AbiTagsRoot(AbiTags) {} CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, const CXXDestructorDecl *D, CXXDtorType Type) : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), AbiTagsRoot(AbiTags) {} CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_, bool NormalizeIntegers_) : Context(C), Out(Out_), NormalizeIntegers(NormalizeIntegers_), NullOut(false), Structor(nullptr), AbiTagsRoot(AbiTags) {} CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_) : Context(Outer.Context), Out(Out_), Structor(Outer.Structor), StructorType(Outer.StructorType), SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth), AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions), ModuleSubstitutions(Outer.ModuleSubstitutions) {} CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_) : CXXNameMangler(Outer, (raw_ostream &)Out_) { NullOut = true; } struct WithTemplateDepthOffset { unsigned Offset; }; CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out, WithTemplateDepthOffset Offset) : CXXNameMangler(C, Out) { TemplateDepthOffset = Offset.Offset; } raw_ostream &getStream() { return Out; } void disableDerivedAbiTags() { DisableDerivedAbiTags = true; } static bool shouldHaveAbiTags(ItaniumMangleContextImpl &C, const VarDecl *VD); void mangle(GlobalDecl GD); void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); void mangleNumber(const llvm::APSInt &I); void mangleNumber(int64_t Number); void mangleFloat(const llvm::APFloat &F); void mangleFunctionEncoding(GlobalDecl GD); void mangleSeqID(unsigned SeqID); void mangleName(GlobalDecl GD); void mangleType(QualType T); void mangleNameOrStandardSubstitution(const NamedDecl *ND); void mangleLambdaSig(const CXXRecordDecl *Lambda); void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false); void mangleVendorQualifier(StringRef Name); private: bool mangleSubstitution(const NamedDecl *ND); bool mangleSubstitution(NestedNameSpecifier *NNS); bool mangleSubstitution(QualType T); bool mangleSubstitution(TemplateName Template); bool mangleSubstitution(uintptr_t Ptr); void mangleExistingSubstitution(TemplateName name); bool mangleStandardSubstitution(const NamedDecl *ND); void addSubstitution(const NamedDecl *ND) { ND = cast(ND->getCanonicalDecl()); addSubstitution(reinterpret_cast(ND)); } void addSubstitution(NestedNameSpecifier *NNS) { NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); addSubstitution(reinterpret_cast(NNS)); } void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); // Destructive copy substitutions from other mangler. void extendSubstitutions(CXXNameMangler* Other); void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, bool recursive = false); void mangleUnresolvedName(NestedNameSpecifier *qualifier, DeclarationName name, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, unsigned KnownArity = UnknownArity); void mangleFunctionEncodingBareType(const FunctionDecl *FD); void mangleNameWithAbiTags(GlobalDecl GD, const AbiTagList *AdditionalAbiTags); void mangleModuleName(const NamedDecl *ND); void mangleTemplateName(const TemplateDecl *TD, ArrayRef Args); void mangleUnqualifiedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName(), DC, UnknownArity, AdditionalAbiTags); } void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name, const DeclContext *DC, unsigned KnownArity, const AbiTagList *AdditionalAbiTags); void mangleUnscopedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); void mangleUnscopedTemplateName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); void mangleSourceName(const IdentifierInfo *II); void mangleRegCallName(const IdentifierInfo *II); void mangleDeviceStubName(const IdentifierInfo *II); void mangleSourceNameWithAbiTags( const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr); void mangleLocalName(GlobalDecl GD, const AbiTagList *AdditionalAbiTags); void mangleBlockForPrefix(const BlockDecl *Block); void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleTemplateParamDecl(const NamedDecl *Decl); void mangleTemplateParameterList(const TemplateParameterList *Params); void mangleTypeConstraint(const ConceptDecl *Concept, ArrayRef Arguments); void mangleTypeConstraint(const TypeConstraint *Constraint); void mangleRequiresClause(const Expr *RequiresClause); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags, bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, ArrayRef Args); void mangleNestedNameWithClosurePrefix(GlobalDecl GD, const NamedDecl *PrefixND, const AbiTagList *AdditionalAbiTags); void manglePrefix(NestedNameSpecifier *qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); void manglePrefix(QualType type); void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false); void mangleTemplatePrefix(TemplateName Template); const NamedDecl *getClosurePrefix(const Decl *ND); void mangleClosurePrefix(const NamedDecl *ND, bool NoFunction = false); bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType, StringRef Prefix = ""); void mangleOperatorName(DeclarationName Name, unsigned Arity); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr); void mangleRefQualifier(RefQualifierKind RefQualifier); void mangleObjCMethodName(const ObjCMethodDecl *MD); // Declare manglers for every type class. #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T); #include "clang/AST/TypeNodes.inc" void mangleType(const TagType*); void mangleType(TemplateName); static StringRef getCallingConvQualifierName(CallingConv CC); void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info); void mangleExtFunctionInfo(const FunctionType *T); void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType, const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); void mangleNeonVectorType(const DependentVectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); void mangleAArch64NeonVectorType(const DependentVectorType *T); void mangleAArch64FixedSveVectorType(const VectorType *T); void mangleAArch64FixedSveVectorType(const DependentVectorType *T); void mangleRISCVFixedRVVVectorType(const VectorType *T); void mangleRISCVFixedRVVVectorType(const DependentVectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleFloatLiteral(QualType T, const llvm::APFloat &V); void mangleFixedPointLiteral(); void mangleNullPointer(QualType T); void mangleMemberExprBase(const Expr *base, bool isArrow); void mangleMemberExpr(const Expr *base, bool isArrow, NestedNameSpecifier *qualifier, NamedDecl *firstQualifierLookup, DeclarationName name, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); void mangleRequirement(SourceLocation RequiresExprLoc, const concepts::Requirement *Req); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity, bool AsTemplateArg = false); void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); void mangleCXXDtorType(CXXDtorType T); struct TemplateArgManglingInfo; void mangleTemplateArgs(TemplateName TN, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs); void mangleTemplateArgs(TemplateName TN, ArrayRef Args); void mangleTemplateArgs(TemplateName TN, const TemplateArgumentList &AL); void mangleTemplateArg(TemplateArgManglingInfo &Info, unsigned Index, TemplateArgument A); void mangleTemplateArg(TemplateArgument A, bool NeedExactType); void mangleTemplateArgExpr(const Expr *E); void mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel, bool NeedExactType = false); void mangleTemplateParameter(unsigned Depth, unsigned Index); void mangleFunctionParam(const ParmVarDecl *parm); void writeAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags); // Returns sorted unique list of ABI tags. AbiTagList makeFunctionReturnTypeTags(const FunctionDecl *FD); // Returns sorted unique list of ABI tags. AbiTagList makeVariableTypeTags(const VarDecl *VD); }; } NamespaceDecl *ItaniumMangleContextImpl::getStdNamespace() { if (!StdNamespace) { StdNamespace = NamespaceDecl::Create( getASTContext(), getASTContext().getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(), SourceLocation(), &getASTContext().Idents.get("std"), /*PrevDecl=*/nullptr, /*Nested=*/false); StdNamespace->setImplicit(); } return StdNamespace; } /// Retrieve the declaration context that should be used when mangling the given /// declaration. const DeclContext * ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { // The ABI assumes that lambda closure types that occur within // default arguments live in the context of the function. However, due to // the way in which Clang parses and creates function declarations, this is // not the case: the lambda closure type ends up living in the context // where the function itself resides, because the function declaration itself // had not yet been created. Fix the context here. if (const CXXRecordDecl *RD = dyn_cast(D)) { if (RD->isLambda()) if (ParmVarDecl *ContextParam = dyn_cast_or_null(RD->getLambdaContextDecl())) return ContextParam->getDeclContext(); } // Perform the same check for block literals. if (const BlockDecl *BD = dyn_cast(D)) { if (ParmVarDecl *ContextParam = dyn_cast_or_null(BD->getBlockManglingContextDecl())) return ContextParam->getDeclContext(); } // On ARM and AArch64, the va_list tag is always mangled as if in the std // namespace. We do not represent va_list as actually being in the std // namespace in C because this would result in incorrect debug info in C, // among other things. It is important for both languages to have the same // mangling in order for -fsanitize=cfi-icall to work. if (D == getASTContext().getVaListTagDecl()) { const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); if (T.isARM() || T.isThumb() || T.isAArch64()) return getStdNamespace(); } const DeclContext *DC = D->getDeclContext(); if (isa(DC) || isa(DC) || isa(DC)) { return getEffectiveDeclContext(cast(DC)); } if (const auto *VD = dyn_cast(D)) if (VD->isExternC()) return getASTContext().getTranslationUnitDecl(); if (const auto *FD = dyn_cast(D)) { if (FD->isExternC()) return getASTContext().getTranslationUnitDecl(); // Member-like constrained friends are mangled as if they were members of // the enclosing class. if (FD->isMemberLikeConstrainedFriend() && getASTContext().getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver17) return D->getLexicalDeclContext()->getRedeclContext(); } return DC->getRedeclContext(); } bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) { if (ND && ND->getFormalLinkage() == Linkage::Internal && !ND->isExternallyVisible() && getEffectiveDeclContext(ND)->isFileContext() && !ND->isInAnonymousNamespace()) return true; return false; } // Check if this Function Decl needs a unique internal linkage name. bool ItaniumMangleContextImpl::isUniqueInternalLinkageDecl( const NamedDecl *ND) { if (!NeedsUniqueInternalLinkageNames || !ND) return false; const auto *FD = dyn_cast(ND); if (!FD) return false; // For C functions without prototypes, return false as their // names should not be mangled. if (!FD->getType()->getAs()) return false; if (isInternalLinkageDecl(ND)) return true; return false; } bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { if (const auto *FD = dyn_cast(D)) { LanguageLinkage L = FD->getLanguageLinkage(); // Overloadable functions need mangling. if (FD->hasAttr()) return true; // "main" is not mangled. if (FD->isMain()) return false; // The Windows ABI expects that we would never mangle "typical" // user-defined entry points regardless of visibility or freestanding-ness. // // N.B. This is distinct from asking about "main". "main" has a lot of // special rules associated with it in the standard while these // user-defined entry points are outside of the purview of the standard. // For example, there can be only one definition for "main" in a standards // compliant program; however nothing forbids the existence of wmain and // WinMain in the same translation unit. if (FD->isMSVCRTEntryPoint()) return false; // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) return true; // C functions are not mangled. if (L == CLanguageLinkage) return false; } // Otherwise, no mangling is done outside C++ mode. if (!getASTContext().getLangOpts().CPlusPlus) return false; if (const auto *VD = dyn_cast(D)) { // Decompositions are mangled. if (isa(VD)) return true; // C variables are not mangled. if (VD->isExternC()) return false; // Variables at global scope are not mangled unless they have internal // linkage or are specializations or are attached to a named module. const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) while (!DC->isFileContext()) DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getFormalLinkage() != Linkage::Internal && !CXXNameMangler::shouldHaveAbiTags(*this, VD) && !isa(VD) && !VD->getOwningModuleForLinkage()) return false; } return true; } void CXXNameMangler::writeAbiTags(const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) { assert(AbiTags && "require AbiTagState"); AbiTags->write(Out, ND, DisableDerivedAbiTags ? nullptr : AdditionalAbiTags); } void CXXNameMangler::mangleSourceNameWithAbiTags( const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) { mangleSourceName(ND->getIdentifier()); writeAbiTags(ND, AdditionalAbiTags); } void CXXNameMangler::mangle(GlobalDecl GD) { // ::= _Z // ::= // ::= Out << "_Z"; if (isa(GD.getDecl())) mangleFunctionEncoding(GD); else if (isa(GD.getDecl())) mangleName(GD); else if (const IndirectFieldDecl *IFD = dyn_cast(GD.getDecl())) mangleName(IFD->getAnonField()); else llvm_unreachable("unexpected kind of global decl"); } void CXXNameMangler::mangleFunctionEncoding(GlobalDecl GD) { const FunctionDecl *FD = cast(GD.getDecl()); // ::= // Don't mangle in the type if this isn't a decl we should typically mangle. if (!Context.shouldMangleDeclName(FD)) { mangleName(GD); return; } AbiTagList ReturnTypeAbiTags = makeFunctionReturnTypeTags(FD); if (ReturnTypeAbiTags.empty()) { // There are no tags for return type, the simplest case. Enter the function // parameter scope before mangling the name, because a template using // constrained `auto` can have references to its parameters within its // template argument list: // // template void f(T x, C auto) // ... is mangled as ... // template U> void f(T, U) FunctionTypeDepthState Saved = FunctionTypeDepth.push(); mangleName(GD); FunctionTypeDepth.pop(Saved); mangleFunctionEncodingBareType(FD); return; } // Mangle function name and encoding to temporary buffer. // We have to output name and encoding to the same mangler to get the same // substitution as it will be in final mangling. SmallString<256> FunctionEncodingBuf; llvm::raw_svector_ostream FunctionEncodingStream(FunctionEncodingBuf); CXXNameMangler FunctionEncodingMangler(*this, FunctionEncodingStream); // Output name of the function. FunctionEncodingMangler.disableDerivedAbiTags(); FunctionTypeDepthState Saved = FunctionTypeDepth.push(); FunctionEncodingMangler.mangleNameWithAbiTags(FD, nullptr); FunctionTypeDepth.pop(Saved); // Remember length of the function name in the buffer. size_t EncodingPositionStart = FunctionEncodingStream.str().size(); FunctionEncodingMangler.mangleFunctionEncodingBareType(FD); // Get tags from return type that are not present in function name or // encoding. const AbiTagList &UsedAbiTags = FunctionEncodingMangler.AbiTagsRoot.getSortedUniqueUsedAbiTags(); AbiTagList AdditionalAbiTags(ReturnTypeAbiTags.size()); AdditionalAbiTags.erase( std::set_difference(ReturnTypeAbiTags.begin(), ReturnTypeAbiTags.end(), UsedAbiTags.begin(), UsedAbiTags.end(), AdditionalAbiTags.begin()), AdditionalAbiTags.end()); // Output name with implicit tags and function encoding from temporary buffer. Saved = FunctionTypeDepth.push(); mangleNameWithAbiTags(FD, &AdditionalAbiTags); FunctionTypeDepth.pop(Saved); Out << FunctionEncodingStream.str().substr(EncodingPositionStart); // Function encoding could create new substitutions so we have to add // temp mangled substitutions to main mangler. extendSubstitutions(&FunctionEncodingMangler); } void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { if (FD->hasAttr()) { FunctionTypeDepthState Saved = FunctionTypeDepth.push(); Out << "Ua9enable_ifI"; for (AttrVec::const_iterator I = FD->getAttrs().begin(), E = FD->getAttrs().end(); I != E; ++I) { EnableIfAttr *EIA = dyn_cast(*I); if (!EIA) continue; if (isCompatibleWith(LangOptions::ClangABI::Ver11)) { // Prior to Clang 12, we hardcoded the X/E around enable-if's argument, // even though should not include an X/E around // . Out << 'X'; mangleExpression(EIA->getCond()); Out << 'E'; } else { mangleTemplateArgExpr(EIA->getCond()); } } Out << 'E'; FunctionTypeDepth.pop(Saved); } // When mangling an inheriting constructor, the bare function type used is // that of the inherited constructor. if (auto *CD = dyn_cast(FD)) if (auto Inherited = CD->getInheritedConstructor()) FD = Inherited.getConstructor(); // Whether the mangling of a function type includes the return type depends on // the context and the nature of the function. The rules for deciding whether // the return type is included are: // // 1. Template functions (names or types) have return types encoded, with // the exceptions listed below. // 2. Function types not appearing as part of a function name mangling, // e.g. parameters, pointer types, etc., have return type encoded, with the // exceptions listed below. // 3. Non-template function names do not have return types encoded. // // The exceptions mentioned in (1) and (2) above, for which the return type is // never included, are // 1. Constructors. // 2. Destructors. // 3. Conversion operator functions, e.g. operator int. bool MangleReturnType = false; if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) { if (!(isa(FD) || isa(FD) || isa(FD))) MangleReturnType = true; // Mangle the type of the primary template. FD = PrimaryTemplate->getTemplatedDecl(); } mangleBareFunctionType(FD->getType()->castAs(), MangleReturnType, FD); } /// Return whether a given namespace is the 'std' namespace. bool CXXNameMangler::isStd(const NamespaceDecl *NS) { if (!Context.getEffectiveParentContext(NS)->isTranslationUnit()) return false; const IdentifierInfo *II = NS->getFirstDecl()->getIdentifier(); return II && II->isStr("std"); } // isStdNamespace - Return whether a given decl context is a toplevel 'std' // namespace. bool CXXNameMangler::isStdNamespace(const DeclContext *DC) { if (!DC->isNamespace()) return false; return isStd(cast(DC)); } static const GlobalDecl isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) { const NamedDecl *ND = cast(GD.getDecl()); // Check if we have a function template. if (const FunctionDecl *FD = dyn_cast(ND)) { if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { TemplateArgs = FD->getTemplateSpecializationArgs(); return GD.getWithDecl(TD); } } // Check if we have a class template. if (const ClassTemplateSpecializationDecl *Spec = dyn_cast(ND)) { TemplateArgs = &Spec->getTemplateArgs(); return GD.getWithDecl(Spec->getSpecializedTemplate()); } // Check if we have a variable template. if (const VarTemplateSpecializationDecl *Spec = dyn_cast(ND)) { TemplateArgs = &Spec->getTemplateArgs(); return GD.getWithDecl(Spec->getSpecializedTemplate()); } return GlobalDecl(); } static TemplateName asTemplateName(GlobalDecl GD) { const TemplateDecl *TD = dyn_cast_or_null(GD.getDecl()); return TemplateName(const_cast(TD)); } void CXXNameMangler::mangleName(GlobalDecl GD) { const NamedDecl *ND = cast(GD.getDecl()); if (const VarDecl *VD = dyn_cast(ND)) { // Variables should have implicit tags from its type. AbiTagList VariableTypeAbiTags = makeVariableTypeTags(VD); if (VariableTypeAbiTags.empty()) { // Simple case no variable type tags. mangleNameWithAbiTags(VD, nullptr); return; } // Mangle variable name to null stream to collect tags. llvm::raw_null_ostream NullOutStream; CXXNameMangler VariableNameMangler(*this, NullOutStream); VariableNameMangler.disableDerivedAbiTags(); VariableNameMangler.mangleNameWithAbiTags(VD, nullptr); // Get tags from variable type that are not present in its name. const AbiTagList &UsedAbiTags = VariableNameMangler.AbiTagsRoot.getSortedUniqueUsedAbiTags(); AbiTagList AdditionalAbiTags(VariableTypeAbiTags.size()); AdditionalAbiTags.erase( std::set_difference(VariableTypeAbiTags.begin(), VariableTypeAbiTags.end(), UsedAbiTags.begin(), UsedAbiTags.end(), AdditionalAbiTags.begin()), AdditionalAbiTags.end()); // Output name with implicit tags. mangleNameWithAbiTags(VD, &AdditionalAbiTags); } else { mangleNameWithAbiTags(GD, nullptr); } } const RecordDecl *CXXNameMangler::GetLocalClassDecl(const Decl *D) { const DeclContext *DC = Context.getEffectiveDeclContext(D); while (!DC->isNamespace() && !DC->isTranslationUnit()) { if (isLocalContainerContext(DC)) return dyn_cast(D); D = cast(DC); DC = Context.getEffectiveDeclContext(D); } return nullptr; } void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, const AbiTagList *AdditionalAbiTags) { const NamedDecl *ND = cast(GD.getDecl()); // ::= [] // ::= [] // ::= [] // ::= // const DeclContext *DC = Context.getEffectiveDeclContext(ND); bool IsLambda = isLambda(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. // FIXME: This is a hack; extern variables declared locally should have // a proper semantic declaration context! if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = Context.getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND) && (!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) { mangleLocalName(GD, AdditionalAbiTags); return; } assert(!isa(DC) && "context cannot be LinkageSpecDecl"); // Closures can require a nested-name mangling even if they're semantically // in the global namespace. if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags); return; } if (isLocalContainerContext(DC)) { mangleLocalName(GD, AdditionalAbiTags); return; } if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) { mangleUnscopedTemplateName(TD, DC, AdditionalAbiTags); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); return; } mangleUnscopedName(GD, DC, AdditionalAbiTags); return; } mangleNestedName(GD, DC, AdditionalAbiTags); } void CXXNameMangler::mangleModuleName(const NamedDecl *ND) { if (ND->isExternallyVisible()) if (Module *M = ND->getOwningModuleForLinkage()) mangleModuleNamePrefix(M->getPrimaryModuleInterfaceName()); } // ::= // ::= // ::= // ::= W // ::= W P void CXXNameMangler::mangleModuleNamePrefix(StringRef Name, bool IsPartition) { // ::= S _ auto It = ModuleSubstitutions.find(Name); if (It != ModuleSubstitutions.end()) { Out << 'S'; mangleSeqID(It->second); return; } // FIXME: Preserve hierarchy in module names rather than flattening // them to strings; use Module*s as substitution keys. auto Parts = Name.rsplit('.'); if (Parts.second.empty()) Parts.second = Parts.first; else { mangleModuleNamePrefix(Parts.first, IsPartition); IsPartition = false; } Out << 'W'; if (IsPartition) Out << 'P'; Out << Parts.second.size() << Parts.second; ModuleSubstitutions.insert({Name, SeqID++}); } void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, ArrayRef Args) { const DeclContext *DC = Context.getEffectiveDeclContext(TD); if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD, DC, nullptr); mangleTemplateArgs(asTemplateName(TD), Args); } else { mangleNestedName(TD, Args); } } void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { // ::= // ::= St # ::std:: assert(!isa(DC) && "unskipped LinkageSpecDecl"); if (isStdNamespace(DC)) Out << "St"; mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } void CXXNameMangler::mangleUnscopedTemplateName( GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags) { const TemplateDecl *ND = cast(GD.getDecl()); // ::= // ::= if (mangleSubstitution(ND)) return; // ::= if (const auto *TTP = dyn_cast(ND)) { assert(!AdditionalAbiTags && "template template param cannot have abi tags"); mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else if (isa(ND) || isa(ND)) { mangleUnscopedName(GD, DC, AdditionalAbiTags); } else { mangleUnscopedName(GD.getWithDecl(ND->getTemplatedDecl()), DC, AdditionalAbiTags); } addSubstitution(ND); } void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { // ABI: // Floating-point literals are encoded using a fixed-length // lowercase hexadecimal string corresponding to the internal // representation (IEEE on Itanium), high-order bytes first, // without leading zeroes. For example: "Lf bf800000 E" is -1.0f // on Itanium. // The 'without leading zeroes' thing seems to be an editorial // mistake; see the discussion on cxx-abi-dev beginning on // 2012-01-16. // Our requirements here are just barely weird enough to justify // using a custom algorithm instead of post-processing APInt::toString(). llvm::APInt valueBits = f.bitcastToAPInt(); unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4; assert(numCharacters != 0); // Allocate a buffer of the right number of characters. SmallVector buffer(numCharacters); // Fill the buffer left-to-right. for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) { // The bit-index of the next hex digit. unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1); // Project out 4 bits starting at 'digitIndex'. uint64_t hexDigit = valueBits.getRawData()[digitBitIndex / 64]; hexDigit >>= (digitBitIndex % 64); hexDigit &= 0xF; // Map that over to a lowercase hex digit. static const char charForHex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; buffer[stringIndex] = charForHex[hexDigit]; } Out.write(buffer.data(), numCharacters); } void CXXNameMangler::mangleFloatLiteral(QualType T, const llvm::APFloat &V) { Out << 'L'; mangleType(T); mangleFloat(V); Out << 'E'; } void CXXNameMangler::mangleFixedPointLiteral() { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( DiagnosticsEngine::Error, "cannot mangle fixed point literals yet"); Diags.Report(DiagID); } void CXXNameMangler::mangleNullPointer(QualType T) { // ::= L 0 E Out << 'L'; mangleType(T); Out << "0E"; } void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) { if (Value.isSigned() && Value.isNegative()) { Out << 'n'; Value.abs().print(Out, /*signed*/ false); } else { Value.print(Out, /*signed*/ false); } } void CXXNameMangler::mangleNumber(int64_t Number) { // ::= [n] if (Number < 0) { Out << 'n'; Number = -Number; } Out << Number; } void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { // ::= h _ // ::= v _ // ::= # non-virtual base override // ::= _ // # virtual base override, with vcall offset if (!Virtual) { Out << 'h'; mangleNumber(NonVirtual); Out << '_'; return; } Out << 'v'; mangleNumber(NonVirtual); Out << '_'; mangleNumber(Virtual); Out << '_'; } void CXXNameMangler::manglePrefix(QualType type) { if (const auto *TST = type->getAs()) { if (!mangleSubstitution(QualType(TST, 0))) { mangleTemplatePrefix(TST->getTemplateName()); // FIXME: GCC does not appear to mangle the template arguments when // the template in question is a dependent template name. Should we // emulate that badness? mangleTemplateArgs(TST->getTemplateName(), TST->template_arguments()); addSubstitution(QualType(TST, 0)); } } else if (const auto *DTST = type->getAs()) { if (!mangleSubstitution(QualType(DTST, 0))) { TemplateName Template = getASTContext().getDependentTemplateName( DTST->getQualifier(), DTST->getIdentifier()); mangleTemplatePrefix(Template); // FIXME: GCC does not appear to mangle the template arguments when // the template in question is a dependent template name. Should we // emulate that badness? mangleTemplateArgs(Template, DTST->template_arguments()); addSubstitution(QualType(DTST, 0)); } } else { // We use the QualType mangle type variant here because it handles // substitutions. mangleType(type); } } /// Mangle everything prior to the base-unresolved-name in an unresolved-name. /// /// \param recursive - true if this is being called recursively, /// i.e. if there is more prefix "to the right". void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, bool recursive) { // x, ::x // ::= [gs] // T::x / decltype(p)::x // ::= sr // T::N::x /decltype(p)::N::x // ::= srN + E // // A::x, N::y, A::z; "gs" means leading "::" // ::= [gs] sr + E // switch (qualifier->getKind()) { case NestedNameSpecifier::Global: Out << "gs"; // We want an 'sr' unless this is the entire NNS. if (recursive) Out << "sr"; // We never want an 'E' here. return; case NestedNameSpecifier::Super: llvm_unreachable("Can't mangle __super specifier"); case NestedNameSpecifier::Namespace: if (qualifier->getPrefix()) mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); else Out << "sr"; mangleSourceNameWithAbiTags(qualifier->getAsNamespace()); break; case NestedNameSpecifier::NamespaceAlias: if (qualifier->getPrefix()) mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); else Out << "sr"; mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *type = qualifier->getAsType(); // We only want to use an unresolved-type encoding if this is one of: // - a decltype // - a template type parameter // - a template template parameter with arguments // In all of these cases, we should have no prefix. if (qualifier->getPrefix()) { mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); } else { // Otherwise, all the cases want this. Out << "sr"; } if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N" : "")) return; break; } case NestedNameSpecifier::Identifier: // Member expressions can have these without prefixes. if (qualifier->getPrefix()) mangleUnresolvedPrefix(qualifier->getPrefix(), /*recursive*/ true); else Out << "sr"; mangleSourceName(qualifier->getAsIdentifier()); // An Identifier has no type information, so we can't emit abi tags for it. break; } // If this was the innermost part of the NNS, and we fell out to // here, append an 'E'. if (!recursive) Out << 'E'; } /// Mangle an unresolved-name, which is generally used for names which /// weren't resolved to specific entities. void CXXNameMangler::mangleUnresolvedName( NestedNameSpecifier *qualifier, DeclarationName name, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, unsigned knownArity) { if (qualifier) mangleUnresolvedPrefix(qualifier); switch (name.getNameKind()) { // ::= case DeclarationName::Identifier: mangleSourceName(name.getAsIdentifierInfo()); break; // ::= dn case DeclarationName::CXXDestructorName: Out << "dn"; mangleUnresolvedTypeOrSimpleId(name.getCXXNameType()); break; // ::= on case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXOperatorName: Out << "on"; mangleOperatorName(name, knownArity); break; case DeclarationName::CXXConstructorName: llvm_unreachable("Can't mangle a constructor name!"); case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); case DeclarationName::CXXDeductionGuideName: llvm_unreachable("Can't mangle a deduction guide name!"); case DeclarationName::ObjCMultiArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCZeroArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); } // The and on productions end in an optional // . if (TemplateArgs) mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs); } void CXXNameMangler::mangleUnqualifiedName( GlobalDecl GD, DeclarationName Name, const DeclContext *DC, unsigned KnownArity, const AbiTagList *AdditionalAbiTags) { const NamedDecl *ND = cast_or_null(GD.getDecl()); // ::= [] [F] // ::= // ::= [] [F] // ::= [] DC * E if (ND && DC && DC->isFileContext()) mangleModuleName(ND); // A member-like constrained friend is mangled with a leading 'F'. // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/24. auto *FD = dyn_cast(ND); auto *FTD = dyn_cast(ND); if ((FD && FD->isMemberLikeConstrainedFriend()) || (FTD && FTD->getTemplatedDecl()->isMemberLikeConstrainedFriend())) { if (!isCompatibleWith(LangOptions::ClangABI::Ver17)) Out << 'F'; } unsigned Arity = KnownArity; switch (Name.getNameKind()) { case DeclarationName::Identifier: { const IdentifierInfo *II = Name.getAsIdentifierInfo(); // We mangle decomposition declarations as the names of their bindings. if (auto *DD = dyn_cast(ND)) { // FIXME: Non-standard mangling for decomposition declarations: // // ::= DC * E // // Proposed on cxx-abi-dev on 2016-08-12 Out << "DC"; for (auto *BD : DD->bindings()) mangleSourceName(BD->getDeclName().getAsIdentifierInfo()); Out << 'E'; writeAbiTags(ND, AdditionalAbiTags); break; } if (auto *GD = dyn_cast(ND)) { // We follow MSVC in mangling GUID declarations as if they were variables // with a particular reserved name. Continue the pretense here. SmallString GUID; llvm::raw_svector_ostream GUIDOS(GUID); Context.mangleMSGuidDecl(GD, GUIDOS); Out << GUID.size() << GUID; break; } if (auto *TPO = dyn_cast(ND)) { // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63. Out << "TA"; mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(), TPO->getValue(), /*TopLevel=*/true); break; } if (II) { // Match GCC's naming convention for internal linkage symbols, for // symbols that are not actually visible outside of this TU. GCC // distinguishes between internal and external linkage symbols in // its mangling, to support cases like this that were valid C++ prior // to DR426: // // void test() { extern void foo(); } // static void foo(); // // Don't bother with the L marker for names in anonymous namespaces; the // 12_GLOBAL__N_1 mangling is quite sufficient there, and this better // matches GCC anyway, because GCC does not treat anonymous namespaces as // implying internal linkage. if (Context.isInternalLinkageDecl(ND)) Out << 'L'; bool IsRegCall = FD && FD->getType()->castAs()->getCallConv() == clang::CC_X86RegCall; bool IsDeviceStub = FD && FD->hasAttr() && GD.getKernelReferenceKind() == KernelReferenceKind::Stub; if (IsDeviceStub) mangleDeviceStubName(II); else if (IsRegCall) mangleRegCallName(II); else mangleSourceName(II); writeAbiTags(ND, AdditionalAbiTags); break; } // Otherwise, an anonymous entity. We must have a declaration. assert(ND && "mangling empty name without declaration"); if (const NamespaceDecl *NS = dyn_cast(ND)) { if (NS->isAnonymousNamespace()) { // This is how gcc mangles these names. Out << "12_GLOBAL__N_1"; break; } } if (const VarDecl *VD = dyn_cast(ND)) { // We must have an anonymous union or struct declaration. const RecordDecl *RD = VD->getType()->castAs()->getDecl(); // Itanium C++ ABI 5.1.2: // // For the purposes of mangling, the name of an anonymous union is // considered to be the name of the first named data member found by a // pre-order, depth-first, declaration-order walk of the data members of // the anonymous union. If there is no such data member (i.e., if all of // the data members in the union are unnamed), then there is no way for // a program to refer to the anonymous union, and there is therefore no // need to mangle its name. assert(RD->isAnonymousStructOrUnion() && "Expected anonymous struct or union!"); const FieldDecl *FD = RD->findFirstNamedDataMember(); // It's actually possible for various reasons for us to get here // with an empty anonymous struct / union. Fortunately, it // doesn't really matter what name we generate. if (!FD) break; assert(FD->getIdentifier() && "Data member name isn't an identifier!"); mangleSourceName(FD->getIdentifier()); // Not emitting abi tags: internal name anyway. break; } // Class extensions have no name as a category, and it's possible // for them to be the semantic parent of certain declarations // (primarily, tag decls defined within declarations). Such // declarations will always have internal linkage, so the name // doesn't really matter, but we shouldn't crash on them. For // safety, just handle all ObjC containers here. if (isa(ND)) break; // We must have an anonymous struct. const TagDecl *TD = cast(ND); if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { assert(TD->getDeclContext() == D->getDeclContext() && "Typedef should not be in another decl context!"); assert(D->getDeclName().getAsIdentifierInfo() && "Typedef was not named!"); mangleSourceName(D->getDeclName().getAsIdentifierInfo()); assert(!AdditionalAbiTags && "Type cannot have additional abi tags"); // Explicit abi tags are still possible; take from underlying type, not // from typedef. writeAbiTags(TD, nullptr); break; } // ::= // // ::= Ul E [ ] _ // ::= * + // # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast(TD)) { std::optional DeviceNumber = Context.getDiscriminatorOverride()(Context.getASTContext(), Record); // If we have a device-number via the discriminator, use that to mangle // the lambda, otherwise use the typical lambda-mangling-number. In either // case, a '0' should be mangled as a normal unnamed class instead of as a // lambda. if (Record->isLambda() && ((DeviceNumber && *DeviceNumber > 0) || (!DeviceNumber && Record->getLambdaManglingNumber() > 0))) { assert(!AdditionalAbiTags && "Lambda type cannot have additional abi tags"); mangleLambda(Record); break; } } if (TD->isExternallyVisible()) { unsigned UnnamedMangle = getASTContext().getManglingNumber(TD, Context.isAux()); Out << "Ut"; if (UnnamedMangle > 1) Out << UnnamedMangle - 2; Out << '_'; writeAbiTags(TD, AdditionalAbiTags); break; } // Get a unique id for the anonymous struct. If it is not a real output // ID doesn't matter so use fake one. unsigned AnonStructId = NullOut ? 0 : Context.getAnonymousStructId(TD, dyn_cast(DC)); // Mangle it as a source name in the form // [n] $_ // where n is the length of the string. SmallString<8> Str; Str += "$_"; Str += llvm::utostr(AnonStructId); Out << Str.size(); Out << Str; break; } case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: { const CXXRecordDecl *InheritedFrom = nullptr; TemplateName InheritedTemplateName; const TemplateArgumentList *InheritedTemplateArgs = nullptr; if (auto Inherited = cast(ND)->getInheritedConstructor()) { InheritedFrom = Inherited.getConstructor()->getParent(); InheritedTemplateName = TemplateName(Inherited.getConstructor()->getPrimaryTemplate()); InheritedTemplateArgs = Inherited.getConstructor()->getTemplateSpecializationArgs(); } if (ND == Structor) // If the named decl is the C++ constructor we're mangling, use the type // we were given. mangleCXXCtorType(static_cast(StructorType), InheritedFrom); else // Otherwise, use the complete constructor name. This is relevant if a // class with a constructor is declared within a constructor. mangleCXXCtorType(Ctor_Complete, InheritedFrom); // FIXME: The template arguments are part of the enclosing prefix or // nested-name, but it's more convenient to mangle them here. if (InheritedTemplateArgs) mangleTemplateArgs(InheritedTemplateName, *InheritedTemplateArgs); writeAbiTags(ND, AdditionalAbiTags); break; } case DeclarationName::CXXDestructorName: if (ND == Structor) // If the named decl is the C++ destructor we're mangling, use the type we // were given. mangleCXXDtorType(static_cast(StructorType)); else // Otherwise, use the complete destructor name. This is relevant if a // class with a destructor is declared within a destructor. mangleCXXDtorType(Dtor_Complete); assert(ND); writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXOperatorName: if (ND && Arity == UnknownArity) { Arity = cast(ND)->getNumParams(); // If we have a member function, we need to include the 'this' pointer. if (const auto *MD = dyn_cast(ND)) if (MD->isImplicitObjectMemberFunction()) Arity++; } [[fallthrough]]; case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXLiteralOperatorName: mangleOperatorName(Name, Arity); writeAbiTags(ND, AdditionalAbiTags); break; case DeclarationName::CXXDeductionGuideName: llvm_unreachable("Can't mangle a deduction guide name!"); case DeclarationName::CXXUsingDirective: llvm_unreachable("Can't mangle a using directive name!"); } } void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) { // ::= __regcall3__ // ::= [n] // ::= if (getASTContext().getLangOpts().RegCall4) Out << II->getLength() + sizeof("__regcall4__") - 1 << "__regcall4__" << II->getName(); else Out << II->getLength() + sizeof("__regcall3__") - 1 << "__regcall3__" << II->getName(); } void CXXNameMangler::mangleDeviceStubName(const IdentifierInfo *II) { // ::= __device_stub__ // ::= [n] // ::= Out << II->getLength() + sizeof("__device_stub__") - 1 << "__device_stub__" << II->getName(); } void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { // ::= // ::= [n] // ::= Out << II->getLength() << II->getName(); } void CXXNameMangler::mangleNestedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags, bool NoFunction) { const NamedDecl *ND = cast(GD.getDecl()); // // ::= N [] [] E // ::= N [] [] // E Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast(ND)) { Qualifiers MethodQuals = Method->getMethodQualifiers(); // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. if (Method->isExplicitObjectMemberFunction()) Out << 'H'; MethodQuals.removeRestrict(); mangleQualifiers(MethodQuals); mangleRefQualifier(Method->getRefQualifier()); } // Check if we have a template. const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) { mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { manglePrefix(DC, NoFunction); mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } Out << 'E'; } void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, ArrayRef Args) { // ::= N [] E Out << 'N'; mangleTemplatePrefix(TD); mangleTemplateArgs(asTemplateName(TD), Args); Out << 'E'; } void CXXNameMangler::mangleNestedNameWithClosurePrefix( GlobalDecl GD, const NamedDecl *PrefixND, const AbiTagList *AdditionalAbiTags) { // A represents a variable or field, not a regular // DeclContext, so needs special handling. In this case we're mangling a // limited form of : // // ::= N E Out << 'N'; mangleClosurePrefix(PrefixND); mangleUnqualifiedName(GD, nullptr, AdditionalAbiTags); Out << 'E'; } static GlobalDecl getParentOfLocalEntity(const DeclContext *DC) { GlobalDecl GD; // The Itanium spec says: // For entities in constructors and destructors, the mangling of the // complete object constructor or destructor is used as the base function // name, i.e. the C1 or D1 version. if (auto *CD = dyn_cast(DC)) GD = GlobalDecl(CD, Ctor_Complete); else if (auto *DD = dyn_cast(DC)) GD = GlobalDecl(DD, Dtor_Complete); else GD = GlobalDecl(cast(DC)); return GD; } void CXXNameMangler::mangleLocalName(GlobalDecl GD, const AbiTagList *AdditionalAbiTags) { const Decl *D = GD.getDecl(); // := Z E [] // := Z E s [] // := Z E d [ ] // _ // := _ assert(isa(D) || isa(D)); const RecordDecl *RD = GetLocalClassDecl(D); const DeclContext *DC = Context.getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; { AbiTagState LocalAbiTags(AbiTags); if (const ObjCMethodDecl *MD = dyn_cast(DC)) mangleObjCMethodName(MD); else if (const BlockDecl *BD = dyn_cast(DC)) mangleBlockForPrefix(BD); else mangleFunctionEncoding(getParentOfLocalEntity(DC)); // Implicit ABI tags (from namespace) are not available in the following // entity; reset to actually emitted tags, which are available. LocalAbiTags.setUsedAbiTags(LocalAbiTags.getEmittedAbiTags()); } Out << 'E'; // GCC 5.3.0 doesn't emit derived ABI tags for local names but that seems to // be a bug that is fixed in trunk. if (RD) { // The parameter number is omitted for the last parameter, 0 for the // second-to-last parameter, 1 for the third-to-last parameter, etc. The // will of course contain a : Its // numbering will be local to the particular argument in which it appears // -- other default arguments do not affect its encoding. const CXXRecordDecl *CXXRD = dyn_cast(RD); if (CXXRD && CXXRD->isLambda()) { if (const ParmVarDecl *Parm = dyn_cast_or_null(CXXRD->getLambdaContextDecl())) { if (const FunctionDecl *Func = dyn_cast(Parm->getDeclContext())) { Out << 'd'; unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); if (Num > 1) mangleNumber(Num - 2); Out << '_'; } } } // Mangle the name relative to the closest enclosing function. // equality ok because RD derived from ND above if (D == RD) { mangleUnqualifiedName(RD, DC, AdditionalAbiTags); } else if (const BlockDecl *BD = dyn_cast(D)) { if (const NamedDecl *PrefixND = getClosurePrefix(BD)) mangleClosurePrefix(PrefixND, true /*NoFunction*/); else manglePrefix(Context.getEffectiveDeclContext(BD), true /*NoFunction*/); assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { const NamedDecl *ND = cast(D); mangleNestedName(GD, Context.getEffectiveDeclContext(ND), AdditionalAbiTags, true /*NoFunction*/); } } else if (const BlockDecl *BD = dyn_cast(D)) { // Mangle a block in a default parameter; see above explanation for // lambdas. if (const ParmVarDecl *Parm = dyn_cast_or_null(BD->getBlockManglingContextDecl())) { if (const FunctionDecl *Func = dyn_cast(Parm->getDeclContext())) { Out << 'd'; unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); if (Num > 1) mangleNumber(Num - 2); Out << '_'; } } assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } if (const NamedDecl *ND = dyn_cast(RD ? RD : D)) { unsigned disc; if (Context.getNextDiscriminator(ND, disc)) { if (disc < 10) Out << '_' << disc; else Out << "__" << disc << '_'; } } } void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { if (GetLocalClassDecl(Block)) { mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; } const DeclContext *DC = Context.getEffectiveDeclContext(Block); if (isLocalContainerContext(DC)) { mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; } if (const NamedDecl *PrefixND = getClosurePrefix(Block)) mangleClosurePrefix(PrefixND); else manglePrefix(DC); mangleUnqualifiedBlock(Block); } void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { // When trying to be ABI-compatibility with clang 12 and before, mangle a // now, with no substitutions and no . if (Decl *Context = Block->getBlockManglingContextDecl()) { if (isCompatibleWith(LangOptions::ClangABI::Ver12) && (isa(Context) || isa(Context)) && Context->getDeclContext()->isRecord()) { const auto *ND = cast(Context); if (ND->getIdentifier()) { mangleSourceNameWithAbiTags(ND); Out << 'M'; } } } // If we have a block mangling number, use it. unsigned Number = Block->getBlockManglingNumber(); // Otherwise, just make up a number. It doesn't matter what it is because // the symbol in question isn't externally visible. if (!Number) Number = Context.getBlockId(Block, false); else { // Stored mangling numbers are 1-based. --Number; } Out << "Ub"; if (Number > 0) Out << Number - 1; Out << '_'; } // // ::= Ty # template type parameter // ::= Tk [] # constrained type parameter // ::= Tn # template non-type parameter // ::= Tt * E [Q ] // # template template parameter // ::= Tp # template parameter pack void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) { // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/47. if (auto *Ty = dyn_cast(Decl)) { if (Ty->isParameterPack()) Out << "Tp"; const TypeConstraint *Constraint = Ty->getTypeConstraint(); if (Constraint && !isCompatibleWith(LangOptions::ClangABI::Ver17)) { // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/24. Out << "Tk"; mangleTypeConstraint(Constraint); } else { Out << "Ty"; } } else if (auto *Tn = dyn_cast(Decl)) { if (Tn->isExpandedParameterPack()) { for (unsigned I = 0, N = Tn->getNumExpansionTypes(); I != N; ++I) { Out << "Tn"; mangleType(Tn->getExpansionType(I)); } } else { QualType T = Tn->getType(); if (Tn->isParameterPack()) { Out << "Tp"; if (auto *PackExpansion = T->getAs()) T = PackExpansion->getPattern(); } Out << "Tn"; mangleType(T); } } else if (auto *Tt = dyn_cast(Decl)) { if (Tt->isExpandedParameterPack()) { for (unsigned I = 0, N = Tt->getNumExpansionTemplateParameters(); I != N; ++I) mangleTemplateParameterList(Tt->getExpansionTemplateParameters(I)); } else { if (Tt->isParameterPack()) Out << "Tp"; mangleTemplateParameterList(Tt->getTemplateParameters()); } } } void CXXNameMangler::mangleTemplateParameterList( const TemplateParameterList *Params) { Out << "Tt"; for (auto *Param : *Params) mangleTemplateParamDecl(Param); mangleRequiresClause(Params->getRequiresClause()); Out << "E"; } void CXXNameMangler::mangleTypeConstraint( const ConceptDecl *Concept, ArrayRef Arguments) { const DeclContext *DC = Context.getEffectiveDeclContext(Concept); if (!Arguments.empty()) mangleTemplateName(Concept, Arguments); else if (DC->isTranslationUnit() || isStdNamespace(DC)) mangleUnscopedName(Concept, DC, nullptr); else mangleNestedName(Concept, DC, nullptr); } void CXXNameMangler::mangleTypeConstraint(const TypeConstraint *Constraint) { llvm::SmallVector Args; if (Constraint->getTemplateArgsAsWritten()) { for (const TemplateArgumentLoc &ArgLoc : Constraint->getTemplateArgsAsWritten()->arguments()) Args.push_back(ArgLoc.getArgument()); } return mangleTypeConstraint(Constraint->getNamedConcept(), Args); } void CXXNameMangler::mangleRequiresClause(const Expr *RequiresClause) { // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/24. if (RequiresClause && !isCompatibleWith(LangOptions::ClangABI::Ver17)) { Out << 'Q'; mangleExpression(RequiresClause); } } void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // When trying to be ABI-compatibility with clang 12 and before, mangle a // now, with no substitutions. if (Decl *Context = Lambda->getLambdaContextDecl()) { if (isCompatibleWith(LangOptions::ClangABI::Ver12) && (isa(Context) || isa(Context)) && !isa(Context)) { if (const IdentifierInfo *Name = cast(Context)->getIdentifier()) { mangleSourceName(Name); const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(cast(Context), TemplateArgs)) mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); Out << 'M'; } } } Out << "Ul"; mangleLambdaSig(Lambda); Out << "E"; // The number is omitted for the first closure type with a given // in a given context; it is n-2 for the nth closure type // (in lexical order) with that same and context. // // The AST keeps track of the number for us. // // In CUDA/HIP, to ensure the consistent lamba numbering between the device- // and host-side compilations, an extra device mangle context may be created // if the host-side CXX ABI has different numbering for lambda. In such case, // if the mangle context is that device-side one, use the device-side lambda // mangling number for this lambda. std::optional DeviceNumber = Context.getDiscriminatorOverride()(Context.getASTContext(), Lambda); unsigned Number = DeviceNumber ? *DeviceNumber : Lambda->getLambdaManglingNumber(); assert(Number > 0 && "Lambda should be mangled as an unnamed class"); if (Number > 1) mangleNumber(Number - 2); Out << '_'; } void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) { // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/31. for (auto *D : Lambda->getLambdaExplicitTemplateParameters()) mangleTemplateParamDecl(D); // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/24. if (auto *TPL = Lambda->getGenericLambdaTemplateParameterList()) mangleRequiresClause(TPL->getRequiresClause()); auto *Proto = Lambda->getLambdaTypeInfo()->getType()->castAs(); mangleBareFunctionType(Proto, /*MangleReturnType=*/false, Lambda->getLambdaStaticInvoker()); } void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { switch (qualifier->getKind()) { case NestedNameSpecifier::Global: // nothing return; case NestedNameSpecifier::Super: llvm_unreachable("Can't mangle __super specifier"); case NestedNameSpecifier::Namespace: mangleName(qualifier->getAsNamespace()); return; case NestedNameSpecifier::NamespaceAlias: mangleName(qualifier->getAsNamespaceAlias()->getNamespace()); return; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: manglePrefix(QualType(qualifier->getAsType(), 0)); return; case NestedNameSpecifier::Identifier: // Clang 14 and before did not consider this substitutable. bool Clang14Compat = isCompatibleWith(LangOptions::ClangABI::Ver14); if (!Clang14Compat && mangleSubstitution(qualifier)) return; // Member expressions can have these without prefixes, but that // should end up in mangleUnresolvedPrefix instead. assert(qualifier->getPrefix()); manglePrefix(qualifier->getPrefix()); mangleSourceName(qualifier->getAsIdentifier()); if (!Clang14Compat) addSubstitution(qualifier); return; } llvm_unreachable("unexpected nested name specifier"); } void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= // ::= // ::= // ::= // ::= # empty // ::= assert(!isa(DC) && "prefix cannot be LinkageSpecDecl"); if (DC->isTranslationUnit()) return; if (NoFunction && isLocalContainerContext(DC)) return; const NamedDecl *ND = cast(DC); if (mangleSubstitution(ND)) return; // Check if we have a template-prefix or a closure-prefix. const TemplateArgumentList *TemplateArgs = nullptr; if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else if (const NamedDecl *PrefixND = getClosurePrefix(ND)) { mangleClosurePrefix(PrefixND, NoFunction); mangleUnqualifiedName(ND, nullptr, nullptr); } else { const DeclContext *DC = Context.getEffectiveDeclContext(ND); manglePrefix(DC, NoFunction); mangleUnqualifiedName(ND, DC, nullptr); } addSubstitution(ND); } void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { // ::=