[flang-commits] [flang] [Flang][#212316] Fix -Wunused-template errors under -Werror (PR #218985)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 2 05:19:18 PDT 2026


https://github.com/laoshd updated https://github.com/llvm/llvm-project/pull/218985

>From f63def66285bb16c811d4d5c4e33005d762bee6f Mon Sep 17 00:00:00 2001
From: Shandong Lao <shandong.lao at hpe.com>
Date: Wed, 26 Aug 2026 11:46:48 -0500
Subject: [PATCH 1/3] [Flang][#212316] Fix -Wunused-template errors under
 -Werror

Some function templates with internal linkage are never instantiated in
their translation unit, which triggers -Wunused-template. With clang
builds that enable this warning by default and -DFLANG_ENABLE_WERROR=ON,
these become fatal errors.

Fix each case with the minimal change that preserves semantics:
- Drop 'static' (give external linkage) for free function templates at
  namespace/file scope: DirectivesCommon.h, PFTBuilder.h, RTBuilder.h,
  fold-reduction.h, formatting.cpp, check-cuda.cpp, resolve-directives.cpp.
- Add [[maybe_unused]] where dropping 'static' would change linkage/ODR
  semantics (member, anonymous-namespace, or global generic-named
  templates): ConvertType.cpp, IO.cpp, CUFAllocationConversion.cpp,
  openmp-utils.cpp.

No functional change. With AI assistance.
---
 flang/include/flang/Lower/DirectivesCommon.h         |  4 ++--
 flang/include/flang/Lower/PFTBuilder.h               |  2 +-
 .../flang/Optimizer/Builder/Runtime/RTBuilder.h      |  4 ++--
 flang/lib/Evaluate/fold-reduction.h                  | 12 ++++++------
 flang/lib/Evaluate/formatting.cpp                    |  4 ++--
 flang/lib/Lower/ConvertType.cpp                      |  3 ++-
 flang/lib/Lower/IO.cpp                               |  5 +++--
 .../Transforms/CUDA/CUFAllocationConversion.cpp      |  2 +-
 flang/lib/Semantics/check-cuda.cpp                   |  2 +-
 flang/lib/Semantics/openmp-utils.cpp                 |  6 ++++--
 flang/lib/Semantics/resolve-directives.cpp           |  2 +-
 11 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/flang/include/flang/Lower/DirectivesCommon.h b/flang/include/flang/Lower/DirectivesCommon.h
index 6f6089a4ffb6c..ac129ef18d7e0 100644
--- a/flang/include/flang/Lower/DirectivesCommon.h
+++ b/flang/include/flang/Lower/DirectivesCommon.h
@@ -75,11 +75,11 @@ getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
 
 namespace detail {
 template <typename T> //
-static T &&AsRvalueRef(T &&t) {
+T &&AsRvalueRef(T &&t) {
   return std::move(t);
 }
 template <typename T> //
-static T AsRvalueRef(T &t) {
+T AsRvalueRef(T &t) {
   return t;
 }
 template <typename T> //
diff --git a/flang/include/flang/Lower/PFTBuilder.h b/flang/include/flang/Lower/PFTBuilder.h
index 8a59dd6638b71..f34024a5ed903 100644
--- a/flang/include/flang/Lower/PFTBuilder.h
+++ b/flang/include/flang/Lower/PFTBuilder.h
@@ -849,7 +849,7 @@ struct Program {
 /// Helper to get location from FunctionLikeUnit/ModuleLikeUnit begin/end
 /// statements.
 template <typename T>
-static parser::CharBlock stmtSourceLoc(const T &stmt) {
+parser::CharBlock stmtSourceLoc(const T &stmt) {
   return stmt.visit(common::visitors{[](const auto &x) { return x.source; }});
 }
 
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index e2131aa7708a3..f18b09fb3fd93 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -843,7 +843,7 @@ struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
 /// Get (or generate) the MLIR FuncOp for a given runtime function. Its template
 /// argument is intended to be of the form: <mkRTKey(runtime function name)>.
 template <typename RuntimeEntry>
-static mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
+mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
                                          fir::FirOpBuilder &builder,
                                          bool isIO = false) {
   using namespace Fortran::runtime;
@@ -857,7 +857,7 @@ static mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
 
 /// Get (or generate) the MLIR FuncOp for a given IO runtime function.
 template <typename E>
-static mlir::func::FuncOp getIORuntimeFunc(mlir::Location loc,
+mlir::func::FuncOp getIORuntimeFunc(mlir::Location loc,
                                            fir::FirOpBuilder &builder) {
   return getRuntimeFunc<E>(loc, builder, /*isIO=*/true);
 }
diff --git a/flang/lib/Evaluate/fold-reduction.h b/flang/lib/Evaluate/fold-reduction.h
index a068364135295..566e04ed772bf 100644
--- a/flang/lib/Evaluate/fold-reduction.h
+++ b/flang/lib/Evaluate/fold-reduction.h
@@ -15,7 +15,7 @@ namespace Fortran::evaluate {
 
 // DOT_PRODUCT
 template <typename T>
-static Expr<T> FoldDotProduct(
+Expr<T> FoldDotProduct(
     FoldingContext &context, FunctionRef<T> &&funcRef) {
   using Element = typename Constant<T>::Element;
   auto args{funcRef.arguments()};
@@ -132,7 +132,7 @@ template <typename T> struct ArrayAndMask {
   Constant<LogicalResult> mask;
 };
 template <typename T>
-static std::optional<ArrayAndMask<T>> ProcessReductionArgs(
+std::optional<ArrayAndMask<T>> ProcessReductionArgs(
     FoldingContext &context, ActualArguments &arg, std::optional<int> &dim,
     int arrayIndex, std::optional<int> dimIndex = std::nullopt,
     std::optional<int> maskIndex = std::nullopt) {
@@ -174,7 +174,7 @@ static std::optional<ArrayAndMask<T>> ProcessReductionArgs(
 // operator()(Scalar<T> &, const ConstantSubscripts &, bool first)
 // and Done(Scalar<T> &).
 template <typename T, typename ACCUMULATOR, typename ARRAY>
-static Constant<T> DoReduction(const Constant<ARRAY> &array,
+Constant<T> DoReduction(const Constant<ARRAY> &array,
     const Constant<LogicalResult> &mask, std::optional<int> &dim,
     const Scalar<T> &identity, ACCUMULATOR &accumulator) {
   ConstantSubscripts at{array.lbounds()};
@@ -265,7 +265,7 @@ template <typename T, bool ABS = false> class MaxvalMinvalAccumulator {
 };
 
 template <typename T>
-static Expr<T> FoldMaxvalMinval(FoldingContext &context, FunctionRef<T> &&ref,
+Expr<T> FoldMaxvalMinval(FoldingContext &context, FunctionRef<T> &&ref,
     RelationalOperator opr, const Scalar<T> &identity) {
   static_assert(T::category == TypeCategory::Integer ||
       T::category == TypeCategory::Unsigned ||
@@ -309,7 +309,7 @@ template <typename T> class ProductAccumulator {
 };
 
 template <typename T>
-static Expr<T> FoldProduct(
+Expr<T> FoldProduct(
     FoldingContext &context, FunctionRef<T> &&ref, Scalar<T> identity) {
   static_assert(T::category == TypeCategory::Integer ||
       T::category == TypeCategory::Unsigned ||
@@ -371,7 +371,7 @@ template <typename T> class SumAccumulator {
 };
 
 template <typename T>
-static Expr<T> FoldSum(FoldingContext &context, FunctionRef<T> &&ref) {
+Expr<T> FoldSum(FoldingContext &context, FunctionRef<T> &&ref) {
   static_assert(T::category == TypeCategory::Integer ||
       T::category == TypeCategory::Unsigned ||
       T::category == TypeCategory::Real ||
diff --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp
index fcedd15ee1791..1187daa5620cc 100644
--- a/flang/lib/Evaluate/formatting.cpp
+++ b/flang/lib/Evaluate/formatting.cpp
@@ -414,7 +414,7 @@ template <typename T> static Precedence ToPrecedence(const Expr<T> &expr) {
   return common::visit([](const auto &x) { return ToPrecedence(x); }, expr.u);
 }
 
-template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
+template <typename T> bool IsNegatedScalarConstant(const Expr<T> &expr) {
   static constexpr TypeCategory cat{T::category};
   if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) {
     if (auto n{GetScalarConstantValue<T>(expr)}) {
@@ -425,7 +425,7 @@ template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
 }
 
 template <TypeCategory CAT>
-static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
+bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
   return common::visit(
       [](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u);
 }
diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index 0fdbdfcc74424..ca4f19c6fcb92 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -536,7 +536,8 @@ struct TypeBuilderImpl {
   }
 
   template <typename A>
-  Fortran::lower::LenParameterTy getCharacterLength(const A &expr) {
+  [[maybe_unused]] Fortran::lower::LenParameterTy getCharacterLength(
+      const A &expr) {
     return fir::SequenceType::getUnknownExtent();
   }
 
diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index 490db8cc1d1ba..8b44fe27ce9a8 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -126,14 +126,15 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter,
 
 /// Helper function to retrieve the name of the IO function given the key `A`
 template <typename A>
-static constexpr const char *getName() {
+[[maybe_unused]] static constexpr const char *getName() {
   return std::get<A>(Fortran::lower::newIOTable).name;
 }
 
 /// Helper function to retrieve the type model signature builder of the IO
 /// function as defined by the key `A`
 template <typename A>
-static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
+[[maybe_unused]] static constexpr fir::runtime::FuncTypeBuilderFunc
+getTypeModel() {
   return std::get<A>(Fortran::lower::newIOTable).getTypeModel();
 }
 
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp
index b75d289faca7a..c8fb7b0797188 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFAllocationConversion.cpp
@@ -43,7 +43,7 @@ using namespace Fortran::runtime::cuda;
 namespace {
 
 template <typename OpTy>
-static bool isPinned(OpTy op) {
+[[maybe_unused]] bool isPinned(OpTy op) {
   if (op.getDataAttr() && *op.getDataAttr() == cuf::DataAttribute::Pinned)
     return true;
   return false;
diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index 8922e0eb559e8..5d432fd1f3db3 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -208,7 +208,7 @@ struct FindHostArray
 };
 
 template <typename A>
-static MaybeMsg CheckUnwrappedExpr(
+MaybeMsg CheckUnwrappedExpr(
     SemanticsContext &context, const A &x, bool allowHostCallees = false) {
   if (const auto *expr{parser::Unwrap<parser::Expr>(x)}) {
     return DeviceExprChecker{context, allowHostCallees}(expr->typedExpr);
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index dc3d5a302e841..4050d95fd1ea3 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -462,11 +462,13 @@ struct ContiguousHelper {
       : fctx_(context.foldingContext()) {}
 
   template <typename Contained>
-  std::optional<bool> Visit(const common::Indirection<Contained> &x) {
+  [[maybe_unused]] std::optional<bool> Visit(
+      const common::Indirection<Contained> &x) {
     return Visit(x.value());
   }
   template <typename Contained>
-  std::optional<bool> Visit(const common::Reference<Contained> &x) {
+  [[maybe_unused]] std::optional<bool> Visit(
+      const common::Reference<Contained> &x) {
     return Visit(x.get());
   }
   template <typename T> std::optional<bool> Visit(const evaluate::Expr<T> &x) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 532f1f821b8f2..67678cdd68a0b 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -36,7 +36,7 @@
 namespace Fortran::semantics {
 
 template <typename T>
-static Scope *GetScope(SemanticsContext &context, const T &x) {
+Scope *GetScope(SemanticsContext &context, const T &x) {
   if (auto source{GetLastSource(x)}) {
     return &context.FindScope(*source);
   } else {

>From f621113b4b915cd4147906d9daf57ff36785e5d8 Mon Sep 17 00:00:00 2001
From: Shandong Lao <shandong.lao at hpe.com>
Date: Wed, 26 Aug 2026 13:13:08 -0500
Subject: [PATCH 2/3] [Flang][#212316] Corrects code formats.

---
 .../include/flang/Optimizer/Builder/Runtime/RTBuilder.h  | 6 +++---
 flang/lib/Evaluate/fold-reduction.h                      | 9 ++++-----
 flang/lib/Lower/ConvertType.cpp                          | 4 ++--
 flang/lib/Semantics/resolve-directives.cpp               | 3 +--
 4 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index f18b09fb3fd93..67bdf6867251a 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -844,8 +844,8 @@ struct RuntimeTableEntry<RuntimeTableKey<KT>, RuntimeIdentifier<Cs...>> {
 /// argument is intended to be of the form: <mkRTKey(runtime function name)>.
 template <typename RuntimeEntry>
 mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
-                                         fir::FirOpBuilder &builder,
-                                         bool isIO = false) {
+                                  fir::FirOpBuilder &builder,
+                                  bool isIO = false) {
   using namespace Fortran::runtime;
   auto name = RuntimeEntry::name;
   auto func = builder.getNamedFunction(name);
@@ -858,7 +858,7 @@ mlir::func::FuncOp getRuntimeFunc(mlir::Location loc,
 /// Get (or generate) the MLIR FuncOp for a given IO runtime function.
 template <typename E>
 mlir::func::FuncOp getIORuntimeFunc(mlir::Location loc,
-                                           fir::FirOpBuilder &builder) {
+                                    fir::FirOpBuilder &builder) {
   return getRuntimeFunc<E>(loc, builder, /*isIO=*/true);
 }
 
diff --git a/flang/lib/Evaluate/fold-reduction.h b/flang/lib/Evaluate/fold-reduction.h
index 566e04ed772bf..aef5e93287297 100644
--- a/flang/lib/Evaluate/fold-reduction.h
+++ b/flang/lib/Evaluate/fold-reduction.h
@@ -15,8 +15,7 @@ namespace Fortran::evaluate {
 
 // DOT_PRODUCT
 template <typename T>
-Expr<T> FoldDotProduct(
-    FoldingContext &context, FunctionRef<T> &&funcRef) {
+Expr<T> FoldDotProduct(FoldingContext &context, FunctionRef<T> &&funcRef) {
   using Element = typename Constant<T>::Element;
   auto args{funcRef.arguments()};
   CHECK(args.size() == 2);
@@ -132,9 +131,9 @@ template <typename T> struct ArrayAndMask {
   Constant<LogicalResult> mask;
 };
 template <typename T>
-std::optional<ArrayAndMask<T>> ProcessReductionArgs(
-    FoldingContext &context, ActualArguments &arg, std::optional<int> &dim,
-    int arrayIndex, std::optional<int> dimIndex = std::nullopt,
+std::optional<ArrayAndMask<T>> ProcessReductionArgs(FoldingContext &context,
+    ActualArguments &arg, std::optional<int> &dim, int arrayIndex,
+    std::optional<int> dimIndex = std::nullopt,
     std::optional<int> maskIndex = std::nullopt) {
   if (arg.empty()) {
     return std::nullopt;
diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp
index ca4f19c6fcb92..8bb8f359b2e79 100644
--- a/flang/lib/Lower/ConvertType.cpp
+++ b/flang/lib/Lower/ConvertType.cpp
@@ -536,8 +536,8 @@ struct TypeBuilderImpl {
   }
 
   template <typename A>
-  [[maybe_unused]] Fortran::lower::LenParameterTy getCharacterLength(
-      const A &expr) {
+  [[maybe_unused]] Fortran::lower::LenParameterTy
+  getCharacterLength(const A &expr) {
     return fir::SequenceType::getUnknownExtent();
   }
 
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 67678cdd68a0b..af6640eb40dac 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -35,8 +35,7 @@
 
 namespace Fortran::semantics {
 
-template <typename T>
-Scope *GetScope(SemanticsContext &context, const T &x) {
+template <typename T> Scope *GetScope(SemanticsContext &context, const T &x) {
   if (auto source{GetLastSource(x)}) {
     return &context.FindScope(*source);
   } else {

>From 27ef1525cf12bbb7844cb1d17a2b7436f07aceae Mon Sep 17 00:00:00 2001
From: Shandong Lao <shandong.lao at hpe.com>
Date: Wed, 2 Sep 2026 07:18:33 -0500
Subject: [PATCH 3/3] [FLANG][OMP] #219234: Add error message for invalid
 dependence type in taskwait construct.

---
 flang/lib/Semantics/check-omp-structure.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 274efa64d03d0..762c9bf8a9be7 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -5116,6 +5116,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
       context_.Say(GetContext().clauseSource,
           "The SINK and SOURCE dependence types can only be used with the ORDERED directive, used here in the %s construct"_err_en_US,
           parser::omp::GetUpperName(dir, version));
+    } else if (dir == llvm::omp::OMPD_taskwait &&
+        taskDep->GetTaskDepType() ==
+            parser::OmpTaskDependenceType::Value::Mutexinoutset) {
+      // A depend clause on a taskwait construct must not have
+      // mutexinoutset as dependence-type.
+      context_.Say(GetContext().clauseSource,
+          "A DEPEND clause on a TASKWAIT construct must not have %s as dependence type"_err_en_US,
+          "MUTEXINOUTSET");
     }
   }
   if (taskDep) {



More information about the flang-commits mailing list