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 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++17 %s
5
6 // PR4806
7 namespace test0 {
8 class Box {
9 public:
10 int i;
11 volatile int j;
12 };
13
doit()14 void doit() {
15 // pointer to volatile has side effect (thus no warning)
16 Box* box = new Box;
17 box->i; // expected-warning {{expression result unused}}
18 box->j;
19 #if __cplusplus <= 199711L
20 // expected-warning@-2 {{expression result unused}}
21 #endif
22 }
23 }
24
25 namespace test1 {
26 struct Foo {
27 int i;
operator ==test1::Foo28 bool operator==(const Foo& rhs) {
29 return i == rhs.i;
30 }
31 };
32
33 #define NOP(x) (x)
b(Foo f1,Foo f2)34 void b(Foo f1, Foo f2) {
35 NOP(f1 == f2); // expected-warning {{expression result unused}}
36 }
37 #undef NOP
38 }
39
40 namespace test2 {
41 extern "C++" {
42 namespace std {
43 template<typename T> struct basic_string {
44 struct X {};
methodtest2::std::basic_string45 void method() const {
46 X* x;
47 &x[0]; // expected-warning {{expression result unused}}
48 }
49 };
50 typedef basic_string<char> string;
func(const std::string & str)51 void func(const std::string& str) {
52 str.method(); // expected-note {{in instantiation of member function}}
53 }
54 }
55 }
56 }
57
58 namespace test3 {
59 struct Used {
60 Used();
61 Used(int);
62 Used(int, int);
~Usedtest3::Used63 ~Used() {}
64 };
65 struct __attribute__((warn_unused)) Unused {
66 Unused();
67 Unused(int);
68 Unused(int, int);
~Unusedtest3::Unused69 ~Unused() {}
70 };
f()71 void f() {
72 Used();
73 Used(1);
74 Used(1, 1);
75 Unused(); // expected-warning {{expression result unused}}
76 Unused(1); // expected-warning {{expression result unused}}
77 Unused(1, 1); // expected-warning {{expression result unused}}
78 #if __cplusplus >= 201103L // C++11 or later
79 Used({});
80 Unused({}); // expected-warning {{expression result unused}}
81 #endif
82 }
83 }
84
85 namespace std {
86 struct type_info {};
87 }
88
89 namespace test4 {
90 struct Good { Good &f(); };
91 struct Bad { virtual Bad& f(); };
92
f()93 void f() {
94 int i = 0;
95 (void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
96
97 Good g;
98 (void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.
99
100 // This is a polymorphic use of a glvalue, which results in the typeid being
101 // evaluated instead of unevaluated.
102 Bad b;
103 (void)typeid(b.f()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
104
105 extern Bad * pb;
106 // This typeid can throw but that is not a side-effect that we care about
107 // warning for since this is idiomatic code
108 (void)typeid(*pb);
109 (void)sizeof(typeid(*pb));
110 (void)typeid(*++pb); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
111 (void)sizeof(typeid(*++pb)); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
112 // FIXME: we should not warn about this in an unevaluated context
113 // expected-warning@-2 {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
114
115 // A dereference of a volatile pointer is a side effecting operation, however
116 // since it is idiomatic code, and the alternatives induce higher maintenance
117 // costs, it is allowed.
118 int * volatile x;
119 (void)sizeof(*x); // Ok
120 }
121 }
122
123 static volatile char var1 = 'a';
124 volatile char var2 = 'a';
125 static volatile char arr1[] = "hello";
126 volatile char arr2[] = "hello";
volatile_array()127 void volatile_array() {
128 static volatile char var3 = 'a';
129 volatile char var4 = 'a';
130 static volatile char arr3[] = "hello";
131 volatile char arr4[] = "hello";
132
133 // These all result in volatile loads in C and C++11. In C++98, they don't,
134 // but we suppress the warning in the case where '(void)var;' might be
135 // idiomatically suppressing an 'unused variable' warning.
136 (void)var1;
137 (void)var2;
138 #if __cplusplus < 201103L
139 // expected-warning@-2 {{expression result unused; assign into a variable to force a volatile load}}
140 #endif
141 (void)var3;
142 (void)var4;
143
144 // None of these result in volatile loads in any language mode, and it's not
145 // really reasonable to assume that they would, since volatile array loads
146 // don't really exist anywhere.
147 (void)arr1;
148 (void)arr2;
149 (void)arr3;
150 (void)arr4;
151 }
152
153 #if __cplusplus >= 201103L // C++11 or later
154 namespace test5 {
155 int v[(5, 6)]; // expected-warning {{left operand of comma operator has no effect}}
foo()156 void foo() {
157 new double[false ? (1, 2) : 3]
158 // FIXME: We shouldn't diagnose the unreachable constant expression
159 // here.
160 [false ? (1, 2) : 3]; // expected-warning {{left operand of comma operator has no effect}}
161 }
162 } // namespace test5
163
164 // comma operator diagnostics should be suppressed in a SFINAE context.
c(int)165 template <typename T, int = (T{},0)> int c(int) { return 0; }
c(double)166 template <typename T, int> int c(double) { return 1; }
foo()167 int foo() { return c<int>(0); }
168
169 #endif
170
171 #if __cplusplus >= 201703L // C++17 or later
172 namespace test6 {
b()173 auto b() {
174 if constexpr (false)
175 return (1,0);
176 else
177 return (1.0,0.0); // expected-warning {{left operand of comma operator has no effect}}
178 }
179 } // namespace test6
180 #endif
181