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