Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -2279,6 +2279,11 @@ if (auto *SA = D->getAttr()) if (!D->getAttr()) F->addFnAttr("implicit-section-name", SA->getName()); + // If we have -ffunction-sections, and an explicit section name, + // and the function is not COMDAT, explicitly retain it. + if (CodeGenOpts.FunctionSections && D->hasAttr() && + !F->getComdat()) + addUsedGlobal(F); llvm::AttrBuilder Attrs(F->getContext()); if (GetCPUAndFeaturesAttributes(GD, Attrs)) { Index: clang/test/CodeGen/section-retain.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/section-retain.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=UNUSED +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -ffunction-sections -o - %s | \ +// RUN: FileCheck %s --check-prefix=USED + +// 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; } + +// UNUSED-NOT: llvm.used +// USED: @llvm.used = {{.*}} [ptr +// USED-NOT: ftemplate +// USED-SAME: fglobal +// USED-NOT: ftemplate +// USED-SAME: ] + +// USED-DAG: define {{.*}}ftemplate{{.*}} section "foo" +// USED-DAG: define {{.*}}fglobal{{.*}} section "foo"