Clang Project

clang_source_code/test/Analysis/live-bindings-test.cpp
1// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core,deadcode -verify %s
2
3typedef unsigned long size_t;
4
5// Machinery required for custom structured bindings decomposition.
6namespace std {
7template <class T> class tuple_size;
8template <class T>
9 constexpr size_t tuple_size_v = tuple_size<T>::value;
10template <size_t I, class T> class tuple_element;
11
12template<class T, T v>
13struct integral_constant {
14    static constexpr T value = v;
15    typedef T value_type;
16    typedef integral_constant type;
17    constexpr operator value_type() const noexcept { return value; }
18};
19}
20
21struct S {
22  int a;
23  double b;
24  S(int a, double b) : a(a), b(b) {};
25};
26
27S GetNumbers();
28
29int used_binding() {
30    const auto [a, b] = GetNumbers(); // no-warning
31    return a + b; 
32}
33
34void no_warning_on_copy(S s) {
35  // Copy constructor might have side effects.
36  const auto [a, b] = s; // no-warning
37}
38
39
40int unused_binding_ignored() {
41    const auto [a, b] = GetNumbers(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}}
42    return 0;
43}
44
45int unused_binding_liveness_required() {
46    auto [a2, b2] = GetNumbers(); // expected-warning{{Value stored to '[a2, b2]' during its initialization is never read}}
47    a2 = 10;
48    b2 = 20;
49    return a2 + b2;
50}
51
52int kill_one_binding() {
53  auto [a, b] = GetNumbers(); // no-warning
54  a = 100;
55  return a + b;
56
57}
58
59int kill_one_binding2() {
60  auto [a, b] = GetNumbers(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}}
61  a = 100;
62  return a;
63}
64
65void use_const_reference_bindings() {
66  const auto &[a, b] = GetNumbers(); // no-warning
67}
68
69void use_reference_bindings() {
70  S s(0, 0);
71  auto &[a, b] = s; // no-warning
72  a = 200;
73}
74
75int read_through_pointer() {
76  auto [a, b] = GetNumbers(); // no-warning
77  int *z = &a;
78  return *z;
79}
80
81auto [globalA, globalB] = GetNumbers(); // no-warning, globals
82auto [globalC, globalD] = GetNumbers(); // no-warning, globals
83
84void use_globals() {
85  globalA = 300; // no-warning
86  globalB = 200;
87}
88
89struct Mytuple {
90  int a;
91  int b;
92
93  template <size_t N>
94  int get() const {
95    if      constexpr (N == 0) return a;
96    else if constexpr (N == 1) return b;
97  }
98};
99
100namespace std {
101    template<>
102    struct tuple_size<Mytuple>
103        : std::integral_constant<size_t, 2> {};
104
105    template<size_t N>
106    struct tuple_element<N, Mytuple> {
107        using type = int;
108    };
109}
110
111void no_warning_on_tuple_types_copy(Mytuple t) {
112  auto [a, b] = t; // no-warning
113}
114
115Mytuple getMytuple();
116
117void deconstruct_tuple_types_warning() {
118  auto [a, b] = getMytuple(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}}
119}
120
121int deconstruct_tuple_types_no_warning() {
122  auto [a, b] = getMytuple(); // no-warning
123  return a + b;
124}
125