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<CXXRecordDecl>(D)) {
- if (RD->isLambda())
- if (ParmVarDecl *ContextParam
- = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
- return ContextParam->getDeclContext();
- }
-
- // Perform the same check for block literals.
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
- if (ParmVarDecl *ContextParam
- = dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
- return ContextParam->getDeclContext();
- }
-
- const DeclContext *DC = D->getDeclContext();
- if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
- isa<OMPDeclareMapperDecl>(DC)) {
- return getEffectiveDeclContext(cast<Decl>(DC));
- }
-
- if (const auto *VD = dyn_cast<VarDecl>(D))
- if (VD->isExternC())
- return VD->getASTContext().getTranslationUnitDecl();
-
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- if (FD->isExternC())
- return FD->getASTContext().getTranslationUnitDecl();
-
- return DC->getRedeclContext();
-}
-
-static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
- return getEffectiveDeclContext(cast<Decl>(DC));
-}
-
static bool isLocalContainerContext(const DeclContext *DC) {
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
}
-static const RecordDecl *GetLocalClassDecl(const Decl *D) {
- const DeclContext *DC = getEffectiveDeclContext(D);
- while (!DC->isNamespace() && !DC->isTranslationUnit()) {
- if (isLocalContainerContext(DC))
- return dyn_cast<RecordDecl>(D);
- D = cast<Decl>(DC);
- DC = getEffectiveDeclContext(D);
- }
- return nullptr;
-}
-
static const FunctionDecl *getStructor(const FunctionDecl *fn) {
if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
return ftd->getTemplatedDecl();
return DiscriminatorOverride;
}
+ const DeclContext *getEffectiveDeclContext(const Decl *D);
+ const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
+ return getEffectiveDeclContext(cast<Decl>(DC));
+ }
+
+ bool isInternalLinkageDecl(const NamedDecl *ND);
+ const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC);
+
/// @}
};
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)
}
-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<CXXRecordDecl>(D)) {
+ if (RD->isLambda())
+ if (ParmVarDecl *ContextParam =
+ dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+ return ContextParam->getDeclContext();
+ }
+
+ // Perform the same check for block literals.
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ if (ParmVarDecl *ContextParam =
+ dyn_cast_or_null<ParmVarDecl>(BD->getBlockManglingContextDecl()))
+ return ContextParam->getDeclContext();
+ }
+
+ const DeclContext *DC = D->getDeclContext();
+ if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) ||
+ isa<OMPDeclareMapperDecl>(DC)) {
+ return getEffectiveDeclContext(cast<Decl>(DC));
+ }
+
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (VD->isExternC())
+ return getASTContext().getTranslationUnitDecl();
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(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() &&
}
/// 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();
// 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;
}
}
+const RecordDecl *CXXNameMangler::GetLocalClassDecl(const Decl *D) {
+ const DeclContext *DC = Context.getEffectiveDeclContext(D);
+ while (!DC->isNamespace() && !DC->isTranslationUnit()) {
+ if (isLocalContainerContext(DC))
+ return dyn_cast<RecordDecl>(D);
+ D = cast<Decl>(DC);
+ DC = Context.getEffectiveDeclContext(D);
+ }
+ return nullptr;
+}
+
void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
const AbiTagList *AdditionalAbiTags) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
// ::= [<module-name>] <unscoped-template-name> <template-args>
// ::= <local-name>
//
- 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.
// 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;
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);
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
- if (isStdNamespace(getEffectiveDeclContext(ND)))
+ if (isStdNamespace(Context.getEffectiveDeclContext(ND)))
Out << "St";
mangleUnqualifiedName(GD, AdditionalAbiTags);
// 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<FunctionDecl>(ND);
// <discriminator> := _ <non-negative number>
assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
const RecordDecl *RD = GetLocalClassDecl(D);
- const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D);
+ const DeclContext *DC = Context.getEffectiveDeclContext(RD ? RD : D);
Out << 'Z';
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<NamedDecl>(D);
- mangleNestedName(GD, getEffectiveDeclContext(ND), AdditionalAbiTags,
- true /*NoFunction*/);
+ mangleNestedName(GD, Context.getEffectiveDeclContext(ND),
+ AdditionalAbiTags, true /*NoFunction*/);
}
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
// Mangle a block in a default parameter; see above explanation for
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
return;
}
- const DeclContext *DC = getEffectiveDeclContext(Block);
+ const DeclContext *DC = Context.getEffectiveDeclContext(Block);
if (isLocalContainerContext(DC)) {
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
return;
mangleClosurePrefix(PrefixND, NoFunction);
mangleUnqualifiedName(ND, nullptr);
} else {
- manglePrefix(getEffectiveDeclContext(ND), NoFunction);
+ manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
mangleUnqualifiedName(ND, nullptr);
}
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
} else {
- manglePrefix(getEffectiveDeclContext(ND), NoFunction);
+ manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
if (isa<BuiltinTemplateDecl>(ND) || isa<ConceptDecl>(ND))
mangleUnqualifiedName(GD, nullptr);
else
mangleTemplatePrefix(TD, NoFunction);
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
} else {
- manglePrefix(getEffectiveDeclContext(ND), NoFunction);
+ manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
mangleUnqualifiedName(ND, nullptr);
}
/// 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;
if (!SD || !SD->getIdentifier()->isStr(Name))
return false;
- if (!isStdNamespace(getEffectiveDeclContext(SD)))
+ if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
return false;
const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
/// Returns whether SD is a template specialization std::Name<char,
/// std::char_traits<char> [, std::allocator<char>]>
/// 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;
}
if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
- if (!isStdNamespace(getEffectiveDeclContext(TD)))
+ if (!isStdNamespace(Context.getEffectiveDeclContext(TD)))
return false;
// <substitution> ::= Sa # ::std::allocator
if (const ClassTemplateSpecializationDecl *SD =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
- if (!isStdNamespace(getEffectiveDeclContext(SD)))
+ if (!isStdNamespace(Context.getEffectiveDeclContext(SD)))
return false;
// <substitution> ::= Ss # ::std::basic_string<char,