1 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++98 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++11 %s
4
5 // PR4806
6 namespace test0 {
7 class Box {
8 public:
9 int i;
10 volatile int j;
11 };
12
doit()13 void doit() {
14 // pointer to volatile has side effect (thus no warning)
15 Box* box = new Box;
16 box->i; // expected-warning {{expression result unused}}
17 box->j;
18 #if __cplusplus <= 199711L
19 // expected-warning@-2 {{expression result unused}}
20 #endif
21 }
22 }
23
24 namespace test1 {
25 struct Foo {
26 int i;
operator ==test1::Foo27 bool operator==(const Foo& rhs) {
28 return i == rhs.i;
29 }
30 };
31
32 #define NOP(x) (x)
b(Foo f1,Foo f2)33 void b(Foo f1, Foo f2) {
34 NOP(f1 == f2); // expected-warning {{expression result unused}}
35 }
36 #undef NOP
37 }
38
39 namespace test2 {
40 extern "C++" {
41 namespace std {
42 template<typename T> struct basic_string {
43 struct X {};
methodtest2::std::basic_string44 void method() const {
45 X* x;
46 &x[0]; // expected-warning {{expression result unused}}
47 }
48 };
49 typedef basic_string<char> string;
func(const std::string & str)50 void func(const std::string& str) {
51 str.method(); // expected-note {{in instantiation of member function}}
52 }
53 }
54 }
55 }
56
57 namespace test3 {
58 struct Used {
59 Used();
60 Used(int);
61 Used(int, int);
~Usedtest3::Used62 ~Used() {}
63 };
64 struct __attribute__((warn_unused)) Unused {
65 Unused();
66 Unused(int);
67 Unused(int, int);
~Unusedtest3::Unused68 ~Unused() {}
69 };
f()70 void f() {
71 Used();
72 Used(1);
73 Used(1, 1);
74 Unused(); // expected-warning {{expression result unused}}
75 Unused(1); // expected-warning {{expression result unused}}
76 Unused(1, 1); // expected-warning {{expression result unused}}
77 #if __cplusplus >= 201103L // C++11 or later
78 Used({});
79 Unused({}); // expected-warning {{expression result unused}}
80 #endif
81 }
82 }
83
84 namespace std {
85 struct type_info {};
86 }
87
88 namespace test4 {
89 struct Good { Good &f(); };
90 struct Bad { virtual Bad& f(); };
91
f()92 void f() {
93 int i = 0;
94 (void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
95
96 Good g;
97 (void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.
98
99 // This is a polymorphic use of a glvalue, which results in the typeid being
100 // evaluated instead of unevaluated.
101 Bad b;
102 (void)typeid(b.f()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
103
104 // A dereference of a volatile pointer is a side effecting operation, however
105 // since it is idiomatic code, and the alternatives induce higher maintenance
106 // costs, it is allowed.
107 int * volatile x;
108 (void)sizeof(*x); // Ok
109 }
110 }
111
112 static volatile char var1 = 'a';
113 volatile char var2 = 'a';
114 static volatile char arr1[] = "hello";
115 volatile char arr2[] = "hello";
volatile_array()116 void volatile_array() {
117 static volatile char var3 = 'a';
118 volatile char var4 = 'a';
119 static volatile char arr3[] = "hello";
120 volatile char arr4[] = "hello";
121
122 // These all result in volatile loads in C and C++11. In C++98, they don't,
123 // but we suppress the warning in the case where '(void)var;' might be
124 // idiomatically suppressing an 'unused variable' warning.
125 (void)var1;
126 (void)var2;
127 #if __cplusplus < 201103L
128 // expected-warning@-2 {{expression result unused; assign into a variable to force a volatile load}}
129 #endif
130 (void)var3;
131 (void)var4;
132
133 // None of these result in volatile loads in any language mode, and it's not
134 // really reasonable to assume that they would, since volatile array loads
135 // don't really exist anywhere.
136 (void)arr1;
137 (void)arr2;
138 (void)arr3;
139 (void)arr4;
140 }
141