forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			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;
 | |
| }
 |