Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -210,8 +210,7 @@ GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); setGlobalVisibility(GV, &D); - if (supportsCOMDAT() && GV->isWeakForLinker()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + maybeSetTrivialComdat(*GV); if (D.getTLSKind()) setTLSMode(GV, D); Index: lib/CodeGen/CGVTT.cpp =================================================================== --- lib/CodeGen/CGVTT.cpp +++ lib/CodeGen/CGVTT.cpp @@ -94,8 +94,7 @@ // Set the correct linkage. VTT->setLinkage(Linkage); - if (CGM.supportsCOMDAT() && VTT->isWeakForLinker()) - VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName())); + CGM.maybeSetTrivialComdat(*VTT); // Set the right visibility. CGM.setGlobalVisibility(VTT, RD); @@ -177,4 +176,3 @@ return I->second; } - Index: lib/CodeGen/CGVTables.cpp =================================================================== --- lib/CodeGen/CGVTables.cpp +++ lib/CodeGen/CGVTables.cpp @@ -378,9 +378,6 @@ // Set the right linkage. CGM.setFunctionLinkage(GD, Fn); - if (CGM.supportsCOMDAT() && Fn->isWeakForLinker()) - Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName())); - // Set the right visibility. const CXXMethodDecl *MD = cast(GD.getDecl()); setThunkVisibility(CGM, MD, Thunk, Fn); @@ -461,6 +458,7 @@ CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, !Thunk.Return.isEmpty()); } + CGM.maybeSetTrivialComdat(*ThunkFn); } void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD, Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -608,6 +608,7 @@ const llvm::Triple &getTriple() const; bool supportsCOMDAT() const; void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO); + void maybeSetTrivialComdat(llvm::GlobalObject &GO); CGCXXABI &getCXXABI() const { return *ABI; } llvm::LLVMContext &getLLVMContext() { return VMContext; } Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1298,8 +1298,7 @@ auto *GV = new llvm::GlobalVariable( getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name); - if (supportsCOMDAT()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + maybeSetTrivialComdat(*GV); return GV; } @@ -1850,9 +1849,7 @@ OldGV->eraseFromParent(); } - if (supportsCOMDAT() && GV->isWeakForLinker() && - !GV->hasAvailableExternallyLinkage()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + maybeSetTrivialComdat(*GV); return GV; } @@ -1985,6 +1982,14 @@ GO.setComdat(TheModule.getOrInsertComdat(GO.getName())); } +void CodeGenModule::maybeSetTrivialComdat(llvm::GlobalObject &GO) { + if (!supportsCOMDAT()) + return; + if (GO.isWeakForLinker() && !GO.hasAvailableExternallyLinkage()) { + GO.setComdat(getModule().getOrInsertComdat(GO.getName())); + } +} + void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = nullptr; QualType ASTTy = D->getType(); @@ -2924,10 +2929,7 @@ nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace); GV->setAlignment(Alignment); GV->setUnnamedAddr(true); - if (GV->isWeakForLinker()) { - assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals"); - GV->setComdat(M.getOrInsertComdat(GV->getName())); - } + CGM.maybeSetTrivialComdat(*GV); return GV; } @@ -3109,8 +3111,7 @@ setGlobalVisibility(GV, VD); GV->setAlignment( getContext().getTypeAlignInChars(MaterializedType).getQuantity()); - if (supportsCOMDAT() && GV->isWeakForLinker()) - GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); + maybeSetTrivialComdat(*GV); if (VD->getTLSKind()) setTLSMode(GV, *VD); Slot = GV; Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -1328,8 +1328,7 @@ // Set the correct linkage. VTable->setLinkage(Linkage); - if (CGM.supportsCOMDAT() && VTable->isWeakForLinker()) - VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName())); + CGM.maybeSetTrivialComdat(*VTable); // Set the right visibility. CGM.setGlobalVisibility(VTable, RD); @@ -1796,8 +1795,8 @@ if (!D.isLocalVarDecl() && C) { guard->setComdat(C); CGF.CurFn->setComdat(C); - } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) { - guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName())); + } else { + CGM.maybeSetTrivialComdat(*guard); } CGM.setStaticLocalDeclGuardAddress(&D, guard); @@ -2803,8 +2802,7 @@ new llvm::GlobalVariable(M, Init->getType(), /*Constant=*/true, Linkage, Init, Name); - if (CGM.supportsCOMDAT() && GV->isWeakForLinker()) - GV->setComdat(M.getOrInsertComdat(GV->getName())); + CGM.maybeSetTrivialComdat(*GV); // If there's already an old global variable, replace it with the new one. if (OldGV) { @@ -3598,8 +3596,7 @@ // we don't want it to turn into an exported symbol. fn->setLinkage(llvm::Function::LinkOnceODRLinkage); fn->setVisibility(llvm::Function::HiddenVisibility); - if (CGM.supportsCOMDAT()) - fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName())); + CGM.maybeSetTrivialComdat(*fn); // Set up the function. llvm::BasicBlock *entry = Index: test/CodeGenCXX/thunks.cpp =================================================================== --- test/CodeGenCXX/thunks.cpp +++ test/CodeGenCXX/thunks.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT namespace Test1 { @@ -361,6 +361,28 @@ // CHECK: declare void @_ZThn8_N6Test151C1fEiz } +namespace Test16 { + +// Check that the thunk for 'B::f' has available_externally linkage +// and is not in a comdat. + +template +struct A { + virtual void f(); +}; + +template +struct B : virtual A { + virtual void f() { } +}; + +extern template struct B; + +void f(B b) { + b.f(); +} +} + /**** The following has to go at the end of the file ****/ // This is from Test5: @@ -371,4 +393,7 @@ // CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv // CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv +// CHECKOPT-LABEL: define available_externally void @_ZTv0_n24_N6Test161BIiE1fEv +// CHECKOPT-NOT: comdat + // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }