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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <vector>
#include <ostream>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>

struct Foo
// expected-error@-1 {{read m_foo1 [loplugin:unusedfields]}}
{
    int m_foo1;
};

struct Bar
// expected-error@-1 {{read m_bar2 [loplugin:unusedfields]}}
// expected-error@-2 {{read m_bar4 [loplugin:unusedfields]}}
// expected-error@-3 {{read m_bar5 [loplugin:unusedfields]}}
// expected-error@-4 {{read m_bar6 [loplugin:unusedfields]}}
// expected-error@-5 {{read m_barfunctionpointer [loplugin:unusedfields]}}
// expected-error@-6 {{read m_bar8 [loplugin:unusedfields]}}
// expected-error@-7 {{read m_bar10 [loplugin:unusedfields]}}
// expected-error@-8 {{write m_bar1 [loplugin:unusedfields]}}
// expected-error@-9 {{write m_bar2 [loplugin:unusedfields]}}
// expected-error@-10 {{write m_bar3 [loplugin:unusedfields]}}
// expected-error@-11 {{write m_bar3b [loplugin:unusedfields]}}
// expected-error@-12 {{write m_bar4 [loplugin:unusedfields]}}
// expected-error@-13 {{write m_bar7 [loplugin:unusedfields]}}
// expected-error@-14 {{write m_bar9 [loplugin:unusedfields]}}
{
    int  m_bar1;
    int  m_bar2 = 1;
    int* m_bar3;
    int* m_bar3b;
    int  m_bar4;
    void (*m_barfunctionpointer)(int&);
    int  m_bar5;
    std::vector<int> m_bar6;
    int m_bar7[5];
    int m_bar8;
    int m_barstream;
    int m_bar9;
    int m_bar10;

    // check that we see reads of fields like m_foo1 when referred to via constructor initializer
    Bar(Foo const & foo) : m_bar1(foo.m_foo1) {}<--- Member variable 'Bar::m_bar3' is not initialized in the constructor.<--- Member variable 'Bar::m_bar3b' is not initialized in the constructor.<--- Member variable 'Bar::m_bar4' is not initialized in the constructor.<--- Member variable 'Bar::m_barfunctionpointer' is not initialized in the constructor.<--- Member variable 'Bar::m_bar5' is not initialized in the constructor.<--- Member variable 'Bar::m_bar7' is not initialized in the constructor.<--- Member variable 'Bar::m_bar8' is not initialized in the constructor.<--- Member variable 'Bar::m_barstream' is not initialized in the constructor.<--- Member variable 'Bar::m_bar9' is not initialized in the constructor.<--- Member variable 'Bar::m_bar10' is not initialized in the constructor.

    // check that we don't see reads when inside copy/move constructor
    Bar(Bar const & other) { m_bar3 = other.m_bar3; }<--- Member variable 'Bar::m_bar1' is not initialized in the constructor.<--- Member variable 'Bar::m_bar3b' is not initialized in the constructor.<--- Member variable 'Bar::m_bar4' is not initialized in the constructor.<--- Member variable 'Bar::m_barfunctionpointer' is not initialized in the constructor.<--- Member variable 'Bar::m_bar5' is not initialized in the constructor.<--- Member variable 'Bar::m_bar7' is not initialized in the constructor.<--- Member variable 'Bar::m_bar8' is not initialized in the constructor.<--- Member variable 'Bar::m_barstream' is not initialized in the constructor.<--- Member variable 'Bar::m_bar9' is not initialized in the constructor.<--- Member variable 'Bar::m_bar10' is not initialized in the constructor.

    // check that we don't see reads when inside copy/move assignment operator
    Bar& operator=(Bar const & other) { m_bar3 = other.m_bar3; return *this; }<--- Member variable 'Bar::m_bar1' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar3b' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar4' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_barfunctionpointer' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar5' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar7' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar8' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_barstream' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar9' is not assigned a value in 'Bar::operator='.<--- Member variable 'Bar::m_bar10' is not assigned a value in 'Bar::operator='.

    // check that we DON'T see reads here
    int bar2() { return m_bar2; }<--- The function 'bar2' is never used.

    // check that we DON'T see reads here
    void bar3()<--- The function 'bar3' is never used.
    {
        m_bar3 = nullptr;
        m_bar3b = m_bar3 = nullptr;
    }

    // check that we see reads of field when passed to a function pointer
    // check that we see read of a field that is a function pointer
    void bar4() { m_barfunctionpointer(m_bar4); }<--- The function 'bar4' is never used.

    // check that we see reads of a field when used in variable init
    void bar5() { int x = m_bar5; (void) x; }<--- The function 'bar5' is never used.

    // check that we see reads of a field when used in ranged-for
    void bar6() { for (auto i : m_bar6) { (void)i; } }<--- The function 'bar6' is never used.

    // check that we see don't see reads of array fields
    void bar7() { m_bar7[3] = 1; }<--- The function 'bar7' is never used.

    // check that we see reads when a field is used in an array expression
    char bar8()<--- The function 'bar8' is never used.
    {
        char tmp[5];<--- Variable 'tmp' is not assigned a value.
        return tmp[m_bar8];<--- Uninitialized variable: tmp
    }

    // check that we don't see reads when calling operator>>=
    void bar9()<--- The function 'bar9' is never used.
    {
        css::uno::Any any;
        any >>= m_bar9;
    }

    // check that we see don't see writes when calling operator<<=
    void bar10()<--- The function 'bar10' is never used.
    {
        css::uno::Any any;
        any <<= m_bar10;
    }
};

