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
/* -*- 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/.
 */

#if defined _WIN32 //TODO, see corresponding TODO in compilerplugins/clang/writeonlyvars.cxx
// expected-no-diagnostics
#else

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

namespace Bar
{
void test()
{
    // check that we DON'T see reads here
    // expected-error@+1 {{write m_bar3 [loplugin:writeonlyvars]}}
    int* m_bar3;
    // expected-error@+1 {{write m_bar3b [loplugin:writeonlyvars]}}
    int* m_bar3b;
    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
    // expected-error@+2 {{write m_bar4 [loplugin:writeonlyvars]}}
    // expected-error@+1 {{read m_bar4 [loplugin:writeonlyvars]}}
    int m_bar4;
    // expected-error@+1 {{read m_barfunctionpointer [loplugin:writeonlyvars]}}
    void (*m_barfunctionpointer)(int&) = nullptr;<--- Assignment 'm_barfunctionpointer=nullptr', assigned value is 0
    m_barfunctionpointer(m_bar4);<--- Null pointer dereference

    // check that we see reads of a field when used in variable init
    // expected-error@+1 {{read m_bar5 [loplugin:writeonlyvars]}}
    int m_bar5 = 1;
    int x = m_bar5;
    (void)x;

    // check that we see reads of a field when used in ranged-for
    // expected-error@+1 {{read m_bar6 [loplugin:writeonlyvars]}}
    std::vector<int> m_bar6;
    for (auto i : m_bar6)
    {
        (void)i;
    }

    // check that we see writes of array fields
    // expected-error@+1 {{write m_bar7 [loplugin:writeonlyvars]}}
    int m_bar7[5];
    m_bar7[3] = 1;<--- Variable 'm_bar7[3]' is assigned a value that is never used.

    // check that we see reads when a field is used in an array expression
    // expected-error@+1 {{read m_bar8 [loplugin:writeonlyvars]}}
    int m_bar8 = 1;
    // expected-error@+1 {{read tmp [loplugin:writeonlyvars]}}
    char tmp[5];<--- Variable 'tmp' is not assigned a value.
    auto x2 = tmp[m_bar8];
    (void)x2;

    // check that we don't see reads when calling operator>>=
    // expected-error@+1 {{write m_bar9 [loplugin:writeonlyvars]}}
    sal_Int32 m_bar9;
    // expected-error@+1 {{read any [loplugin:writeonlyvars]}}
    css::uno::Any any;
    any >>= m_bar9;<--- Variable 'any' is assigned a value that is never used.

    // check that we see don't see writes when calling operator<<=
    // expected-error@+1 {{read m_bar10 [loplugin:writeonlyvars]}}
    sal_Int32 m_bar10;
    // expected-error@+2 {{write any2 [loplugin:writeonlyvars]}}
    // expected-error@+1 {{read any2 [loplugin:writeonlyvars]}}
    css::uno::Any any2;
    any2 <<= m_bar10;<--- Variable 'any2' is assigned a value that is never used.
};
};

struct ReadOnly1
{
    ReadOnly1(int&);
};

namespace ReadOnlyAnalysis
{
void method1(int&);

void test()
{
    // check that we see a write when we pass by non-const ref
    // expected-error@+2 {{read m_f2 [loplugin:writeonlyvars]}}
    // expected-error@+1 {{write m_f2 [loplugin:writeonlyvars]}}
    int m_f2;
    method1(m_f2);

    // expected-error@+1 {{write m_f4 [loplugin:writeonlyvars]}}
    std::vector<int> m_f4;
    m_f4.push_back(1);

    // check that we see a write when we pass by non-const ref
    // expected-error@+2 {{read m_f5 [loplugin:writeonlyvars]}}
    // expected-error@+1 {{write m_f5 [loplugin:writeonlyvars]}}
    int m_f5;
    ReadOnly1 a(m_f5);<--- Variable 'a' is assigned a value that is never used.

    // check that we see a write when we pass by non-const ref
    // expected-error@+2 {{read m_f6 [loplugin:writeonlyvars]}}
    // expected-error@+1 {{write m_f6 [loplugin:writeonlyvars]}}
    int m_f6;
    // expected-error@+1 {{write r [loplugin:writeonlyvars]}}
    int& r = m_f6;
    r = 1;
};
};

void ReadOnlyAnalysis3()<--- The function 'ReadOnlyAnalysis3' is never used.
{
    // expected-error@+1 {{read m_f1 [loplugin:writeonlyvars]}}
    int m_f1 = 0;<--- Assignment 'm_f1=0', assigned value is 0

    if (m_f1)<--- Condition 'm_f1' is always false
        m_f1 = 1;<--- Variable 'm_f1' is assigned a value that is never used.
};

// Verify the special logic for container fields that only contains mutations that
// add elements.
void ReadOnlyAnalysis4()<--- The function 'ReadOnlyAnalysis4' is never used.
{
    // expected-error@+1 {{read m_readonly [loplugin:writeonlyvars]}}
    std::vector<int> m_readonly;
    // expected-error@+1 {{write m_writeonly [loplugin:writeonlyvars]}}
    std::vector<int> m_writeonly;
    // expected-error@+1 {{read m_readonlyCss [loplugin:writeonlyvars]}}
    css::uno::Sequence<sal_Int32> m_readonlyCss;

    // expected-error@+1 {{write x [loplugin:writeonlyvars]}}
    int x = m_readonly[0];<--- Access out of bounds
    (void)x;
    *m_readonly.begin() = 1; // TODO?

    m_writeonly.push_back(0);

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

#endif

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