1952d344fSTyler Rockwood // RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-unused-local-non-trivial-variable %t -- \ 237fc9c6aSPiotr Zegar // RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Future;::async::Foo.*', bugprone-unused-local-non-trivial-variable.ExcludeTypes: '::async::FooBar'}}" \ 3007ed0dcSPiotr Zegar // RUN: -- -fexceptions 4952d344fSTyler Rockwood 5952d344fSTyler Rockwood namespace async { 6952d344fSTyler Rockwood template <typename T> 7952d344fSTyler Rockwood class Ptr { 8952d344fSTyler Rockwood public: 9952d344fSTyler Rockwood explicit Ptr(T Arg) : Underlying(new T(Arg)) {} 10952d344fSTyler Rockwood T& operator->() { 11952d344fSTyler Rockwood return Underlying; 12952d344fSTyler Rockwood } 13952d344fSTyler Rockwood ~Ptr() { 14952d344fSTyler Rockwood delete Underlying; 15952d344fSTyler Rockwood } 16952d344fSTyler Rockwood private: 17952d344fSTyler Rockwood T* Underlying; 18952d344fSTyler Rockwood }; 19952d344fSTyler Rockwood 20952d344fSTyler Rockwood template<typename T> 21952d344fSTyler Rockwood class Future { 22952d344fSTyler Rockwood public: 23952d344fSTyler Rockwood T get() { 24952d344fSTyler Rockwood return Pending; 25952d344fSTyler Rockwood } 26952d344fSTyler Rockwood ~Future(); 27952d344fSTyler Rockwood private: 28952d344fSTyler Rockwood T Pending; 29952d344fSTyler Rockwood }; 30952d344fSTyler Rockwood 31952d344fSTyler Rockwood class FooBar { 32952d344fSTyler Rockwood public: 33952d344fSTyler Rockwood ~FooBar(); 34952d344fSTyler Rockwood private: 35952d344fSTyler Rockwood Future<int> Fut; 36952d344fSTyler Rockwood }; 37952d344fSTyler Rockwood 38952d344fSTyler Rockwood class FooQux { 39952d344fSTyler Rockwood public: 40952d344fSTyler Rockwood ~FooQux(); 41952d344fSTyler Rockwood private: 42952d344fSTyler Rockwood Future<int> Fut; 43952d344fSTyler Rockwood }; 44952d344fSTyler Rockwood 45952d344fSTyler Rockwood class FizzFoo { 46952d344fSTyler Rockwood public: 47952d344fSTyler Rockwood ~FizzFoo(); 48952d344fSTyler Rockwood private: 49952d344fSTyler Rockwood Future<int> Fut; 50952d344fSTyler Rockwood }; 51952d344fSTyler Rockwood 52952d344fSTyler Rockwood } // namespace async 53952d344fSTyler Rockwood 54952d344fSTyler Rockwood // Warning is still emitted if there are type aliases. 55952d344fSTyler Rockwood namespace a { 56952d344fSTyler Rockwood template<typename T> 57952d344fSTyler Rockwood using Future = async::Future<T>; 58952d344fSTyler Rockwood } // namespace a 59952d344fSTyler Rockwood 60952d344fSTyler Rockwood void releaseUnits(); 61952d344fSTyler Rockwood struct Units { 62952d344fSTyler Rockwood ~Units() { 63952d344fSTyler Rockwood releaseUnits(); 64952d344fSTyler Rockwood } 65952d344fSTyler Rockwood }; 66952d344fSTyler Rockwood a::Future<Units> acquireUnits(); 67952d344fSTyler Rockwood 68952d344fSTyler Rockwood template<typename T> 69952d344fSTyler Rockwood T qux(T Generic) { 70952d344fSTyler Rockwood async::Future<Units> PendingA = acquireUnits(); 71952d344fSTyler Rockwood auto PendingB = acquireUnits(); 72952d344fSTyler Rockwood // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'Future<Units>') [bugprone-unused-local-non-trivial-variable] 73952d344fSTyler Rockwood async::Future<Units> MustBeUsed; 74952d344fSTyler Rockwood // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unused local variable 'MustBeUsed' of type 'async::Future<Units>' [bugprone-unused-local-non-trivial-variable] 75952d344fSTyler Rockwood PendingA.get(); 76952d344fSTyler Rockwood async::Future<T> TemplateType; 77952d344fSTyler Rockwood // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future<T>' [bugprone-unused-local-non-trivial-variable] 78952d344fSTyler Rockwood a::Future<T> AliasTemplateType; 79*7f78f99fSMatheus Izvekov // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'Future<T>') [bugprone-unused-local-non-trivial-variable] 80ebe77cc3SCongcong Cai [[maybe_unused]] async::Future<Units> MaybeUnused; 81952d344fSTyler Rockwood return Generic; 82952d344fSTyler Rockwood } 83952d344fSTyler Rockwood 84952d344fSTyler Rockwood async::Future<int> Global; 85952d344fSTyler Rockwood 86952d344fSTyler Rockwood int bar(int Num) { 87952d344fSTyler Rockwood a::Future<Units> PendingA = acquireUnits(); 88952d344fSTyler Rockwood a::Future<Units> PendingB = acquireUnits(); // not used at all, unused variable not fired because of destructor side effect 89952d344fSTyler Rockwood // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'Future<Units>') [bugprone-unused-local-non-trivial-variable] 90952d344fSTyler Rockwood auto Num2 = PendingA.get(); 91952d344fSTyler Rockwood auto Num3 = qux(Num); 92952d344fSTyler Rockwood async::Ptr<a::Future<Units>> Shared = async::Ptr<a::Future<Units>>(acquireUnits()); 93952d344fSTyler Rockwood static auto UnusedStatic = async::Future<Units>(); 94952d344fSTyler Rockwood thread_local async::Future<Units> UnusedThreadLocal; 95952d344fSTyler Rockwood auto Captured = acquireUnits(); 96952d344fSTyler Rockwood Num3 += [Captured]() { 97952d344fSTyler Rockwood return 1; 98952d344fSTyler Rockwood }(); 99952d344fSTyler Rockwood a::Future<Units> Referenced = acquireUnits(); 100952d344fSTyler Rockwood a::Future<Units>* Pointer = &Referenced; 101952d344fSTyler Rockwood a::Future<Units>& Reference = Referenced; 102952d344fSTyler Rockwood const a::Future<Units>& ConstReference = Referenced; 103952d344fSTyler Rockwood try { 104952d344fSTyler Rockwood } catch (a::Future<Units> Fut) { 105952d344fSTyler Rockwood } 106952d344fSTyler Rockwood struct Holder { 107952d344fSTyler Rockwood a::Future<Units> Fut; 108952d344fSTyler Rockwood }; 109952d344fSTyler Rockwood Holder H; 110952d344fSTyler Rockwood auto [fut] = H; 111952d344fSTyler Rockwood return Num * Num3; 112952d344fSTyler Rockwood } 113952d344fSTyler Rockwood 114952d344fSTyler Rockwood void exclusion() { 115952d344fSTyler Rockwood async::FizzFoo A; 116952d344fSTyler Rockwood async::FooBar B; 117952d344fSTyler Rockwood async::FooQux C; 118952d344fSTyler Rockwood // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unused local variable 'C' of type 'async::FooQux' [bugprone-unused-local-non-trivial-variable] 119952d344fSTyler Rockwood } 120