// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-unused-local-non-trivial-variable %t -- \ // RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Future;::async::Foo.*', bugprone-unused-local-non-trivial-variable.ExcludeTypes: '::async::FooBar'}}" \ // RUN: -- -fexceptions namespace async { template class Ptr { public: explicit Ptr(T Arg) : Underlying(new T(Arg)) {} T& operator->() { return Underlying; } ~Ptr() { delete Underlying; } private: T* Underlying; }; template class Future { public: T get() { return Pending; } ~Future(); private: T Pending; }; class FooBar { public: ~FooBar(); private: Future Fut; }; class FooQux { public: ~FooQux(); private: Future Fut; }; class FizzFoo { public: ~FizzFoo(); private: Future Fut; }; } // namespace async // Warning is still emitted if there are type aliases. namespace a { template using Future = async::Future; } // namespace a void releaseUnits(); struct Units { ~Units() { releaseUnits(); } }; a::Future acquireUnits(); template T qux(T Generic) { async::Future PendingA = acquireUnits(); auto PendingB = acquireUnits(); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] async::Future MustBeUsed; // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unused local variable 'MustBeUsed' of type 'async::Future' [bugprone-unused-local-non-trivial-variable] PendingA.get(); async::Future TemplateType; // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future' [bugprone-unused-local-non-trivial-variable] a::Future AliasTemplateType; // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] return Generic; } async::Future Global; int bar(int Num) { a::Future PendingA = acquireUnits(); a::Future PendingB = acquireUnits(); // not used at all, unused variable not fired because of destructor side effect // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] auto Num2 = PendingA.get(); auto Num3 = qux(Num); async::Ptr> Shared = async::Ptr>(acquireUnits()); static auto UnusedStatic = async::Future(); thread_local async::Future UnusedThreadLocal; auto Captured = acquireUnits(); Num3 += [Captured]() { return 1; }(); a::Future Referenced = acquireUnits(); a::Future* Pointer = &Referenced; a::Future& Reference = Referenced; const a::Future& ConstReference = Referenced; try { } catch (a::Future Fut) { } struct Holder { a::Future Fut; }; Holder H; auto [fut] = H; return Num * Num3; } void exclusion() { async::FizzFoo A; async::FooBar B; async::FooQux C; // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unused local variable 'C' of type 'async::FooQux' [bugprone-unused-local-non-trivial-variable] }