Address Chris's comments regarding C++ name mangling.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64984 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 9ad98d7..f007539 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -1,4 +1,4 @@
-//===--------------------- Mangle.cpp - Mangle C++ Names ------------------===//
+//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -18,6 +18,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -61,17 +62,28 @@
   // FIXME: Actually use a visitor to decode these?
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     bool RequiresMangling = false;
-    // Clang's "overloadable" attribute extension to C/C++
-    if (FD->getAttr<OverloadableAttr>())
+    // No mangled in an "implicit extern C" header.
+    if (Context.getSourceManager().getFileCharacteristic(FD->getLocation())
+          == SrcMgr::C_ExternCSystem)
+      RequiresMangling = false;
+    // Clang's "overloadable" attribute extension to C/C++ implies
+    // name mangling (always).
+    else if (FD->getAttr<OverloadableAttr>())
       RequiresMangling = true;
     else if (Context.getLangOptions().CPlusPlus) {
+      // C++ requires name mangling, unless we're in a C linkage
+      // specification.
       RequiresMangling = true;
-      if (isa<LinkageSpecDecl>(FD->getDeclContext()) &&
-          cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() 
-            == LinkageSpecDecl::lang_c) {
-        // Entities with C linkage are not mangled.
-        RequiresMangling = false;
-      } 
+
+      for (const DeclContext *DC = FD->getDeclContext(); 
+           !DC->isTranslationUnit(); DC = DC->getParent()) {
+        if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
+          // extern "C" functions don't use name mangling
+          if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
+            RequiresMangling = false;
+          break;
+        }
+      }
     }
 
     if (RequiresMangling) {
@@ -95,15 +107,7 @@
     return false;
 
   const NamespaceDecl *NS = cast<NamespaceDecl>(DC);
-  const IdentifierInfo *Name = NS->getIdentifier();
-  if (Name->getLength() != 3)
-    return false;
-
-  const char *Str = Name->getName();
-  if (Str[0] != 's' || Str[1] != 't' || Str[2] != 'd')
-    return false;
-      
-  return true;
+  return NS->getOriginalNamespace()->getIdentifier()->isStr("std");
 }
 
 void CXXNameMangler::mangleName(const NamedDecl *ND) {
@@ -307,7 +311,7 @@
 
   case OO_None: 
   case NUM_OVERLOADED_OPERATORS:
-    assert(false && "Not an ovelroaded operator"); 
+    assert(false && "Not an overloaded operator"); 
     break;
   }
 }
@@ -516,7 +520,11 @@
   bool mangleName(const NamedDecl *D, ASTContext &Context, 
                   llvm::raw_ostream &os) {
     CXXNameMangler Mangler(Context, os);
-    return Mangler.mangle(D);
+    if (!Mangler.mangle(D))
+      return false;
+    
+    os.flush();
+    return true;
   }
 }