// check that we __dont__ see a read of m_barstream
std::ostream& operator<<(std::ostream& s, Bar const & bar)
{
    s << bar.m_barstream;
    return s;
};

struct ReadOnly1 { ReadOnly1(int&); };

struct ReadOnlyAnalysis
// expected-error@-1 {{read m_f2 [loplugin:unusedfields]}}
// expected-error@-2 {{read m_f3 [loplugin:unusedfields]}}
// expected-error@-3 {{read m_f4 [loplugin:unusedfields]}}
// expected-error@-4 {{read m_f5 [loplugin:unusedfields]}}
// expected-error@-5 {{read m_f6 [loplugin:unusedfields]}}
// expected-error@-6 {{write m_f2 [loplugin:unusedfields]}}
// expected-error@-7 {{write m_f3 [loplugin:unusedfields]}}
// expected-error@-8 {{write m_f4 [loplugin:unusedfields]}}
// expected-error@-9 {{write m_f5 [loplugin:unusedfields]}}
// expected-error@-10 {{write m_f6 [loplugin:unusedfields]}}
{
    int m_f1;
    int m_f2;
    int m_f3;
    std::vector<int> m_f4;
    int m_f5;
    int m_f6;

    // check that we don't see a write of m_f1
    ReadOnlyAnalysis() : m_f1(0) {}<--- Member variable 'ReadOnlyAnalysis::m_f2' is not initialized in the constructor.<--- Member variable 'ReadOnlyAnalysis::m_f3' is not initialized in the constructor.<--- Member variable 'ReadOnlyAnalysis::m_f5' is not initialized in the constructor.<--- Member variable 'ReadOnlyAnalysis::m_f6' is not initialized in the constructor.

    void method1(int&);

    // check that we see a write when we pass by non-const ref
    void method2() { method1(m_f2); }

    int& method3() { return m_f3; }<--- The function 'method3' is never used.

    void method4() { m_f4.push_back(1); }<--- The function 'method4' is never used.

    // check that we see a write when we pass by non-const ref
    void method5() { ReadOnly1 a(m_f5); }<--- The function 'method5' is never used.

    // check that we see a write when we pass by non-const ref
    void method6()<--- The function 'method6' is never used.
    {
        int& r = m_f6;
        r = 1;
    }
};

struct ReadOnlyAnalysis2
// expected-error@-1 {{write m_r2f1 [loplugin:unusedfields]}}
{
    int m_r2f1;
};

ReadOnlyAnalysis2 global { 1 };

struct ReadOnlyAnalysis3
// expected-error@-1 {{read m_f1 [loplugin:unusedfields]}}
{
    int m_f1;

    void func1()
    {
        if (m_f1)
            m_f1 = 1;
    }
};

// Verify the special logic for container fields that only contains mutations that
// add elements.
struct ReadOnlyAnalysis4
// expected-error@-1 {{read m_readonly [loplugin:unusedfields]}}
// expected-error@-2 {{read m_readwrite [loplugin:unusedfields]}}
// expected-error@-3 {{write m_readwrite [loplugin:unusedfields]}}
// expected-error@-4 {{read m_readonlyCss [loplugin:unusedfields]}}
{
    std::vector<int> m_readonly;
    std::vector<int> m_readwrite;
    css::uno::Sequence<sal_Int32> m_readonlyCss;

    void func1()
    {
        int x = m_readonly[0];
        (void)x;
        *m_readonly.begin() = 1;

        m_readwrite.push_back(0);

        x = m_readonlyCss.getArray()[0];<--- Variable 'x' is assigned a value that is never used.
    }
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */