summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Analysis/live-bindings-test.cpp124
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;
+}
OpenPOWER on IntegriCloud