aboutsummaryrefslogtreecommitdiff
path: root/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp
blob: 3fdc24b94a6cb2b7d3080772c40c4d4b5b9c22f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// 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 <typename T>
class Ptr {
  public:
  explicit Ptr(T Arg) : Underlying(new T(Arg)) {}
  T& operator->() {
    return Underlying;
  }
  ~Ptr() {
    delete Underlying;
  }
  private:
    T* Underlying;
};

template<typename T>
class Future {
public:
    T get() {
        return Pending;
    }
    ~Future();
private:
    T Pending;
};

class FooBar {
  public:
    ~FooBar();
  private:
    Future<int> Fut;
};

class FooQux {
  public:
    ~FooQux();
  private:
    Future<int> Fut;
};

class FizzFoo {
  public:
    ~FizzFoo();
  private:
    Future<int> Fut;
};

} // namespace async

// Warning is still emitted if there are type aliases.
namespace a {
template<typename T>
using Future = async::Future<T>;
} // namespace a

void releaseUnits();
struct Units {
  ~Units() {
    releaseUnits();
  }
};
a::Future<Units> acquireUnits();

template<typename T>
T qux(T Generic) {
    async::Future<Units> PendingA = acquireUnits();
    auto PendingB = acquireUnits();
    // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future<Units>' (aka 'Future<Units>') [bugprone-unused-local-non-trivial-variable]
    async::Future<Units> MustBeUsed;
    // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unused local variable 'MustBeUsed' of type 'async::Future<Units>' [bugprone-unused-local-non-trivial-variable]
    PendingA.get();
    async::Future<T> TemplateType;
    // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future<T>' [bugprone-unused-local-non-trivial-variable]
    a::Future<T> AliasTemplateType;
    // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'Future<type-parameter-0-0>') [bugprone-unused-local-non-trivial-variable]
    [[maybe_unused]] async::Future<Units> MaybeUnused;
    return Generic;
}

async::Future<int> Global;

int bar(int Num) {
    a::Future<Units> PendingA = acquireUnits();
    a::Future<Units> 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<Units>' (aka 'Future<Units>') [bugprone-unused-local-non-trivial-variable]
    auto Num2 = PendingA.get();
    auto Num3 = qux(Num);
    async::Ptr<a::Future<Units>> Shared = async::Ptr<a::Future<Units>>(acquireUnits());
    static auto UnusedStatic = async::Future<Units>();
    thread_local async::Future<Units> UnusedThreadLocal;
    auto Captured = acquireUnits();
    Num3 += [Captured]() {
      return 1;
    }();
    a::Future<Units> Referenced = acquireUnits();
    a::Future<Units>* Pointer = &Referenced;
    a::Future<Units>& Reference = Referenced;
    const a::Future<Units>& ConstReference = Referenced;
    try {
    } catch (a::Future<Units> Fut) {
    }
    struct Holder {
      a::Future<Units> 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]
}