From: Anders Carlsson Date: Fri, 4 Dec 2009 06:23:23 +0000 (+0000) Subject: Correctly mangle the 'std' namespace inside extern "C++" blocks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47846d2b4c19972e57563bb05a777748939bfb47;p=clang Correctly mangle the 'std' namespace inside extern "C++" blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90544 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 1aea1873fd..a20dec6ef8 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -247,14 +247,32 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { mangleBareFunctionType(FT, MangleReturnType); } -static bool isStdNamespace(const NamespaceDecl *NS) { +/// isStd - Return whether a given namespace is the 'std' namespace. +static bool isStd(const NamespaceDecl *NS) { const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); return II && II->isStr("std"); } +static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { + while (isa(DC)) { + assert(cast(DC)->getLanguage() == + LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!"); + DC = DC->getParent(); + } + + return DC; +} + +// isStdNamespace - Return whether a given decl context is a toplevel 'std' +// namespace. static bool isStdNamespace(const DeclContext *DC) { - return DC->isNamespace() && DC->getParent()->isTranslationUnit() && - isStdNamespace(cast(DC)); + if (!DC->isNamespace()) + return false; + + if (!IgnoreLinkageSpecDecls(DC->getParent())->isTranslationUnit()) + return false; + + return isStd(cast(DC)); } static const TemplateDecl * @@ -317,12 +335,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { void CXXNameMangler::mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { - const DeclContext *DC = TD->getDeclContext(); - while (isa(DC)) { - assert(cast(DC)->getLanguage() == - LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!"); - DC = DC->getParent(); - } + const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext()); if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD); @@ -1244,11 +1257,8 @@ static bool isCharSpecialization(QualType T, const char *Name) { bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { // ::= St # ::std:: - // FIXME: type_info == comes out as __ZNK3std9type_infoeqERKS0_ instead of - // __ZNKSt9type_infoeqERKS_ - // FIXME: __ZSt13set_terminatePFvvE comes out as __ZNSt13set_terminateEPFvvE. if (const NamespaceDecl *NS = dyn_cast(ND)) { - if (isStdNamespace(NS)) { + if (isStd(NS)) { Out << "St"; return true; } diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp index fbce204512..8a410b8b04 100644 --- a/test/CodeGenCXX/mangle-subst-std.cpp +++ b/test/CodeGenCXX/mangle-subst-std.cpp @@ -37,3 +37,13 @@ namespace std { // CHECK: _Z1fSo void f(std::basic_ostream >) { } + +extern "C++" { +namespace std +{ + typedef void (*terminate_handler) (); + + // CHECK: _ZSt13set_terminatePFvvE + terminate_handler set_terminate(terminate_handler) { return 0; } +} +}