]> granicus.if.org Git - clang/commitdiff
It turns out that linkers (at least, the Darwin linker) don't necessarily
authorJohn McCall <rjmccall@apple.com>
Thu, 5 Aug 2010 20:39:18 +0000 (20:39 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 5 Aug 2010 20:39:18 +0000 (20:39 +0000)
do the right thing with mixed-visibility symbols, so disable the visibility
optimization where that's possible, i.e. with template classes (since it's
possible that an arbitrary template might be subject to an explicit
instantiation elsewhere).  447.dealII actually does this.

I've put the code under an option that's currently not hooked up to anything.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110374 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/CodeGenOptions.h
lib/CodeGen/CGVTables.cpp
lib/CodeGen/CodeGenModule.cpp
test/CodeGenCXX/mangle-subst-std.cpp
test/CodeGenCXX/rtti-linkage.cpp
test/CodeGenCXX/virt-template-vtable.cpp
test/CodeGenCXX/vtable-linkage.cpp

index 2918f4e9d3cb3015d1acc9b95578e38a0c18f5dc..63f247b5a917cb67e79a8fcc40db5d60f8ebe7d4 100644 (file)
@@ -46,7 +46,12 @@ public:
                                   /// internal state before optimizations are
                                   /// done.
   unsigned DisableRedZone    : 1; /// Set when -mno-red-zone is enabled.
+  unsigned EmitDeclMetadata  : 1; /// Emit special metadata indicating what Decl*
+                                  /// various IR entities came from.  Only useful
+                                  /// when running CodeGen as a subroutine.
   unsigned FunctionSections  : 1; /// Set when -ffunction-sections is enabled
+  unsigned EmitWeakTemplatesHidden : 1;  /// Emit weak vtables and typeinfo for
+                                  /// template classes with hidden visibility
   unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is enabled
   unsigned MergeAllConstants : 1; /// Merge identical constants.
   unsigned NoCommon          : 1; /// Set when -fno-common or C++ is enabled.
@@ -67,9 +72,6 @@ public:
   unsigned UnwindTables      : 1; /// Emit unwind tables.
   unsigned VerifyModule      : 1; /// Control whether the module should be run
                                   /// through the LLVM Verifier.
-  unsigned EmitDeclMetadata  : 1; /// Emit special metadata indicating what Decl*
-                                  /// various IR entities came from.  Only useful
-                                  /// when running CodeGen as a subroutine.
 
   /// The code model to use (-mcmodel).
   std::string CodeModel;
@@ -108,7 +110,9 @@ public:
     DisableFPElim = 0;
     DisableLLVMOpts = 0;
     DisableRedZone = 0;
+    EmitDeclMetadata = 0;
     FunctionSections = 0;
+    EmitWeakTemplatesHidden = 0;
     MergeAllConstants = 1;
     NoCommon = 0;
     NoImplicitFloat = 0;
@@ -125,7 +129,6 @@ public:
     UnrollLoops = 0;
     UnwindTables = 0;
     VerifyModule = 1;
-    EmitDeclMetadata = 0;
 
     Inlining = NoInlining;
     RelocationModel = "pic";
index cd34d03cd7747a5048c1b7c0934fa96b26d62806..494176a90633752e54de7aa3e5741c23c54c80e6 100644 (file)
@@ -15,6 +15,7 @@
 #include "CodeGenFunction.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/RecordLayout.h"
+#include "clang/Frontend/CodeGenOptions.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/Support/Compiler.h"
@@ -2469,34 +2470,29 @@ static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
   // emit its thunks with hidden visibility, since its thunks must be
   // emitted when the function is.
 
