]> granicus.if.org Git - clang/commitdiff
Correctly mangle the 'std' namespace inside extern "C++" blocks.
authorAnders Carlsson <andersca@mac.com>
Fri, 4 Dec 2009 06:23:23 +0000 (06:23 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 4 Dec 2009 06:23:23 +0000 (06:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90544 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/Mangle.cpp
test/CodeGenCXX/mangle-subst-std.cpp

index 1aea1873fd5d8797968c9a9da61dfc8f06e28be7..a20dec6ef8544a5b0bf64bb29b3885fbcad23916 100644 (file)
@@ -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<LinkageSpecDecl>(DC)) {
+    assert(cast<LinkageSpecDecl>(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<NamespaceDecl>(DC));
+  if (!DC->isNamespace())
+    return false;
+  
+  if (!IgnoreLinkageSpecDecls(DC->getParent())->isTranslationUnit())
+    return false;
+  
+  return isStd(cast<NamespaceDecl>(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<LinkageSpecDecl>(DC)) {
-    assert(cast<LinkageSpecDecl>(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) {
   // <substitution> ::= 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<NamespaceDecl>(ND)) {
-    if (isStdNamespace(NS)) {
+    if (isStd(NS)) {
       Out << "St";
       return true;
     }
index fbce20451264f82918d3fa59461b088af7a33649..8a410b8b049c8c6200528f1d58182a4b5005af64 100644 (file)
@@ -37,3 +37,13 @@ namespace std {
 
 // CHECK: _Z1fSo
 void f(std::basic_ostream<char, std::char_traits<char> >) { }
+
+extern "C++" {
+namespace std
+{
+  typedef void (*terminate_handler) ();
+  
+  // CHECK: _ZSt13set_terminatePFvvE
+  terminate_handler set_terminate(terminate_handler) { return 0; }
+}
+}