Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -2293,6 +2293,18 @@ if (auto *SA = D->getAttr()) if (!D->getAttr()) F->addFnAttr("implicit-section-name", SA->getName()); + // If we have -ffunction-sections, and also an explicit section name, + // put the function into a section group so that various linker GC + // operations will still work with this function. + if (CodeGenOpts.FunctionSections && getTriple().supportsCOMDAT() && + D->hasAttr()) { + // Don't replace a real comdat. + if (!F->getComdat()) { + llvm::Comdat *C = TheModule.getOrInsertComdat(F->getName()); + C->setSelectionKind(llvm::Comdat::NoDeduplicate); + F->setComdat(C); + } + } llvm::AttrBuilder Attrs(F->getContext()); if (GetCPUAndFeaturesAttributes(GD, Attrs)) { Index: clang/test/CodeGen/section-attr-comdat.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/section-attr-comdat.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple=x86_64-linux -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=NOCOMDAT +// RUN: %clang_cc1 -triple=x86_64-linux -emit-llvm -ffunction-sections %s -o - | \ +// RUN: FileCheck %s --check-prefix=COMDAT + +// template function = comdat always. +template +__attribute__((section("foo"))) T ftemplate(T a) { return a + 1; } +__attribute__((section("foo"))) int fglobal(int a) { return ftemplate(a) + 2; } + +// NOCOMDAT-DAG: ${{.*}}ftemplate{{.*}} = comdat any +// NOCOMDAT-DAG: define {{.*}}ftemplate{{.*}} section "foo" comdat { +// NOCOMDAT-DAG: define {{.*}}fglobal{{.*}} section "foo" { + +// COMDAT-DAG: ${{.*}}ftemplate{{.*}} = comdat any +// COMDAT-DAG: ${{.*}}fglobal{{.*}} = comdat nodeduplicate +// COMDAT-DAG: define {{.*}}ftemplate{{.*}} section "foo" comdat { +// COMDAT-DAG: define {{.*}}fglobal{{.*}} section "foo" comdat {