1 // RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core,deadcode -verify %s 2 3 typedef unsigned long size_t; 4 5 // Machinery required for custom structured bindings decomposition. 6 namespace std { 7 template <class T> class tuple_size; 8 template <class T> 9 constexpr size_t tuple_size_v = tuple_size<T>::value; 10 template <size_t I, class T> class tuple_element; 11 12 template<class T, T v> 13 struct 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 21 struct S { 22 int a; 23 double b; 24 S(int a, double b) : a(a), b(b) {}; 25 }; 26 27 S GetNumbers(); 28 29 int used_binding() { 30 const auto [a, b] = GetNumbers(); // no-warning 31 return a + b; 32 } 33 34 void no_warning_on_copy(S s) { 35 // Copy constructor might have side effects. 36 const auto [a, b] = s; // no-warning 37 } 38 39 40 int 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 45 int 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 52 int kill_one_binding() { 53 auto [a, b] = GetNumbers(); // no-warning 54 a = 100; 55 return a + b; 56 57 } 58 59 int 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 65 void use_const_reference_bindings() { 66 const auto &[a, b] = GetNumbers(); // no-warning 67 } 68 69 void use_reference_bindings() { 70 S s(0, 0); 71 auto &[a, b] = s; // no-warning 72 a = 200; 73 } 74 75 int read_through_pointer() { 76 auto [a, b] = GetNumbers(); // no-warning 77 int *z = &a; 78 return *z; 79 } 80 81 auto [globalA, globalB] = GetNumbers(); // no-warning, globals 82 auto [globalC, globalD] = GetNumbers(); // no-warning, globals 83 84 void use_globals() { 85 globalA = 300; // no-warning 86 globalB = 200; 87 } 88 89 struct 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 100 namespace 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 111 void no_warning_on_tuple_types_copy(Mytuple t) { 112 auto [a, b] = t; // no-warning 113 } 114 115 Mytuple getMytuple(); 116 117 void deconstruct_tuple_types_warning() { 118 auto [a, b] = getMytuple(); // expected-warning{{Value stored to '[a, b]' during its initialization is never read}} 119 } 120 121 int deconstruct_tuple_types_no_warning() { 122 auto [a, b] = getMytuple(); // no-warning 123 return a + b; 124 } 125