-  // This mostly follows CodeGenModule::setTypeVisibility.
+  // This follows CodeGenModule::setTypeVisibility; see the comments
+  // there for explanation.
 
   if ((Fn->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage &&
        Fn->getLinkage() != llvm::GlobalVariable::WeakODRLinkage) ||
       Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
     return;
 
-  // Don't override an explicit visibility attribute.
   if (MD->hasAttr<VisibilityAttr>())
     return;
 
   switch (MD->getTemplateSpecializationKind()) {
-  // We have to disable the optimization if this is an EI definition
-  // because there might be EI declarations in other shared objects.
   case TSK_ExplicitInstantiationDefinition:
   case TSK_ExplicitInstantiationDeclaration:
     return;
 
-  // Every use of a non-template or explicitly-specialized class's
-  // type information has to emit it.
-  case TSK_ExplicitSpecialization:
   case TSK_Undeclared:
     break;
 
-  // Implicit instantiations can ignore the possibility of an
-  // explicit instantiation declaration because there necessarily
-  // must be an EI definition somewhere with default visibility.
+  case TSK_ExplicitSpecialization:
   case TSK_ImplicitInstantiation:
+    if (!CGM.getCodeGenOpts().EmitWeakTemplatesHidden)
+      return;
     break;
   }
 
index 6338402579934a40025a623e02f8ef27b8ca518f..297aa4524e3883ae22a6358b87548186087963f6 100644 (file)
@@ -229,6 +229,9 @@ void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
   // This isn't possible if there might be unresolved references
   // elsewhere that rely on this symbol being visible.
 
+  // This should be kept roughly in sync with setThunkVisibility
+  // in CGVTables.cpp.
+
   // Preconditions.
   if (GV->getLinkage() != llvm::GlobalVariable::WeakODRLinkage ||
       GV->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
@@ -245,16 +248,20 @@ void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
   case TSK_ExplicitInstantiationDeclaration:
     return;
 
-  // Every use of a non-template or explicitly-specialized class's
-  // type information has to emit it.
-  case TSK_ExplicitSpecialization:
+  // Every use of a non-template class's type information has to emit it.
   case TSK_Undeclared:
     break;
 
-  // Implicit instantiations can ignore the possibility of an
-  // explicit instantiation declaration because there necessarily
-  // must be an EI definition somewhere with default visibility.
+  // In theory, implicit instantiations can ignore the possibility of
+  // an explicit instantiation declaration because there necessarily
+  // must be an EI definition somewhere with default visibility.  In
+  // practice, it's possible to have an explicit instantiation for
+  // an arbitrary template class, and linkers aren't necessarily able
+  // to deal with mixed-visibility symbols.
+  case TSK_ExplicitSpecialization:
   case TSK_ImplicitInstantiation:
+    if (!CodeGenOpts.EmitWeakTemplatesHidden)
+      return;
     break;
   }
 
index b08b12c91ebeb17594acc5fac6c607c6064dd54b..9c1e978294c860ac0f6d7f4680b6513e3b5fe2e9 100644 (file)
@@ -3,13 +3,13 @@
 // Check mangling of Vtables, VTTs, and construction vtables that
 // involve standard substitutions.
 
-// CHECK: @_ZTVSd = weak_odr hidden constant 
+// CHECK: @_ZTVSd = weak_odr constant 
 // CHECK: @_ZTCSd0_Si = internal constant 
 // CHECK: @_ZTCSd16_So = internal constant
 // CHECK: @_ZTTSd = weak_odr constant
-// CHECK: @_ZTVSo = weak_odr hidden constant
+// CHECK: @_ZTVSo = weak_odr constant
 // CHECK: @_ZTTSo = weak_odr constant
-// CHECK: @_ZTVSi = weak_odr hidden constant
+// CHECK: @_ZTVSi = weak_odr constant
 // CHECK: @_ZTTSi = weak_odr constant
 namespace std {
   struct A { A(); };
index a8b62f7bc3bfc5313ead45146285d561236aae20..49d1c1f5f313d49dcca84a5dbc9a753155f3118b 100644 (file)
@@ -14,7 +14,7 @@
 // CHECK: _ZTI1A = weak_odr hidden constant
 // CHECK: _ZTI1B = constant
 // CHECK: _ZTI1C = internal constant
-// CHECK: _ZTI1TILj0EE = weak_odr hidden constant
+// CHECK: _ZTI1TILj0EE = weak_odr constant
 // CHECK: _ZTI1TILj1EE = weak_odr constant
 // CHECK: _ZTI1TILj2EE = external constant
 // CHECK: _ZTIA10_i = weak_odr hidden constant
index ab406fd99826c39ffa1893e1d982405c89351006..b9558283127605d5195c59271bc4a98dcc1d01f3 100644 (file)
@@ -19,4 +19,4 @@ template class A<short>;
 // CHECK: @_ZTV1B = weak_odr hidden constant
 // CHECK: @_ZTV1AIlE = weak_odr constant
 // CHECK: @_ZTV1AIsE = weak_odr constant
-// CHECK: @_ZTV1AIiE = weak_odr hidden constant
+// CHECK: @_ZTV1AIiE = weak_odr constant
index 67980edf7be2924d050d42925d46d2737da288e6..6c1301bee1ef68f8bab2585f54c77606ff7e5325 100644 (file)
@@ -137,10 +137,10 @@ void use_F() {
 // CHECK-7: @_ZTI1EIlE = weak_odr constant
 
 // F<long> is an implicit template instantiation with no key function,
-// so its vtable should have weak_odr linkage and hidden visibility.
-// CHECK-8: @_ZTV1FIlE = weak_odr hidden constant
+// so its vtable should have weak_odr linkage.
+// CHECK-8: @_ZTV1FIlE = weak_odr constant
 // CHECK-8: @_ZTS1FIlE = weak_odr constant
-// CHECK-8: @_ZTI1FIlE = weak_odr hidden constant
+// CHECK-8: @_ZTI1FIlE = weak_odr constant
 
 // F<int> is an explicit template instantiation declaration without a
 // key function, so its vtable should have external linkage.
@@ -164,10 +164,10 @@ void use_F() {
 // CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant
 
 // F<char> is an explicit specialization without a key function, so
-// its vtable should have weak_odr linkage and hidden visibility.
-// CHECK-13: @_ZTV1FIcE = weak_odr hidden constant
+// its vtable should have weak_odr linkage.
+// CHECK-13: @_ZTV1FIcE = weak_odr constant
 // CHECK-13: @_ZTS1FIcE = weak_odr constant
-// CHECK-13: @_ZTI1FIcE = weak_odr hidden constant
+// CHECK-13: @_ZTI1FIcE = weak_odr constant
 
 // RUN: FileCheck --check-prefix=CHECK-G %s < %t
 //