[llvm-branch-commits] [clang] [clang-tools-extra] [compiler-rt] [lldb] [llvm] [mlir] [release/23.x] Backport -Wunused-template fixes (PR #222336)
Med Ismail Bennani via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 9 07:07:34 PDT 2026
https://github.com/medismailben created https://github.com/llvm/llvm-project/pull/222336
`-Wunused-template` was added to `-Wall` by 1529d35adbd6 (reland of #206123, 2026-07-08).
`release/23.x` branched on 2026-07-14, so it inherited the warning enabled. The revert 8710728e0418 (#218638) landed on main 2026-08-25 and was backported here the same day, but it missed the 23.1.0 tag by hours, so **clang 23.1.0 ships with `-Wunused-template` in `-Wall`**. 23.1.1 has it off again.
The practical consequence is that building this branch with a released 23.1.0 compiler and `-Werror` fails, because the tree still contains the violations that were since cleaned up on `main`. Observed failures include:
```
lldb/unittests/TestingSupport/TestUtilities.h:68:48: error: unused function template
'roundtripJSON' [-Werror,-Wunused-template]
llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp:1448:21: error: unused function
template 'DecodeUImm' [-Werror,-Wunused-template]
```
The `roundtripJSON` one alone affects 44 translation units on this branch, since it is a header
included by most of the LLDB unit tests.
This backports the upstream cleanup so 23.x can be built with the compiler it shipped.
>From 0ab67be663a483f21afd10f4e1c7fdd7dca8e28f Mon Sep 17 00:00:00 2001
From: Kyungtak Woo <kevinwkt at google.com>
Date: Wed, 15 Jul 2026 12:57:28 -0600
Subject: [PATCH 01/15] [compiler-rt][tsan] Fix -Wunused-template in
tsan_interface_atomic.cpp (NFC) (#209621)
(cherry picked from commit b74c800578a06bba7b3bacc690cbe493759836a2)
---
.../lib/tsan/rtl/tsan_interface_atomic.cpp | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
index 5c2461634d2d4..798e23088d78e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
@@ -350,12 +350,13 @@ struct OpFetchAdd {
struct OpFetchSub {
template <typename T>
- static T NoTsanAtomic(morder mo, volatile T *a, T v) {
+ [[maybe_unused]] static T NoTsanAtomic(morder mo, volatile T* a, T v) {
return func_sub(a, v);
}
template <typename T>
- static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
+ [[maybe_unused]] static T Atomic(ThreadState* thr, uptr pc, morder mo,
+ volatile T* a, T v) {
return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
}
};
@@ -386,24 +387,26 @@ struct OpFetchOr {
struct OpFetchXor {
template <typename T>
- static T NoTsanAtomic(morder mo, volatile T *a, T v) {
+ [[maybe_unused]] static T NoTsanAtomic(morder mo, volatile T* a, T v) {
return func_xor(a, v);
}
template <typename T>
- static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
+ [[maybe_unused]] static T Atomic(ThreadState* thr, uptr pc, morder mo,
+ volatile T* a, T v) {
return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
}
};
struct OpFetchNand {
template <typename T>
- static T NoTsanAtomic(morder mo, volatile T *a, T v) {
+ [[maybe_unused]] static T NoTsanAtomic(morder mo, volatile T* a, T v) {
return func_nand(a, v);
}
template <typename T>
- static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
+ [[maybe_unused]] static T Atomic(ThreadState* thr, uptr pc, morder mo,
+ volatile T* a, T v) {
return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
}
};
>From cacaf899b3b700127c50c97d1efc93fc0b1590be Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Wed, 15 Jul 2026 12:57:32 -0700
Subject: [PATCH 02/15] [compiler-rt] Fix asan_interceptors.cpp build warning
-Wunused-template (#209750)
mmap_interceptor/munmap_interceptor template functions are instantiated
in sanitizer_common_interceptors.inc only under `#if
SANITIZER_INTERCEPT_MMAP`. Fix `unused function template
'mmap_interceptor'` warning on Windows, which is error under -Werror.
(cherry picked from commit 835ae525713e27aa98c46469792cee980669c6ca)
---
compiler-rt/lib/asan/asan_interceptors.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 5075919a47d50..4e91e34f76cee 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -178,6 +178,7 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void*)
*begin = *end = 0; \
}
+# if SANITIZER_INTERCEPT_MMAP
template <class Mmap>
static void* mmap_interceptor(Mmap real_mmap, void* addr, SIZE_T length,
int prot, int flags, int fd, OFF64_T offset) {
@@ -243,6 +244,7 @@ static int munmap_interceptor(Munmap real_munmap, void* addr, SIZE_T length) {
}
return real_munmap(addr, length);
}
+# endif // SANITIZER_INTERCEPT_MMAP
# define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \
fd, offset) \
>From c0a883a7ac443254b722ef6b746679af5edd1bb6 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 12 Aug 2026 08:41:37 +0900
Subject: [PATCH 03/15] ConstantFPRangeTest.cpp: Hide templates conditionally.
[-Wunused-template] (#215559)
Introduced in #86483. They are referred in `EXPENSIVE_CHECKS`.
(cherry picked from commit 1c33a0f6eb45ba2b52a9989d40ab3b78c051becb)
---
llvm/unittests/IR/ConstantFPRangeTest.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp
index 67fee962379e1..a77d8d76c0aea 100644
--- a/llvm/unittests/IR/ConstantFPRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp
@@ -154,6 +154,7 @@ static void EnumerateConstantFPRanges(Fn TestFn, SparseLevel Level,
/*MayBeSNaN=*/true);
}
+#if defined(EXPENSIVE_CHECKS)
template <typename Fn>
static void EnumerateTwoInterestingConstantFPRanges(Fn TestFn,
SparseLevel Level) {
@@ -165,6 +166,7 @@ static void EnumerateTwoInterestingConstantFPRanges(Fn TestFn,
},
Level, /*IgnoreSNaNs=*/true);
}
+#endif
template <typename Fn>
static void EnumerateValuesInConstantFPRange(const ConstantFPRange &CR,
@@ -203,6 +205,7 @@ static void EnumerateValuesInConstantFPRange(const ConstantFPRange &CR,
}
}
+#if defined(EXPENSIVE_CHECKS)
template <typename Fn>
static bool AnyOfValueInConstantFPRange(const ConstantFPRange &CR, Fn TestFn,
bool IgnoreNaNPayload) {
@@ -245,6 +248,7 @@ static bool AnyOfValueInConstantFPRange(const ConstantFPRange &CR, Fn TestFn,
}
return false;
}
+#endif
TEST_F(ConstantFPRangeTest, Basics) {
EXPECT_TRUE(Full.isFullSet());
>From f9b832174cc45d1cf213e7c132cdbff398826d6e Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 12 Aug 2026 12:01:56 +0900
Subject: [PATCH 04/15] llvm/unittests: Prune unused templates
[-Wunused-template] (#215565)
(cherry picked from commit f47dbac96ee726fbeedfd80dcdcb15b6ad1d658b)
---
llvm/unittests/ADT/SmallVectorTest.cpp | 5 -----
llvm/unittests/IR/IntrinsicsTest.cpp | 3 ---
llvm/unittests/Support/RecyclerTest.cpp | 5 -----
3 files changed, 13 deletions(-)
diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp
index ebecacefcb0c5..4a32c6d2ff08a 100644
--- a/llvm/unittests/ADT/SmallVectorTest.cpp
+++ b/llvm/unittests/ADT/SmallVectorTest.cpp
@@ -1063,11 +1063,6 @@ struct Emplaceable {
: A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
State(ES_Emplaced) {}
- template <class A0Ty, class A1Ty, class A2Ty>
- Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2)
- : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
- A2(std::forward<A2Ty>(A2)), State(ES_Emplaced) {}
-
template <class A0Ty, class A1Ty, class A2Ty, class A3Ty>
Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3)
: A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
diff --git a/llvm/unittests/IR/IntrinsicsTest.cpp b/llvm/unittests/IR/IntrinsicsTest.cpp
index d502bf591b7fa..4556c8e113e14 100644
--- a/llvm/unittests/IR/IntrinsicsTest.cpp
+++ b/llvm/unittests/IR/IntrinsicsTest.cpp
@@ -57,9 +57,6 @@ class IntrinsicsTest : public ::testing::Test {
}
return Builder.CreateCall(Decl, ProcessedArgs);
}
- template <typename T> void checkIsa(const Instruction &I) {
- EXPECT_TRUE(isa<T>(I));
- }
};
TEST(IntrinsicNameLookup, Basic) {
diff --git a/llvm/unittests/Support/RecyclerTest.cpp b/llvm/unittests/Support/RecyclerTest.cpp
index 696e397d3f10e..160b56b049adb 100644
--- a/llvm/unittests/Support/RecyclerTest.cpp
+++ b/llvm/unittests/Support/RecyclerTest.cpp
@@ -30,11 +30,6 @@ class DecoratedMallocAllocator : public MallocAllocator {
DeallocCount++;
MallocAllocator::Deallocate(Ptr, Size, Alignment);
}
-
- template <typename T> void Deallocate(T *Ptr) {
- DeallocCount++;
- MallocAllocator::Deallocate(Ptr);
- }
};
TEST(RecyclerTest, RecycleAllocation) {
>From 12b61477c48ae9635b28c65bee27537b0e1291a0 Mon Sep 17 00:00:00 2001
From: Aditya Medhane <sherlockedaditya at gmail.com>
Date: Wed, 12 Aug 2026 09:34:08 +0530
Subject: [PATCH 05/15] [mlir][NFC] Remove internal linkage from reshape op
helper templates (#214759)
Another case of the cleanup done for #208001, which enabled
-Wunused-template under -Wall. Both helpers are `static` in
ReshapeOpsUtils.h, which reaches many TUs via Linalg.h, Tensor.h and
MemRef.h, so clang warns wherever they are not instantiated. Dropping
`static` gives them vague linkage.
(cherry picked from commit 1376072719a09cf6cbde3d44dab860cd9e1f3427)
---
mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
index 2e8c0e269995e..6f58ed48fd64f 100644
--- a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
+++ b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h
@@ -84,8 +84,8 @@ bool isReassociationValid(ArrayRef<AffineMap> reassociation,
int *invalidIndex = nullptr);
template <typename ReshapeOpTy, typename InverseReshapeOpTy>
-static OpFoldResult foldReshapeOp(ReshapeOpTy reshapeOp,
- ArrayRef<Attribute> operands) {
+OpFoldResult foldReshapeOp(ReshapeOpTy reshapeOp,
+ ArrayRef<Attribute> operands) {
// Fold identity reshape.
if (reshapeOp.getSrcType() == reshapeOp.getType())
return reshapeOp.getSrc();
@@ -140,8 +140,8 @@ static OpFoldResult foldReshapeOp(ReshapeOpTy reshapeOp,
/// Common verifier for reshape-like types. Fills `expandedType` and
///`collapsedType` with the proper `src` or `result` type.
template <typename Op, typename T>
-static LogicalResult verifyReshapeLikeTypes(Op op, T expandedType,
- T collapsedType, bool isExpansion) {
+LogicalResult verifyReshapeLikeTypes(Op op, T expandedType, T collapsedType,
+ bool isExpansion) {
unsigned expandedRank = expandedType.getRank();
unsigned collapsedRank = collapsedType.getRank();
>From ccb6596f88b337b91c80f893ffe5460b41458464 Mon Sep 17 00:00:00 2001
From: Aditya Medhane <sherlockedaditya at gmail.com>
Date: Wed, 12 Aug 2026 09:34:38 +0530
Subject: [PATCH 06/15] [mlir][NFC] Remove internal linkage from core header
function templates (#214756)
These are more of the cases fixed alongside #208001, which enabled
-Wunused-template under -Wall. Each template is `static` in a widely
included header, so clang warns in every TU that includes it without
instantiating it. Dropping `static` gives them vague linkage and
silences the warning.
(cherry picked from commit da6918474bb7fae41124521f0c8e225c7f6c65cd)
---
.../mlir/Bytecode/BytecodeImplementation.h | 4 ++--
mlir/include/mlir/IR/AffineMap.h | 4 ++--
mlir/include/mlir/IR/OpDefinition.h | 13 ++++++-------
mlir/include/mlir/IR/PDLPatternMatch.h.inc | 19 ++++++++-----------
mlir/include/mlir/Pass/PassOptions.h | 6 +++---
5 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/mlir/include/mlir/Bytecode/BytecodeImplementation.h b/mlir/include/mlir/Bytecode/BytecodeImplementation.h
index d8d0ca7b3b9f7..93045439d2ba4 100644
--- a/mlir/include/mlir/Bytecode/BytecodeImplementation.h
+++ b/mlir/include/mlir/Bytecode/BytecodeImplementation.h
@@ -443,8 +443,8 @@ class DialectBytecodeWriter {
/// Helper for resource handle reading that returns LogicalResult.
template <typename T, typename... Ts>
-static LogicalResult readResourceHandle(DialectBytecodeReader &reader,
- FailureOr<T> &value, Ts &&...params) {
+LogicalResult readResourceHandle(DialectBytecodeReader &reader,
+ FailureOr<T> &value, Ts &&...params) {
FailureOr<T> handle = reader.readResourceHandle<T>();
if (failed(handle))
return failure();
diff --git a/mlir/include/mlir/IR/AffineMap.h b/mlir/include/mlir/IR/AffineMap.h
index 0643f0a4b308f..aa932e7bcda6c 100644
--- a/mlir/include/mlir/IR/AffineMap.h
+++ b/mlir/include/mlir/IR/AffineMap.h
@@ -694,8 +694,8 @@ SmallVector<T> applyPermutationMap(AffineMap map, llvm::ArrayRef<T> source) {
/// Calculates maximum dimension and symbol positions from the expressions
/// in `exprsLists` and stores them in `maxDim` and `maxSym` respectively.
template <typename AffineExprContainer>
-static void getMaxDimAndSymbol(ArrayRef<AffineExprContainer> exprsList,
- int64_t &maxDim, int64_t &maxSym) {
+void getMaxDimAndSymbol(ArrayRef<AffineExprContainer> exprsList,
+ int64_t &maxDim, int64_t &maxSym) {
for (const auto &exprs : exprsList) {
for (auto expr : exprs) {
expr.walk([&maxDim, &maxSym](AffineExpr e) {
diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index bd7fa1ffd4428..fe2fa0a0ccd23 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -1607,8 +1607,8 @@ using detect_has_any_fold_trait =
/// Returns the result of folding a trait that implements a `foldTrait` function
/// that is specialized for operations that have a single result.
template <typename Trait>
-static std::enable_if_t<detect_has_single_result_fold_trait<Trait>::value,
- LogicalResult>
+std::enable_if_t<detect_has_single_result_fold_trait<Trait>::value,
+ LogicalResult>
foldTrait(Operation *op, ArrayRef<Attribute> operands,
SmallVectorImpl<OpFoldResult> &results) {
assert(op->hasTrait<OpTrait::OneResult>() &&
@@ -1629,7 +1629,7 @@ foldTrait(Operation *op, ArrayRef<Attribute> operands,
/// Returns the result of folding a trait that implements a generalized
/// `foldTrait` function that is supports any operation type.
template <typename Trait>
-static std::enable_if_t<detect_has_fold_trait<Trait>::value, LogicalResult>
+std::enable_if_t<detect_has_fold_trait<Trait>::value, LogicalResult>
foldTrait(Operation *op, ArrayRef<Attribute> operands,
SmallVectorImpl<OpFoldResult> &results) {
// If a previous trait has already been folded and replaced this operation, we
@@ -1637,8 +1637,7 @@ foldTrait(Operation *op, ArrayRef<Attribute> operands,
return results.empty() ? Trait::foldTrait(op, operands, results) : failure();
}
template <typename Trait>
-static inline std::enable_if_t<!detect_has_any_fold_trait<Trait>::value,
- LogicalResult>
+inline std::enable_if_t<!detect_has_any_fold_trait<Trait>::value, LogicalResult>
foldTrait(Operation *, ArrayRef<Attribute>, SmallVectorImpl<OpFoldResult> &) {
return failure();
}
@@ -1646,8 +1645,8 @@ foldTrait(Operation *, ArrayRef<Attribute>, SmallVectorImpl<OpFoldResult> &) {
/// Given a tuple type containing a set of traits, return the result of folding
/// the given operation.
template <typename... Ts>
-static LogicalResult foldTraits(Operation *op, ArrayRef<Attribute> operands,
- SmallVectorImpl<OpFoldResult> &results) {
+LogicalResult foldTraits(Operation *op, ArrayRef<Attribute> operands,
+ SmallVectorImpl<OpFoldResult> &results) {
return success((succeeded(foldTrait<Ts>(op, operands, results)) || ...));
}
diff --git a/mlir/include/mlir/IR/PDLPatternMatch.h.inc b/mlir/include/mlir/IR/PDLPatternMatch.h.inc
index aa74202178a9b..a39a46382affd 100644
--- a/mlir/include/mlir/IR/PDLPatternMatch.h.inc
+++ b/mlir/include/mlir/IR/PDLPatternMatch.h.inc
@@ -642,8 +642,8 @@ void assertArgs(PatternRewriter &rewriter, ArrayRef<PDLValue> values,
/// Store a single result within the result list.
template <typename T>
-static LogicalResult processResults(PatternRewriter &rewriter,
- PDLResultList &results, T &&value) {
+LogicalResult processResults(PatternRewriter &rewriter, PDLResultList &results,
+ T &&value) {
ProcessPDLValue<T>::processAsResult(rewriter, results,
std::forward<T>(value));
return success();
@@ -651,9 +651,8 @@ static LogicalResult processResults(PatternRewriter &rewriter,
/// Store a std::pair<> as individual results within the result list.
template <typename T1, typename T2>
-static LogicalResult processResults(PatternRewriter &rewriter,
- PDLResultList &results,
- std::pair<T1, T2> &&pair) {
+LogicalResult processResults(PatternRewriter &rewriter, PDLResultList &results,
+ std::pair<T1, T2> &&pair) {
if (failed(processResults(rewriter, results, std::move(pair.first))) ||
failed(processResults(rewriter, results, std::move(pair.second))))
return failure();
@@ -662,9 +661,8 @@ static LogicalResult processResults(PatternRewriter &rewriter,
/// Store a std::tuple<> as individual results within the result list.
template <typename... Ts>
-static LogicalResult processResults(PatternRewriter &rewriter,
- PDLResultList &results,
- std::tuple<Ts...> &&tuple) {
+LogicalResult processResults(PatternRewriter &rewriter, PDLResultList &results,
+ std::tuple<Ts...> &&tuple) {
auto applyFn = [&](auto &&...args) {
return (succeeded(processResults(rewriter, results, std::move(args))) &&
...);
@@ -679,9 +677,8 @@ inline LogicalResult processResults(PatternRewriter &rewriter,
return result;
}
template <typename T>
-static LogicalResult processResults(PatternRewriter &rewriter,
- PDLResultList &results,
- FailureOr<T> &&result) {
+LogicalResult processResults(PatternRewriter &rewriter, PDLResultList &results,
+ FailureOr<T> &&result) {
if (failed(result))
return failure();
return processResults(rewriter, results, std::move(*result));
diff --git a/mlir/include/mlir/Pass/PassOptions.h b/mlir/include/mlir/Pass/PassOptions.h
index 0c71f78b52d3d..4e4652ee8eef1 100644
--- a/mlir/include/mlir/Pass/PassOptions.h
+++ b/mlir/include/mlir/Pass/PassOptions.h
@@ -57,11 +57,11 @@ using has_stream_operator = llvm::is_detected<has_stream_operator_trait, T>;
/// Utility methods for printing option values.
template <typename ParserT>
-static void printOptionValue(raw_ostream &os, const bool &value) {
+void printOptionValue(raw_ostream &os, const bool &value) {
os << (value ? StringRef("true") : StringRef("false"));
}
template <typename ParserT>
-static void printOptionValue(raw_ostream &os, const std::string &str) {
+void printOptionValue(raw_ostream &os, const std::string &str) {
// Check if the string needs to be escaped before writing it to the ostream.
const size_t spaceIndex = str.find_first_of(' ');
const size_t escapeIndex =
@@ -75,7 +75,7 @@ static void printOptionValue(raw_ostream &os, const std::string &str) {
os << "}";
}
template <typename ParserT, typename DataT>
-static void printOptionValue(raw_ostream &os, const DataT &value) {
+void printOptionValue(raw_ostream &os, const DataT &value) {
if constexpr (has_stream_operator<DataT>::value)
os << value;
else
>From c35cbdfe269838dacd8e8b850fe1449bc82071a3 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 13 Aug 2026 07:07:40 +0900
Subject: [PATCH 07/15] HashingTest.cpp: Prune
`StructWithHashBuilderAndHashValueSupport::hash_value()` [-Wunused-template]
(#215561)
The customized version of `hash_value()` won't use it.
(cherry picked from commit 819ed9f5cb5fc09c23b5969c3b979b286e7ca309)
---
llvm/unittests/ADT/HashingTest.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/llvm/unittests/ADT/HashingTest.cpp b/llvm/unittests/ADT/HashingTest.cpp
index b6daf8f4695f8..d2fc1da9a0f60 100644
--- a/llvm/unittests/ADT/HashingTest.cpp
+++ b/llvm/unittests/ADT/HashingTest.cpp
@@ -390,9 +390,6 @@ TEST(HashingTest, HashWithHashBuilder) {
struct StructWithHashBuilderAndHashValueSupport {
char C;
int I;
- template <typename HasherT, llvm::endianness Endianness>
- friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
- const StructWithHashBuilderAndHashValueSupport &Value) {}
friend hash_code
hash_value(const StructWithHashBuilderAndHashValueSupport &Value) {
return 0xbeef;
>From 0f1610d40a04692311b18007a51187c4062705ec Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 13 Aug 2026 07:11:46 +0900
Subject: [PATCH 08/15] AArch64Disassembler.cpp: Prune `DecodeUImm`
[-Wunused-template] (#215558)
This has been introduced in #181386.
(cherry picked from commit 8aedcecc5bf1b14187ce34d510c6c66d7e8b6d10)
---
.../AArch64/Disassembler/AArch64Disassembler.cpp | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 3170ad8c99774..e7820f7d6c5b1 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -38,9 +38,6 @@ using DecodeStatus = MCDisassembler::DecodeStatus;
template <int Bits>
static DecodeStatus DecodeSImm(MCInst &Inst, uint64_t Imm, uint64_t Address,
const MCDisassembler *Decoder);
-template <int Bits>
-static DecodeStatus DecodeUImm(MCInst &Inst, uint64_t Imm, uint64_t Address,
- const MCDisassembler *Decoder);
#define Success MCDisassembler::Success
#define Fail MCDisassembler::Fail
@@ -1444,16 +1441,6 @@ static DecodeStatus DecodeSImm(MCInst &Inst, uint64_t Imm, uint64_t Address,
return Success;
}
-template <int Bits>
-static DecodeStatus DecodeUImm(MCInst &Inst, uint64_t Imm, uint64_t Address,
- const MCDisassembler *Decoder) {
- if (Imm & ~((1ULL << Bits) - 1))
- return Fail;
-
- Inst.addOperand(MCOperand::createImm(Imm));
- return Success;
-}
-
// Decode 8-bit signed/unsigned immediate for a given element width.
template <int ElementWidth>
static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, unsigned Imm, uint64_t Addr,
>From 566c318dc9cc21d8648571e48c39bb0b517ed8c2 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 15 Aug 2026 19:04:30 +0900
Subject: [PATCH 09/15] SignAnalysisTest.cpp: Suppress a warning.
[-Wunused-template] (#215563)
(cherry picked from commit 7afbf0f3e79f00fda49202214dd2917805b8529d)
---
clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp
index b8fc528dbdce0..08c1bdc4f58ed 100644
--- a/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp
@@ -444,6 +444,7 @@ void runDataflow(llvm::StringRef Code, Matcher Match,
// FIXME add this to testing support.
template <typename NodeType, typename MatcherType>
+[[maybe_unused]]
const NodeType *findFirst(ASTContext &ASTCtx, const MatcherType &M) {
auto TargetNodes = match(M.bind("v"), ASTCtx);
assert(TargetNodes.size() == 1 && "Match must be unique");
>From 84a2b676daadb8e0260d8eaac9217149d601f406 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 15 Aug 2026 19:11:32 +0900
Subject: [PATCH 10/15] IntervalPartitionTest.cpp: Suppress a warning.
[-Wunused-template] (#215564)
I think it'd be fair just to suppress since this is just a test.
(cherry picked from commit e45f256d0389ca5f9536dcd949680c1097ef9728)
---
clang/unittests/Analysis/IntervalPartitionTest.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/unittests/Analysis/IntervalPartitionTest.cpp b/clang/unittests/Analysis/IntervalPartitionTest.cpp
index 845608504a3d0..e2391ac56e69c 100644
--- a/clang/unittests/Analysis/IntervalPartitionTest.cpp
+++ b/clang/unittests/Analysis/IntervalPartitionTest.cpp
@@ -90,7 +90,7 @@ using ::testing::UnorderedElementsAre;
MATCHER_P(intervalID, ID, "") { return arg->ID == ID; }
-template <typename... T> auto blockIDs(T... IDs) {
+template <typename... T> [[maybe_unused]] auto blockIDs(T... IDs) {
return UnorderedElementsAre(Property(&CFGBlock::getBlockID, IDs)...);
}
>From b56a277c886bbd54bab30a9dac244237fc686547 Mon Sep 17 00:00:00 2001
From: Baranov Victor <bar.victor.2002 at gmail.com>
Date: Sat, 5 Sep 2026 19:03:19 +0300
Subject: [PATCH 11/15] [clang-tools-extra][NFC] Fix -Wunused-template
violations (#221427)
These cause build errors in
https://github.com/llvm/llvm-project/actions/runs/33952646467/job/101270176288.
(cherry picked from commit e1474e57522c4188d3a5a06921c1199210f1c3e1)
---
.../clangd/unittests/CallHierarchyTests.cpp | 1 -
.../clangd/unittests/ClangdLSPServerTests.cpp | 9 ---------
.../clangd/unittests/ParsedASTTests.cpp | 2 --
.../clangd/unittests/PreambleTests.cpp | 4 ----
.../clangd/unittests/SymbolCollectorTests.cpp | 1 -
.../clangd/unittests/TUSchedulerTests.cpp | 13 -------------
clang-tools-extra/clangd/unittests/XRefsTests.cpp | 3 ---
.../unittests/clang-tidy/ClangTidyOptionsTest.cpp | 4 ----
8 files changed, 37 deletions(-)
diff --git a/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp
index 4fd294c41a3b2..1d5e63b0ad0aa 100644
--- a/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp
@@ -46,7 +46,6 @@ using ::testing::UnorderedElementsAre;
MATCHER_P(withName, N, "") { return arg.name == N; }
MATCHER_P(withDetail, N, "") { return arg.detail == N; }
MATCHER_P(withFile, N, "") { return arg.uri.file() == N; }
-MATCHER_P(withSelectionRange, R, "") { return arg.selectionRange == R; }
template <class ItemMatcher>
::testing::Matcher<CallHierarchyIncomingCall> from(ItemMatcher M) {
diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
index 5d6a69c953e17..aaa3a68b856d4 100644
--- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
@@ -366,15 +366,6 @@ TEST_F(LSPTest, ModulesTest) {
ElementsAre(llvm::json::Value(2), llvm::json::Value(10)));
}
-// Creates a Callback that writes its received value into an
-// std::optional<Expected>.
-template <typename T>
-llvm::unique_function<void(llvm::Expected<T>)>
-capture(std::optional<llvm::Expected<T>> &Out) {
- Out.reset();
- return [&Out](llvm::Expected<T> V) { Out.emplace(std::move(V)); };
-}
-
TEST_F(LSPTest, FeatureModulesThreadingTest) {
// A feature module that does its work on a background thread, and so
// exercises the block/shutdown protocol.
diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
index f9752d5d44f97..d7d784043a6a0 100644
--- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -348,8 +348,6 @@ TEST(ParsedASTTest, CollectsMainFileMacroExpansions) {
testing::UnorderedElementsAreArray(TestCase.points()));
}
-MATCHER_P(withFileName, Inc, "") { return arg.FileName == Inc; }
-
TEST(ParsedASTTest, PatchesAdditionalIncludes) {
llvm::StringLiteral ModifiedContents = R"cpp(
#include "baz.h"
diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
index 16a2f9448b1ec..14324dc1fad9a 100644
--- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -54,10 +54,6 @@ namespace clang {
namespace clangd {
namespace {
-MATCHER_P2(Distance, File, D, "") {
- return arg.first() == File && arg.second == D;
-}
-
// Builds a preamble for BaselineContents, patches it for ModifiedContents and
// returns the includes in the patch.
IncludeStructure
diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index 94116fca3cbb2..0346a46fb5fc4 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -58,7 +58,6 @@ MATCHER_P(snippet, S, "") {
return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
}
MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P(hasName, Name, "") { return arg.Name == Name; }
MATCHER_P(templateArgs, TemplArgs, "") {
return arg.TemplateSpecializationArgs == TemplArgs;
}
diff --git a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
index c6862b5eba6fa..1404f559aa2b8 100644
--- a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -63,19 +63,6 @@ using ::testing::Pointee;
using ::testing::SizeIs;
using ::testing::UnorderedElementsAre;
-MATCHER_P2(TUState, PreambleActivity, ASTActivity, "") {
- if (arg.PreambleActivity != PreambleActivity) {
- *result_listener << "preamblestate is "
- << static_cast<uint8_t>(arg.PreambleActivity);
- return false;
- }
- if (arg.ASTActivity.K != ASTActivity) {
- *result_listener << "aststate is " << arg.ASTActivity.K;
- return false;
- }
- return true;
-}
-
// Simple ContextProvider to verify the provider is invoked & contexts are used.
static Key<std::string> BoundPath;
Context bindPath(PathRef F) {
diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index dce033af73c1a..d5ba2bc093c9c 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -46,9 +46,6 @@ std::string guard(llvm::StringRef Code) {
return "#pragma once\n" + Code.str();
}
-MATCHER_P2(FileRange, File, Range, "") {
- return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
-}
MATCHER(declRange, "") {
const LocatedSymbol &Sym = ::testing::get<0>(arg);
const Range &Range = ::testing::get<1>(arg);
diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
index 3f86f65c1ce65..2aa8d7386605b 100644
--- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
+++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp
@@ -305,10 +305,6 @@ class TestCheck : public ClangTidyCheck {
return Options.get(std::forward<Args>(Arguments)...);
}
- template <typename... Args> auto getGlobal(Args &&... Arguments) {
- return Options.getLocalOrGlobal(std::forward<Args>(Arguments)...);
- }
-
template <typename IntType = int, typename... Args>
auto getIntLocal(Args &&... Arguments) {
return Options.get<IntType>(std::forward<Args>(Arguments)...);
>From 59c4bfa8fc16f0a1e89431772d360ffe49bcb343 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <xlauko at mail.muni.cz>
Date: Sat, 5 Sep 2026 20:31:07 +0200
Subject: [PATCH 12/15] [mlir][tblgen] Prune unused filterForDialect template
[-Wunused-template] (#221422)
`filterForDialect` lost its last caller in 4957518ef57f (May 2022) and
has been dead since. It is a static file-scope function template, so
`-Wunused-template` flags it and `-Werror` builds fail. Removing it also
orphans the `DialectFilterIterator` alias and the `llvm::Record`
using-declaration, which nothing else references, so this drops all
three.
Co-authored-by: Henrich Lauko <hlauko at nvidia.com>
(cherry picked from commit 2fb12bca76c52d8e0bbb838017820ee58a395293)
---
mlir/tools/mlir-tblgen/DialectGen.cpp | 20 --------------------
1 file changed, 20 deletions(-)
diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp
index 8eecad39f49f3..14ded6de764b4 100644
--- a/mlir/tools/mlir-tblgen/DialectGen.cpp
+++ b/mlir/tools/mlir-tblgen/DialectGen.cpp
@@ -31,7 +31,6 @@
using namespace mlir;
using namespace mlir::tblgen;
-using llvm::Record;
using llvm::RecordKeeper;
static llvm::cl::OptionCategory dialectGenCat("Options for -gen-dialect-*");
@@ -39,13 +38,6 @@ static llvm::cl::opt<std::string>
selectedDialect("dialect", llvm::cl::desc("The dialect to gen for"),
llvm::cl::cat(dialectGenCat), llvm::cl::CommaSeparated);
-/// Utility iterator used for filtering records for a specific dialect.
-namespace {
-using DialectFilterIterator =
- llvm::filter_iterator<ArrayRef<Record *>::iterator,
- std::function<bool(const Record *)>>;
-} // namespace
-
static void populateDiscardableAttributes(
Dialect &dialect, const llvm::DagInit *discardableAttrDag,
SmallVector<std::pair<std::string, std::string>> &discardableAttributes) {
@@ -61,18 +53,6 @@ static void populateDiscardableAttributes(
}
}
-/// Given a set of records for a T, filter the ones that correspond to
-/// the given dialect.
-template <typename T>
-static iterator_range<DialectFilterIterator>
-filterForDialect(ArrayRef<Record *> records, Dialect &dialect) {
- auto filterFn = [&](const Record *record) {
- return T(record).getDialect() == dialect;
- };
- return {DialectFilterIterator(records.begin(), records.end(), filterFn),
- DialectFilterIterator(records.end(), records.end(), filterFn)};
-}
-
std::optional<Dialect>
tblgen::findDialectToGenerate(ArrayRef<Dialect> dialects) {
if (dialects.empty()) {
>From e3c5e06bc488e76eecb2f3fb7ec84962138d0b19 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Sat, 5 Sep 2026 12:56:31 -0700
Subject: [PATCH 13/15] [Support] Fix -Wunused-template from debugString
This is not used in the header (outside of a non-instantiated template),
so triggers -Wunused-template. Move it into the class definition to
prevent this without adding any namespace pollution.
Reviewers: MaskRay, kazutakahirata
Pull Request: https://github.com/llvm/llvm-project/pull/221478
(cherry picked from commit 03de3d1299bffd3a2829da92b28875142d8ad944)
---
llvm/include/llvm/Support/LSP/Transport.h | 15 ++++++++-------
llvm/unittests/Support/LSP/Transport.cpp | 2 +-
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Support/LSP/Transport.h b/llvm/include/llvm/Support/LSP/Transport.h
index 6a0dd51d946bd..2bb32561a1bf3 100644
--- a/llvm/include/llvm/Support/LSP/Transport.h
+++ b/llvm/include/llvm/Support/LSP/Transport.h
@@ -27,13 +27,6 @@
#include <memory>
namespace llvm {
-// Simple helper function that returns a string as printed from a op.
-template <typename T> static std::string debugString(T &&Op) {
- std::string InstrStr;
- llvm::raw_string_ostream Os(InstrStr);
- Os << Op;
- return Os.str();
-}
namespace lsp {
class MessageHandler;
@@ -229,6 +222,14 @@ class MessageHandler {
};
}
+ // Simple helper function that returns a string as printed from a op.
+ template <typename T> static std::string debugString(T &&Op) {
+ std::string InstrStr;
+ llvm::raw_string_ostream Os(InstrStr);
+ Os << Op;
+ return Os.str();
+ }
+
/// Create an OutgoingRequest function that, when called, sends a request with
/// the given method via the transport. Should the outgoing request be
/// met with a response, the result JSON is parsed and the response callback
diff --git a/llvm/unittests/Support/LSP/Transport.cpp b/llvm/unittests/Support/LSP/Transport.cpp
index 055a6276dc0c3..ef7cd4e2f44a3 100644
--- a/llvm/unittests/Support/LSP/Transport.cpp
+++ b/llvm/unittests/Support/LSP/Transport.cpp
@@ -182,7 +182,7 @@ TEST_F(TransportInputTest, OutgoingRequestJSONParseFailure) {
llvm::Error err = result.takeError();
EXPECT_EQ(id, 109);
ASSERT_TRUE((bool)err);
- EXPECT_THAT(debugString(err),
+ EXPECT_THAT(MessageHandler::debugString(err),
HasSubstr("failed to decode "
"reply:outgoing-request-json-parse-failure(109) "
"response: missing value at (root).character"));
>From 8cc18380f9d66465f9bb0fe849d699d7ae573530 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Sat, 5 Sep 2026 23:52:03 -0700
Subject: [PATCH 14/15] [MLIR][Python] Pass -Wno-unused-template to nanobind
build
As with a lot of other warnings, the nanobind build is also not clean
under -Wunused-template. This was enabled by default for clang 23
(although reverted for 23.1.1). Disable it in case it gets enabled again
and also in case anyone enables it manually.
Reviewers: joker-eph, makslevental, dcaballe
Pull Request: https://github.com/llvm/llvm-project/pull/221479
(cherry picked from commit cb25e7ca7cef9e84db077fe36f3d27b269394c65)
---
mlir/cmake/modules/AddMLIRPython.cmake | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mlir/cmake/modules/AddMLIRPython.cmake b/mlir/cmake/modules/AddMLIRPython.cmake
index 7d47fd0bca34f..1e483116569a0 100644
--- a/mlir/cmake/modules/AddMLIRPython.cmake
+++ b/mlir/cmake/modules/AddMLIRPython.cmake
@@ -385,6 +385,7 @@ function(build_nanobind_lib)
-Wno-deprecated-literal-operator
-Wno-nested-anon-types
-Wno-unused-parameter
+ -Wno-unused-template
-Wno-zero-length-array
-Wno-missing-field-initializers
${eh_rtti_enable})
@@ -1055,6 +1056,7 @@ function(add_mlir_python_extension libname extname nb_library_target_name)
-Wno-deprecated-literal-operator
-Wno-nested-anon-types
-Wno-unused-parameter
+ -Wno-unused-template
-Wno-zero-length-array
-Wno-missing-field-initializers)
endif()
>From f8af72209ebb1d8e4cdc13ceca6f18c9121bfa81 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Tue, 8 Sep 2026 13:51:23 -0700
Subject: [PATCH 15/15] [lldb] Fix -Wunused-template (#221815)
This warning was enabled by default in clang 23.1.0 (although reverted
for 23.1.1). These fixes still make sense to perform though. Template
definitions in headers should not use static, and others are completely
unused.
(cherry picked from commit cc5c51457347547dbac6edcfe9887ca5aeee1b3d)
---
.../Protocol/ProtocolMCPServerTest.cpp | 34 -------------------
lldb/unittests/TestingSupport/TestUtilities.h | 2 +-
2 files changed, 1 insertion(+), 35 deletions(-)
diff --git a/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp b/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp
index d83cbfd7c036d..4b07682bc5df7 100644
--- a/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp
+++ b/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp
@@ -211,42 +211,8 @@ class ProtocolServerMCPTest : public testing::Test {
Response resp = promised_result.get_future().get();
return toJSON(resp);
}
-
- template <typename Result>
- Expected<json::Value>
- Capture(llvm::unique_function<void(Reply<Result>)> &fn) {
- std::promise<llvm::Expected<Result>> promised_result;
- fn([&promised_result](llvm::Expected<Result> result) {
- promised_result.set_value(std::move(result));
- });
- Run();
- llvm::Expected<Result> result = promised_result.get_future().get();
- if (!result)
- return result.takeError();
- return toJSON(*result);
- }
-
- template <typename Result, typename Params>
- Expected<json::Value>
- Capture(llvm::unique_function<void(const Params &, Reply<Result>)> &fn,
- const Params ¶ms) {
- std::promise<llvm::Expected<Result>> promised_result;
- fn(params, [&promised_result](llvm::Expected<Result> result) {
- promised_result.set_value(std::move(result));
- });
- Run();
- llvm::Expected<Result> result = promised_result.get_future().get();
- if (!result)
- return result.takeError();
- return toJSON(*result);
- }
};
-template <typename T>
-inline testing::internal::EqMatcher<llvm::json::Value> HasJSON(T x) {
- return testing::internal::EqMatcher<llvm::json::Value>(toJSON(x));
-}
-
} // namespace
TEST_F(ProtocolServerMCPTest, Initialization) {
diff --git a/lldb/unittests/TestingSupport/TestUtilities.h b/lldb/unittests/TestingSupport/TestUtilities.h
index 68b4dbc127a7d..f322716eb6977 100644
--- a/lldb/unittests/TestingSupport/TestUtilities.h
+++ b/lldb/unittests/TestingSupport/TestUtilities.h
@@ -65,7 +65,7 @@ class TestFile {
std::string Buffer;
};
-template <typename T> static llvm::Expected<T> roundtripJSON(const T &input) {
+template <typename T> llvm::Expected<T> roundtripJSON(const T &input) {
std::string encoded;
llvm::raw_string_ostream OS(encoded);
OS << toJSON(input);
More information about the llvm-branch-commits
mailing list