diff --git a/clang/include/clang/Frontend/CodeGenOptions.h b/clang/include/clang/Frontend/CodeGenOptions.h index 2918f4e9d3cb..63f247b5a917 100644 --- a/clang/include/clang/Frontend/CodeGenOptions.h +++ b/clang/include/clang/Frontend/CodeGenOptions.h @@ -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"; diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index cd34d03cd774..494176a90633 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -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()) 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; } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 633840257993..297aa4524e38 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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; } diff --git a/clang/test/CodeGenCXX/mangle-subst-std.cpp b/clang/test/CodeGenCXX/mangle-subst-std.cpp index b08b12c91ebe..9c1e978294c8 100644 --- a/clang/test/CodeGenCXX/mangle-subst-std.cpp +++ b/clang/test/CodeGenCXX/mangle-subst-std.cpp @@ -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(); }; diff --git a/clang/test/CodeGenCXX/rtti-linkage.cpp b/clang/test/CodeGenCXX/rtti-linkage.cpp index a8b62f7bc3bf..49d1c1f5f313 100644 --- a/clang/test/CodeGenCXX/rtti-linkage.cpp +++ b/clang/test/CodeGenCXX/rtti-linkage.cpp @@ -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 diff --git a/clang/test/CodeGenCXX/virt-template-vtable.cpp b/clang/test/CodeGenCXX/virt-template-vtable.cpp index ab406fd99826..b95582831276 100644 --- a/clang/test/CodeGenCXX/virt-template-vtable.cpp +++ b/clang/test/CodeGenCXX/virt-template-vtable.cpp @@ -19,4 +19,4 @@ template class A; // 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 diff --git a/clang/test/CodeGenCXX/vtable-linkage.cpp b/clang/test/CodeGenCXX/vtable-linkage.cpp index 67980edf7be2..6c1301bee1ef 100644 --- a/clang/test/CodeGenCXX/vtable-linkage.cpp +++ b/clang/test/CodeGenCXX/vtable-linkage.cpp @@ -137,10 +137,10 @@ void use_F() { // CHECK-7: @_ZTI1EIlE = weak_odr constant // F 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 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 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 //