changeset 1214:7e5547d8e59f

Give all symbols nested in functions internal linkage, unless it's one of the other special cases. (for example: this shouldn't be done if the symbol in question is also nested in a template; such symbols should get template-like linkage)
author Frits van Bommel <fvbommel wxs.nl>
date Mon, 13 Apr 2009 16:16:03 +0200
parents 9430d4959ab4
children 08f87d8cd101
files gen/tollvm.cpp
diffstat 1 files changed, 19 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/gen/tollvm.cpp	Mon Apr 13 12:19:18 2009 +0200
+++ b/gen/tollvm.cpp	Mon Apr 13 16:16:03 2009 +0200
@@ -272,9 +272,6 @@
         // template
         if (needsTemplateLinkage(sym))
             return TEMPLATE_LINKAGE_TYPE;
-        // local static
-        else if (sym->parent && sym->parent->isFuncDeclaration())
-            return llvm::GlobalValue::InternalLinkage;
     }
     // function
     else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
@@ -311,7 +308,25 @@
     {
         assert(0 && "not global/function");
     }
-
+    
+    // Any symbol nested in a function can't be referenced directly from
+    // outside that function, so we can give such symbols internal linkage.
+    // This holds even if nested indirectly, such as member functions of
+    // aggregates nested in functions.
+    //
+    // Note: This must be checked after things like template member-ness or
+    // symbols nested in templates would get duplicated for each module,
+    // breaking things like
+    // ---
+    // int counter(T)() { static int i; return i++; }"
+    // ---
+    // if instances get emitted in multiple object files because they'd use
+    // different instances of 'i'.
+    for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent) {
+        if (parent->isFuncDeclaration())
+            return llvm::GlobalValue::InternalLinkage;
+    }
+    
     // default to external linkage
     return llvm::GlobalValue::ExternalLinkage;
 }