summaryrefslogtreecommitdiff
path: root/clang/test/Analysis/PR121201.cpp
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 18:49:54 +0900
committerNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 18:49:54 +0900
commite2810c9a248f4c7fbfae84bb32b6f7e01027458b (patch)
treeae0b02a8491b969a1cee94ea16ffe42c559143c5 /clang/test/Analysis/PR121201.cpp
parentfa04eb4af95c1ca7377279728cb004bcd2324d01 (diff)
parentbdcf47e4bcb92889665825654bb80a8bbe30379e (diff)
Merge branch 'users/chapuni/cov/single/base' into users/chapuni/cov/single/switchusers/chapuni/cov/single/switch
Diffstat (limited to 'clang/test/Analysis/PR121201.cpp')
-rw-r--r--clang/test/Analysis/PR121201.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/clang/test/Analysis/PR121201.cpp b/clang/test/Analysis/PR121201.cpp
new file mode 100644
index 000000000000..acd2492d011f
--- /dev/null
+++ b/clang/test/Analysis/PR121201.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s \
+// RUN: -analyzer-config unroll-loops=true
+
+// expected-no-diagnostics
+
+template <bool, typename T, typename> using conditional_t = T;
+class basic_format_arg;
+template <typename> struct formatter;
+
+template <typename Context> struct value {
+ template <typename T> value(T) {
+ using value_type = T;
+ (void)format_custom_arg<value_type,
+ typename Context::template formatter_type<value_type>>;
+ }
+
+ template <typename, typename Formatter> static void format_custom_arg() {
+ Context ctx;
+ auto f = Formatter();
+ f.format(0, ctx);
+ }
+};
+
+struct context {
+ template <typename T> using formatter_type = formatter<T>;
+};
+
+enum { max_packed_args };
+
+template <typename Context, long>
+using arg_t = conditional_t<max_packed_args, value<Context>, basic_format_arg>;
+
+template <int NUM_ARGS> struct format_arg_store {
+ arg_t<context, NUM_ARGS> args;
+};
+
+template <typename... T, long NUM_ARGS = sizeof...(T)>
+auto make_format_args(T... args) -> format_arg_store<NUM_ARGS> {
+ return {args...};
+}
+
+template <typename F> void write_padded(F write) { write(0); }
+
+template <typename... T> void format(T... args) { make_format_args(args...); }
+
+template <int> struct bitset {
+ bitset(long);
+};
+
+template <long N> struct formatter<bitset<N>> {
+ struct writer {
+ bitset<N> bs;
+
+ template <typename OutputIt> void operator()(OutputIt) {
+ for (auto pos = N; pos > 0; --pos) // no-crash
+ ;
+ }
+ };
+
+ template <typename FormatContext> void format(bitset<N> bs, FormatContext) {
+ write_padded(writer{bs});
+ }
+};
+
+bitset<6> TestBody_bs(2);
+
+void TestBody() { format(TestBody_bs); }