120 lines · cpp
1// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-unused-local-non-trivial-variable %t -- \2// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Future;::async::Foo.*', bugprone-unused-local-non-trivial-variable.ExcludeTypes: '::async::FooBar'}}" \3// RUN: -- -fexceptions4 5namespace async {6template <typename T>7class Ptr {8 public:9 explicit Ptr(T Arg) : Underlying(new T(Arg)) {}10 T& operator->() {11 return Underlying;12 }13 ~Ptr() {14 delete Underlying;15 }16 private:17 T* Underlying;18};19 20template<typename T>21class Future {22public:23 T get() {24 return Pending;25 }26 ~Future();27private:28 T Pending;29};30 31class FooBar {32 public:33 ~FooBar();34 private:35 Future<int> Fut;36};37 38class FooQux {39 public:40 ~FooQux();41 private:42 Future<int> Fut;43};44 45class FizzFoo {46 public:47 ~FizzFoo();48 private:49 Future<int> Fut;50};51 52} // namespace async53 54// Warning is still emitted if there are type aliases.55namespace a {56template<typename T>57using Future = async::Future<T>;58} // namespace a59 60void releaseUnits();61struct Units {62 ~Units() {63 releaseUnits();64 }65};66a::Future<Units> acquireUnits();67 68template<typename T>69T qux(T Generic) {70 async::Future<Units> PendingA = acquireUnits();71 auto PendingB = acquireUnits();72 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'async::Future<Units>') [bugprone-unused-local-non-trivial-variable]73 async::Future<Units> MustBeUsed;74 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unused local variable 'MustBeUsed' of type 'async::Future<Units>' [bugprone-unused-local-non-trivial-variable]75 PendingA.get();76 async::Future<T> TemplateType;77 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future<T>' [bugprone-unused-local-non-trivial-variable]78 a::Future<T> AliasTemplateType;79 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'async::Future<T>') [bugprone-unused-local-non-trivial-variable]80 [[maybe_unused]] async::Future<Units> MaybeUnused;81 return Generic;82}83 84async::Future<int> Global;85 86int bar(int Num) {87 a::Future<Units> PendingA = acquireUnits();88 a::Future<Units> PendingB = acquireUnits(); // not used at all, unused variable not fired because of destructor side effect89 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'async::Future<Units>') [bugprone-unused-local-non-trivial-variable]90 auto Num2 = PendingA.get();91 auto Num3 = qux(Num);92 async::Ptr<a::Future<Units>> Shared = async::Ptr<a::Future<Units>>(acquireUnits());93 static auto UnusedStatic = async::Future<Units>();94 thread_local async::Future<Units> UnusedThreadLocal;95 auto Captured = acquireUnits();96 Num3 += [Captured]() {97 return 1;98 }();99 a::Future<Units> Referenced = acquireUnits();100 a::Future<Units>* Pointer = &Referenced;101 a::Future<Units>& Reference = Referenced;102 const a::Future<Units>& ConstReference = Referenced;103 try {104 } catch (a::Future<Units> Fut) {105 }106 struct Holder {107 a::Future<Units> Fut;108 };109 Holder H;110 auto [fut] = H;111 return Num * Num3;112}113 114void exclusion() {115 async::FizzFoo A;116 async::FooBar B;117 async::FooQux C;118 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unused local variable 'C' of type 'async::FooQux' [bugprone-unused-local-non-trivial-variable]119}120