diff options
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/live-bindings-test.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/clang/test/Analysis/live-bindings-test.cpp b/clang/test/Analysis/live-bindings-test.cpp new file mode 100644 index 00000000000..afbb1b399fc --- /dev/null +++ b/clang/test/Analysis/live-bindings-test.cpp @@ -0,0 +1,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; +} |

