xref: /llvm-project/clang/test/Analysis/PR121201.cpp (revision 8e965d89c9624c184c48806dc39d50209265f0f8)
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s \
2 // RUN:    -analyzer-config unroll-loops=true
3 
4 // expected-no-diagnostics
5 
6 template <bool, typename T, typename> using conditional_t = T;
7 class basic_format_arg;
8 template <typename> struct formatter;
9 
10 template <typename Context> struct value {
11   template <typename T> value(T) {
12     using value_type = T;
13     (void)format_custom_arg<value_type,
14                       typename Context::template formatter_type<value_type>>;
15   }
16 
17   template <typename, typename Formatter> static void format_custom_arg() {
18     Context ctx;
19     auto f = Formatter();
20     f.format(0, ctx);
21   }
22 };
23 
24 struct context {
25   template <typename T> using formatter_type = formatter<T>;
26 };
27 
28 enum { max_packed_args };
29 
30 template <typename Context, long>
31 using arg_t = conditional_t<max_packed_args, value<Context>, basic_format_arg>;
32 
33 template <int NUM_ARGS> struct format_arg_store {
34   arg_t<context, NUM_ARGS> args;
35 };
36 
37 template <typename... T, long NUM_ARGS = sizeof...(T)>
38 auto make_format_args(T... args) -> format_arg_store<NUM_ARGS> {
39   return {args...};
40 }
41 
42 template <typename F> void write_padded(F write) { write(0); }
43 
44 template <typename... T> void format(T... args) { make_format_args(args...); }
45 
46 template <int> struct bitset {
47   bitset(long);
48 };
49 
50 template <long N> struct formatter<bitset<N>> {
51   struct writer {
52     bitset<N> bs;
53 
54     template <typename OutputIt> void operator()(OutputIt) {
55       for (auto pos = N; pos > 0; --pos) // no-crash
56         ;
57     }
58   };
59 
60   template <typename FormatContext> void format(bitset<N> bs, FormatContext) {
61     write_padded(writer{bs});
62   }
63 };
64 
65 bitset<6> TestBody_bs(2);
66 
67 void TestBody() { format(TestBody_bs); }
68