125 lines
2.7 KiB
C++
125 lines
2.7 KiB
C++
// 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;
|
|
}
|