diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 63e40a0f30721..4277a0166f202 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -40,65 +40,10 @@ using namespace clang; namespace { -/// Retrieve the declaration context that should be used when mangling the given -/// declaration. -static const DeclContext *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(); - } - - 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 VD->getASTContext().getTranslationUnitDecl(); - - if (const auto *FD = dyn_cast(D)) - if (FD->isExternC()) - return FD->getASTContext().getTranslationUnitDecl(); - - return DC->getRedeclContext(); -} - -static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { - return getEffectiveDeclContext(cast(DC)); -} - static bool isLocalContainerContext(const DeclContext *DC) { return isa(DC) || isa(DC) || isa(DC); } -static const RecordDecl *GetLocalClassDecl(const Decl *D) { - const DeclContext *DC = getEffectiveDeclContext(D); - while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isLocalContainerContext(DC)) - return dyn_cast(D); - D = cast(DC); - DC = getEffectiveDeclContext(D); - } - return nullptr; -} - static const FunctionDecl *getStructor(const FunctionDecl *fn) { if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate()) return ftd->getTemplatedDecl(); @@ -249,6 +194,14 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { return DiscriminatorOverride; } + const DeclContext *getEffectiveDeclContext(const Decl *D); + const DeclContext *getEffectiveParentContext(const DeclContext *DC) { + return getEffectiveDeclContext(cast(DC)); + } + + bool isInternalLinkageDecl(const NamedDecl *ND); + const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC); + /// @} }; @@ -427,6 +380,15 @@ class CXXNameMangler { ASTContext &getASTContext() const { return Context.getASTContext(); } + bool isStd(const NamespaceDecl *NS); + bool isStdNamespace(const DeclContext *DC); + + const RecordDecl *GetLocalClassDecl(const Decl *D); + const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC); + 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) @@ -628,7 +590,48 @@ class CXXNameMangler { } -static bool isInternalLinkageDecl(const NamedDecl *ND) { +/// 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(); + } + + 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(); + + return DC->getRedeclContext(); +} + +bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) { if (ND && ND->getFormalLinkage() == InternalLinkage && !ND->isExternallyVisible() && getEffectiveDeclContext(ND)->isFileContext() && @@ -863,8 +866,8 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { } /// Return whether a given namespace is the 'std' namespace. -static bool isStd(const NamespaceDecl *NS) { - if (!getEffectiveParentContext(NS)->isTranslationUnit()) +bool CXXNameMangler::isStd(const NamespaceDecl *NS) { + if (!Context.getEffectiveParentContext(NS)->isTranslationUnit()) return false; const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); @@ -873,7 +876,7 @@ static bool isStd(const NamespaceDecl *NS) { // isStdNamespace - Return whether a given decl context is a toplevel 'std' // namespace. -static bool isStdNamespace(const DeclContext *DC) { +bool CXXNameMangler::isStdNamespace(const DeclContext *DC) { if (!DC->isNamespace()) return false; @@ -947,6 +950,17 @@ void CXXNameMangler::mangleName(GlobalDecl GD) { } } +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()); @@ -955,7 +969,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // ::= [] // ::= // - const DeclContext *DC = getEffectiveDeclContext(ND); + const DeclContext *DC = Context.getEffectiveDeclContext(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. @@ -963,7 +977,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // a proper semantic declaration context! if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = getEffectiveParentContext(DC); + DC = Context.getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { mangleLocalName(GD, AdditionalAbiTags); return; @@ -1045,7 +1059,7 @@ void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) { void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { - const DeclContext *DC = getEffectiveDeclContext(TD); + const DeclContext *DC = Context.getEffectiveDeclContext(TD); if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD, nullptr); @@ -1061,7 +1075,7 @@ void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, // ::= // ::= St # ::std:: - if (isStdNamespace(getEffectiveDeclContext(ND))) + if (isStdNamespace(Context.getEffectiveDeclContext(ND))) Out << "St"; mangleUnqualifiedName(GD, AdditionalAbiTags); @@ -1421,7 +1435,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, // 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 (isInternalLinkageDecl(ND)) + if (Context.isInternalLinkageDecl(ND)) Out << 'L'; auto *FD = dyn_cast(ND); @@ -1736,7 +1750,7 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, // := _ assert(isa(D) || isa(D)); const RecordDecl *RD = GetLocalClassDecl(D); - const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D); + const DeclContext *DC = Context.getEffectiveDeclContext(RD ? RD : D); Out << 'Z'; @@ -1789,13 +1803,13 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, if (const NamedDecl *PrefixND = getClosurePrefix(BD)) mangleClosurePrefix(PrefixND, true /*NoFunction*/); else - manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/); + manglePrefix(Context.getEffectiveDeclContext(BD), true /*NoFunction*/); assert(!AdditionalAbiTags && "Block cannot have additional abi tags"); mangleUnqualifiedBlock(BD); } else { const NamedDecl *ND = cast(D); - mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags, - true /*NoFunction*/); + 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 @@ -1834,7 +1848,7 @@ void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) { mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; } - const DeclContext *DC = getEffectiveDeclContext(Block); + const DeclContext *DC = Context.getEffectiveDeclContext(Block); if (isLocalContainerContext(DC)) { mangleLocalName(Block, /* AdditionalAbiTags */ nullptr); return; @@ -2044,7 +2058,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { mangleClosurePrefix(PrefixND, NoFunction); mangleUnqualifiedName(ND, nullptr); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); + manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND, nullptr); } @@ -2098,7 +2112,7 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, if (const auto *TTP = dyn_cast(ND)) { mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); + manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction); if (isa(ND) || isa(ND)) mangleUnqualifiedName(GD, nullptr); else @@ -2143,7 +2157,7 @@ void CXXNameMangler::mangleClosurePrefix(const NamedDecl *ND, bool NoFunction) { mangleTemplatePrefix(TD, NoFunction); mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { - manglePrefix(getEffectiveDeclContext(ND), NoFunction); + manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction); mangleUnqualifiedName(ND, nullptr); } @@ -5962,7 +5976,8 @@ bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) { /// Returns whether S is a template specialization of std::Name with a single /// argument of type A. -static bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A) { +bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name, + QualType A) { if (S.isNull()) return false; @@ -5975,7 +5990,7 @@ static bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A) { if (!SD || !SD->getIdentifier()->isStr(Name)) return false; - if (!isStdNamespace(getEffectiveDeclContext(SD))) + if (!isStdNamespace(Context.getEffectiveDeclContext(SD))) return false; const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); @@ -5991,8 +6006,9 @@ static bool isSpecializedAs(QualType S, llvm::StringRef Name, QualType A) { /// Returns whether SD is a template specialization std::Name [, std::allocator]> /// HasAllocator controls whether the 3rd template argument is needed. -static bool isStdCharSpecialization(const ClassTemplateSpecializationDecl *SD, - llvm::StringRef Name, bool HasAllocator) { +bool CXXNameMangler::isStdCharSpecialization( + const ClassTemplateSpecializationDecl *SD, llvm::StringRef Name, + bool HasAllocator) { if (!SD->getIdentifier()->isStr(Name)) return false; @@ -6029,7 +6045,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { } if (const ClassTemplateDecl *TD = dyn_cast(ND)) { - if (!isStdNamespace(getEffectiveDeclContext(TD))) + if (!isStdNamespace(Context.getEffectiveDeclContext(TD))) return false; // ::= Sa # ::std::allocator @@ -6048,7 +6064,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { if (const ClassTemplateSpecializationDecl *SD = dyn_cast(ND)) { - if (!isStdNamespace(getEffectiveDeclContext(SD))) + if (!isStdNamespace(Context.getEffectiveDeclContext(SD))) return false; // ::= Ss # ::std::basic_string