warn-unused-value.cpp
3.51 KB
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
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++11 %s
// PR4806
namespace test0 {
class Box {
public:
int i;
volatile int j;
};
void doit() {
// pointer to volatile has side effect (thus no warning)
Box* box = new Box;
box->i; // expected-warning {{expression result unused}}
box->j;
#if __cplusplus <= 199711L
// expected-warning@-2 {{expression result unused}}
#endif
}
}
namespace test1 {
struct Foo {
int i;
bool operator==(const Foo& rhs) {
return i == rhs.i;
}
};
#define NOP(x) (x)
void b(Foo f1, Foo f2) {
NOP(f1 == f2); // expected-warning {{expression result unused}}
}
#undef NOP
}
namespace test2 {
extern "C++" {
namespace std {
template<typename T> struct basic_string {
struct X {};
void method() const {
X* x;
&x[0]; // expected-warning {{expression result unused}}
}
};
typedef basic_string<char> string;
void func(const std::string& str) {
str.method(); // expected-note {{in instantiation of member function}}
}
}
}
}
namespace test3 {
struct Used {
Used();
Used(int);
Used(int, int);
~Used() {}
};
struct __attribute__((warn_unused)) Unused {
Unused();
Unused(int);
Unused(int, int);
~Unused() {}
};
void f() {
Used();
Used(1);
Used(1, 1);
Unused(); // expected-warning {{expression result unused}}
Unused(1); // expected-warning {{expression result unused}}
Unused(1, 1); // expected-warning {{expression result unused}}
#if __cplusplus >= 201103L // C++11 or later
Used({});
Unused({}); // expected-warning {{expression result unused}}
#endif
}
}
namespace std {
struct type_info {};
}
namespace test4 {
struct Good { Good &f(); };
struct Bad { virtual Bad& f(); };
void f() {
int i = 0;
(void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
Good g;
(void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.
// This is a polymorphic use of a glvalue, which results in the typeid being
// evaluated instead of unevaluated.
Bad b;
(void)typeid(b.f()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
// A dereference of a volatile pointer is a side effecting operation, however
// since it is idiomatic code, and the alternatives induce higher maintenance
// costs, it is allowed.
int * volatile x;
(void)sizeof(*x); // Ok
}
}
static volatile char var1 = 'a';
volatile char var2 = 'a';
static volatile char arr1[] = "hello";
volatile char arr2[] = "hello";
void volatile_array() {
static volatile char var3 = 'a';
volatile char var4 = 'a';
static volatile char arr3[] = "hello";
volatile char arr4[] = "hello";
// These all result in volatile loads in C and C++11. In C++98, they don't,
// but we suppress the warning in the case where '(void)var;' might be
// idiomatically suppressing an 'unused variable' warning.
(void)var1;
(void)var2;
#if __cplusplus < 201103L
// expected-warning@-2 {{expression result unused; assign into a variable to force a volatile load}}
#endif
(void)var3;
(void)var4;
// None of these result in volatile loads in any language mode, and it's not
// really reasonable to assume that they would, since volatile array loads
// don't really exist anywhere.
(void)arr1;
(void)arr2;
(void)arr3;
(void)arr4;
}