Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / live-bindings-test.cpp
blob7660e9c9904d71ab288290b299988717bd6c0e69
1 // RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core,deadcode -verify %s
3 typedef unsigned long size_t;
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;
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; }
21 struct S {
22 int a;
23 double b;
24 S(int a, double b) : a(a), b(b) {};
27 S GetNumbers();
29 int used_binding() {
30 const auto [a, b] = GetNumbers(); // no-warning
31 return a + b;
34 void no_warning_on_copy(S s) {
35 // Copy constructor might have side effects.
36 const auto [a, b] = s; // no-warning
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;
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;
52 int kill_one_binding() {
53 auto [a, b] = GetNumbers(); // no-warning
54 a = 100;
55 return a + b;
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;
65 void use_const_reference_bindings() {
66 const auto &[a, b] = GetNumbers(); // no-warning
69 void use_reference_bindings() {
70 S s(0, 0);
71 auto &[a, b] = s; // no-warning
72 a = 200;
75 int read_through_pointer() {
76 auto [a, b] = GetNumbers(); // no-warning
77 int *z = &a;
78 return *z;
81 auto [globalA, globalB] = GetNumbers(); // no-warning, globals
82 auto [globalC, globalD] = GetNumbers(); // no-warning, globals
84 void use_globals() {
85 globalA = 300; // no-warning
86 globalB = 200;
89 struct Mytuple {
90 int a;
91 int b;
93 template <size_t N>
94 int get() const {
95 if constexpr (N == 0) return a;
96 else if constexpr (N == 1) return b;
100 namespace std {
101 template<>
102 struct tuple_size<Mytuple>
103 : std::integral_constant<size_t, 2> {};
105 template<size_t N>
106 struct tuple_element<N, Mytuple> {
107 using type = int;
111 void no_warning_on_tuple_types_copy(Mytuple t) {
112 auto [a, b] = t; // no-warning
115 Mytuple getMytuple();
117 void deconstruct_tuple_types_warning() {
118 // The initializers reference the decomposed region, so the warning is not reported
119 // FIXME: ideally we want to ignore that the initializers reference the decomposed region, and report the warning,
120 // though the first step towards that is to handle DeadCode if the initializer is CXXConstructExpr.
121 auto [a, b] = getMytuple(); // no-warning
124 int deconstruct_tuple_types_no_warning() {
125 auto [a, b] = getMytuple(); // no-warning
126 return a + b;