]> granicus.if.org Git - clang/commitdiff
Address Chris's comments regarding C++ name mangling.
authorDouglas Gregor <dgregor@apple.com>
Wed, 18 Feb 2009 23:53:56 +0000 (23:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 18 Feb 2009 23:53:56 +0000 (23:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64984 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/Mangle.cpp
lib/CodeGen/Mangle.h

index f2fec65cc3689755295b894f3b9ad2d9e3ea4e07..56e7b8b79296c3024ab4b0e20146e50b84630938 100644 (file)
@@ -106,7 +106,7 @@ CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D,
 
   std::string ContextName;
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
-    ContextName = CGM.getMangledName(FD)->getName();
+    ContextName = CGM.getMangledName(FD);
   else if (isa<ObjCMethodDecl>(CurFuncDecl))
     ContextName = std::string(CurFn->getNameStart(), 
                               CurFn->getNameStart() + CurFn->getNameLen());
@@ -171,7 +171,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
       // A normal fixed sized variable becomes an alloca in the entry block.
       const llvm::Type *LTy = ConvertType(Ty);
       llvm::AllocaInst *Alloc =
-        CreateTempAlloca(LTy, CGM.getMangledName(&D)->getName());
+        CreateTempAlloca(LTy, CGM.getMangledName(&D));
       unsigned align = getContext().getTypeAlign(Ty);
       if (const AlignedAttr* AA = D.getAttr<AlignedAttr>())
         align = std::max(align, AA->getAlignment());
index e991c8ec7726674475debf098ba3455bd2ecd496..69429e08e679d5637e9e04f3503f009e82136fa1 100644 (file)
@@ -702,7 +702,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
 
   std::string FunctionName;
   if(const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) {
-    FunctionName = CGM.getMangledName(FD)->getName();
+    FunctionName = CGM.getMangledName(FD);
   } else {
     // Just get the mangled name.
     FunctionName = CurFn->getName();
index a699317f63d557b32b1c4a2614f27a8ea0935af8..c1436b5ff4bfb11e6982f4d60397c2097a3e79c1 100644 (file)
@@ -171,8 +171,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
   if (CGDebugInfo *DI = getDebugInfo()) {
     DI->setLocation(StartLoc);
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-      DI->EmitFunctionStart(CGM.getMangledName(FD)->getName(),
-                            RetTy, CurFn, Builder);
+      DI->EmitFunctionStart(CGM.getMangledName(FD), RetTy, CurFn, Builder);
     } else {
       // Just use LLVM function name.
       DI->EmitFunctionStart(Fn->getName().c_str(), 
index e7c784580bd76ad18b6d5a7fc240defca4fc0e09..ca6ba14f85557602155f20fb286ca1bbf981afca 100644 (file)
@@ -170,13 +170,15 @@ static void setGlobalVisibility(llvm::GlobalValue *GV,
 /// FIXME: Performance here is going to be terribly until we start
 /// caching mangled names. However, we should fix the problem above
 /// first.
-IdentifierInfo *CodeGenModule::getMangledName(const NamedDecl *ND) const {
-  std::string Name;
-  llvm::raw_string_ostream Out(Name);
+const char *CodeGenModule::getMangledName(const NamedDecl *ND) {
+  llvm::SmallString<256> Name;
+  llvm::raw_svector_ostream Out(Name);
   if (!mangleName(ND, Context, Out))
-    return ND->getIdentifier();
+    return ND->getIdentifier()->getName();
 
-  return &Context.Idents.get(Out.str());
+  Name += '\0';
+  return MangledNames.GetOrCreateValue(Name.begin(), Name.end())
+           .getKeyData();
 }
 
 /// AddGlobalCtor - Add a function to the list that will be called before
@@ -379,7 +381,7 @@ void CodeGenModule::EmitAliases() {
     llvm::GlobalValue *GA = 
       new llvm::GlobalAlias(aliasee->getType(),
                             llvm::Function::ExternalLinkage,
-                            getMangledName(D)->getName(), aliasee, 
+                            getMangledName(D), aliasee, 
                             &getModule());
     
     llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)];
@@ -582,7 +584,7 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) {
     llvm::GlobalVariable *GV = 
       new llvm::GlobalVariable(Ty, false, 
                                llvm::GlobalValue::ExternalLinkage,
-                               0, getMangledName(D)->getName(), &getModule(), 
+                               0, getMangledName(D), &getModule(), 
                                0, ASTTy.getAddressSpace());
     Entry = GV;
 
@@ -630,7 +632,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
   if (!GV) {
     GV = new llvm::GlobalVariable(InitType, false, 
                                   llvm::GlobalValue::ExternalLinkage,
-                                  0, getMangledName(D)->getName()
+                                  0, getMangledName(D), 
                                   &getModule(), 0, ASTTy.getAddressSpace());
   } else if (GV->getType() != 
              llvm::PointerType::get(InitType, ASTTy.getAddressSpace())) {
@@ -654,7 +656,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
     // Make a new global with the correct type
     GV = new llvm::GlobalVariable(InitType, false, 
                                   llvm::GlobalValue::ExternalLinkage,
-                                  0, getMangledName(D)->getName()
+                                  0, getMangledName(D), 
                                   &getModule(), 0, ASTTy.getAddressSpace());
     // Steal the name of the old global
     GV->takeName(OldGV);
@@ -753,7 +755,7 @@ CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) {
   const llvm::Type *Ty = getTypes().ConvertType(D->getType());
   llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
                                              llvm::Function::ExternalLinkage,
-                                             getMangledName(D)->getName(),
+                                             getMangledName(D),
                                              &getModule());
   SetFunctionAttributes(D, F);
   return F;
index b54ee13df63ee67af8bf898da4273d283cfa2e34..24453ccadc7669dfecb62d6858943992c694f9e0 100644 (file)
@@ -18,6 +18,7 @@
 #include "clang/AST/Attr.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
 
 #include "CGCall.h"
 
@@ -81,14 +82,23 @@ class CodeGenModule {
   /// will name them and patch up conflicts when we release the module.
   std::vector< std::pair<llvm::Function*, std::string> > RuntimeFunctions;
 
-  /// GlobalDeclMap - Mapping of decl names global variables we have already
-  /// emitted. Note that the entries in this map are the actual globals and
-  /// therefore may not be of the same type as the decl, they should be
-  /// bitcasted on retrieval. Also note that the globals are keyed on their
-  /// source name, not the global name (which may change with attributes such as
-  /// asm-labels).  This key to this map should be generated using
-  /// getMangledName().
-  llvm::DenseMap<IdentifierInfo*, llvm::GlobalValue*> GlobalDeclMap;
+  /// GlobalDeclMap - Mapping of decl names (represented as unique
+  /// character pointers from either the identifier table or the set
+  /// of mangled names) to global variables we have already
+  /// emitted. Note that the entries in this map are the actual
+  /// globals and therefore may not be of the same type as the decl,
+  /// they should be bitcasted on retrieval. Also note that the
+  /// globals are keyed on their source name, not the global name
+  /// (which may change with attributes such as asm-labels).  This key
+  /// to this map should be generated using getMangledName().
+  llvm::DenseMap<const char*, llvm::GlobalValue*> GlobalDeclMap;
+
+  /// \brief Contains the strings used for mangled names.
+  ///
+  /// FIXME: Eventually, this should map from the semantic/canonical
+  /// declaration for each global entity to its mangled name (if it
+  /// has one).
+  llvm::StringSet<> MangledNames;
 
   /// Aliases - List of aliases in module. These cannot be emitted until all the
   /// code has been seen, as they reference things by name instead of directly
@@ -285,7 +295,7 @@ public:
                               const Decl *TargetDecl,
                               AttributeListType &PAL);
 
-  IdentifierInfo *getMangledName(const NamedDecl *ND) const;
+  const char *getMangledName(const NamedDecl *ND);
 
 
 private:
index 9ad98d787a8b0c0a285e4786cb814b376a61c095..f007539714c51ac338223d3de17a69f9766e81d1 100644 (file)
@@ -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 @@ bool CXXNameMangler::mangle(const NamedDecl *D) {
   // 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 @@ static bool isStdNamespace(const DeclContext *DC) {
     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 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
 
   case OO_None: 
   case NUM_OVERLOADED_OPERATORS:
-    assert(false && "Not an ovelroaded operator"); 
+    assert(false && "Not an overloaded operator"); 
     break;
   }
 }
@@ -516,7 +520,11 @@ namespace clang {
   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;
   }
 }
 
index 404f8bddb75a63a64388861c0e5838fb51d6c67b..60a5113ccc9290249ea21f6417fdd2741fb13490 100644 (file)
@@ -1,4 +1,4 @@
-//===---------------------- Mangle.h - Mangle C++ Names -------------------===//
+//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //