summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/tests/TestNonParameterChecker.cpp
blob: d3c2b9b379a11333736074fb73621c294e40e1a2 (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
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
#define MOZ_NON_PARAM __attribute__((annotate("moz_non_param")))

struct Param {};
struct MOZ_NON_PARAM NonParam {};
union MOZ_NON_PARAM NonParamUnion {};
class MOZ_NON_PARAM NonParamClass {};
enum MOZ_NON_PARAM NonParamEnum { X, Y, Z };
enum class MOZ_NON_PARAM NonParamEnumClass { X, Y, Z };

struct HasNonParamStruct { NonParam x; int y; }; // expected-note 14 {{'HasNonParamStruct' is a non-param type because member 'x' is a non-param type 'NonParam'}}
union HasNonParamUnion { NonParam x; int y; }; // expected-note 18 {{'HasNonParamUnion' is a non-param type because member 'x' is a non-param type 'NonParam'}}
struct HasNonParamStructUnion { HasNonParamUnion z; }; // expected-note 9 {{'HasNonParamStructUnion' is a non-param type because member 'z' is a non-param type 'HasNonParamUnion'}}

#define MAYBE_STATIC
#include "NonParameterTestCases.h"
#undef MAYBE_STATIC

// Do not check typedef and using.
typedef void (*funcTypeParam)(Param x);
typedef void (*funcTypeNonParam)(NonParam x);

using usingFuncTypeParam = void (*)(Param x);
using usingFuncTypeNonParam = void (*)(NonParam x);

class class_
{
    explicit class_(Param x) {}
    explicit class_(NonParam x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    explicit class_(HasNonParamStruct x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    explicit class_(HasNonParamUnion x) {} //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    explicit class_(HasNonParamStructUnion x) {} //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}

#define MAYBE_STATIC
#include "NonParameterTestCases.h"
#undef MAYBE_STATIC
};

class classWithStatic
{
#define MAYBE_STATIC static
#include "NonParameterTestCases.h"
#undef MAYBE_STATIC
};

template <typename T>
class tmplClassForParam
{
public:
    void raw(T x) {}
    void rawDefault(T x = T()) {}
    void const_(const T x) {}
    void ptr(T* x) {}
    void ref(T& x) {}
    void constRef(const T& x) {}

    void notCalled(T x) {}
};

template <typename T>
class tmplClassForNonParam
{
public:
    void raw(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    void rawDefault(T x = T()) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    void const_(const T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    void ptr(T* x) {}
    void ref(T& x) {}
    void constRef(const T& x) {}

    void notCalled(T x) {}
};

template <typename T>
class tmplClassForHasNonParamStruct
{
public:
    void raw(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    void rawDefault(T x = T()) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    void const_(const T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    void ptr(T* x) {}
    void ref(T& x) {}
    void constRef(const T& x) {}

    void notCalled(T x) {}
};

void testTemplateClass()
{
    tmplClassForParam<Param> paramClass;
    Param param;
    paramClass.raw(param);
    paramClass.rawDefault();
    paramClass.const_(param);
    paramClass.ptr(&param);
    paramClass.ref(param);
    paramClass.constRef(param);

    tmplClassForNonParam<NonParam> nonParamClass; //expected-note 3 {{The bad argument was passed to 'tmplClassForNonParam' here}}
    NonParam nonParam;
    nonParamClass.raw(nonParam);
    nonParamClass.rawDefault();
    nonParamClass.const_(nonParam);
    nonParamClass.ptr(&nonParam);
    nonParamClass.ref(nonParam);
    nonParamClass.constRef(nonParam);

    tmplClassForHasNonParamStruct<HasNonParamStruct> hasNonParamStructClass;//expected-note 3 {{The bad argument was passed to 'tmplClassForHasNonParamStruct' here}}
    HasNonParamStruct hasNonParamStruct;
    hasNonParamStructClass.raw(hasNonParamStruct);
    hasNonParamStructClass.rawDefault();
    hasNonParamStructClass.const_(hasNonParamStruct);
    hasNonParamStructClass.ptr(&hasNonParamStruct);
    hasNonParamStructClass.ref(hasNonParamStruct);
    hasNonParamStructClass.constRef(hasNonParamStruct);
}

template <typename T>
class NestedTemplateInner
{
public:
    void raw(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
};

template <typename T>
class nestedTemplateOuter
{
public:
    void constRef(const T& x) {
        NestedTemplateInner<T> inner; //expected-note {{The bad argument was passed to 'NestedTemplateInner' here}}
        inner.raw(x);
    }
};

void testNestedTemplateClass()
{
    nestedTemplateOuter<NonParam> outer;
    NonParam nonParam;
    outer.constRef(nonParam); // FIXME: this line needs note "The bad argument was passed to 'constRef' here"
}

template <typename T>
void tmplFuncForParam(T x) {}
template <typename T>
void tmplFuncForNonParam(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
template <typename T>
void tmplFuncForNonParamImplicit(T x) {} //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
template <typename T>
void tmplFuncForHasNonParamStruct(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
template <typename T>
void tmplFuncForHasNonParamStructImplicit(T x) {} //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}

void testTemplateFunc()
{
    Param param;
    tmplFuncForParam<Param>(param);

    NonParam nonParam;
    tmplFuncForNonParam<NonParam>(nonParam); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForNonParam' here"
    tmplFuncForNonParamImplicit(nonParam); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForNonParamImplicit' here"

    HasNonParamStruct hasNonParamStruct;
    tmplFuncForHasNonParamStruct<HasNonParamStruct>(hasNonParamStruct); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForHasNonParamStruct' here"
    tmplFuncForHasNonParamStructImplicit(hasNonParamStruct); // FIXME: this line needs note "The bad argument was passed to 'tmplFuncForHasNonParamStructImplicit' here"
}

void testLambda()
{
    auto paramLambda = [](Param x) -> void {};
    auto nonParamLambda = [](NonParam x) -> void {}; //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    auto nonParamStructLambda = [](HasNonParamStruct x) -> void {}; //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    auto nonParamUnionLambda = [](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    auto nonParamStructUnionLambda = [](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}

    (void)[](Param x) -> void {};
    (void)[](NonParam x) -> void {}; //expected-error {{Type 'NonParam' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    (void)[](HasNonParamStruct x) -> void {}; //expected-error {{Type 'HasNonParamStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    (void)[](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
    (void)[](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
}

// Check that alignas() implies the MOZ_NON_PARAM attribute.

struct alignas(8) AlignasStruct { char a; }; // expected-note {{'AlignasStruct' is a non-param type because it has an alignas(_) annotation}}
void takesAlignasStruct(AlignasStruct x) { } // expected-error {{Type 'AlignasStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
void takesAlignasStructByRef(const AlignasStruct& x) { }

struct AlignasMember { alignas(8) char a; }; // expected-note {{'AlignasMember' is a non-param type because member 'a' has an alignas(_) annotation}}
void takesAlignasMember(AlignasMember x) { } // expected-error {{Type 'AlignasMember' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}}
void takesAlignasMemberByRef(const AlignasMember& x) { }