1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 2 3 int f() __attribute__((warn_unused_result)); 4 5 struct S { 6 void t() const; 7 }; 8 S g1() __attribute__((warn_unused_result)); 9 S *g2() __attribute__((warn_unused_result)); 10 S &g3() __attribute__((warn_unused_result)); 11 12 void test() { 13 f(); // expected-warning {{ignoring return value}} 14 g1(); // expected-warning {{ignoring return value}} 15 g2(); // expected-warning {{ignoring return value}} 16 g3(); // expected-warning {{ignoring return value}} 17 18 (void)f(); 19 (void)g1(); 20 (void)g2(); 21 (void)g3(); 22 23 if (f() == 0) return; 24 25 g1().t(); 26 g2()->t(); 27 g3().t(); 28 29 int i = f(); 30 S s1 = g1(); 31 S *s2 = g2(); 32 S &s3 = g3(); 33 const S &s4 = g1(); 34 } 35 36 void testSubstmts(int i) { 37 switch (i) { 38 case 0: 39 f(); // expected-warning {{ignoring return value}} 40 default: 41 f(); // expected-warning {{ignoring return value}} 42 } 43 44 if (i) 45 f(); // expected-warning {{ignoring return value}} 46 else 47 f(); // expected-warning {{ignoring return value}} 48 49 while (i) 50 f(); // expected-warning {{ignoring return value}} 51 52 do 53 f(); // expected-warning {{ignoring return value}} 54 while (i); 55 56 for (f(); // expected-warning {{ignoring return value}} 57 ; 58 f() // expected-warning {{ignoring return value}} 59 ) 60 f(); // expected-warning {{ignoring return value}} 61 62 f(), // expected-warning {{ignoring return value}} 63 (void)f(); 64 } 65 66 struct X { 67 int foo() __attribute__((warn_unused_result)); 68 }; 69 70 void bah() { 71 X x, *x2; 72 x.foo(); // expected-warning {{ignoring return value}} 73 x2->foo(); // expected-warning {{ignoring return value}} 74 } 75 76 namespace warn_unused_CXX11 { 77 class Status; 78 class Foo { 79 public: 80 Status doStuff(); 81 }; 82 83 struct [[clang::warn_unused_result]] Status { 84 bool ok() const; 85 Status& operator=(const Status& x); 86 inline void Update(const Status& new_status) { 87 if (ok()) { 88 *this = new_status; //no-warning 89 } 90 } 91 }; 92 Status DoSomething(); 93 Status& DoSomethingElse(); 94 Status* DoAnotherThing(); 95 Status** DoYetAnotherThing(); 96 void lazy() { 97 Status s = DoSomething(); 98 if (!s.ok()) return; 99 Status &rs = DoSomethingElse(); 100 if (!rs.ok()) return; 101 Status *ps = DoAnotherThing(); 102 if (!ps->ok()) return; 103 Status **pps = DoYetAnotherThing(); 104 if (!(*pps)->ok()) return; 105 106 (void)DoSomething(); 107 (void)DoSomethingElse(); 108 (void)DoAnotherThing(); 109 (void)DoYetAnotherThing(); 110 111 DoSomething(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} 112 DoSomethingElse(); 113 DoAnotherThing(); 114 DoYetAnotherThing(); 115 } 116 117 template <typename T> 118 class [[clang::warn_unused_result]] StatusOr { 119 }; 120 StatusOr<int> doit(); 121 void test() { 122 Foo f; 123 f.doStuff(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} 124 doit(); // expected-warning {{ignoring return value of type 'StatusOr<int>' declared with 'warn_unused_result'}} 125 126 auto func = []() { return Status(); }; 127 func(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} 128 } 129 } 130 131 namespace PR17587 { 132 struct [[clang::warn_unused_result]] Status; 133 134 struct Foo { 135 Status Bar(); 136 }; 137 138 struct Status {}; 139 140 void Bar() { 141 Foo f; 142 f.Bar(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} 143 }; 144 145 } 146 147 namespace PR18571 { 148 // Unevaluated contexts should not trigger unused result warnings. 149 template <typename T> 150 auto foo(T) -> decltype(f(), bool()) { // Should not warn. 151 return true; 152 } 153 154 void g() { 155 foo(1); 156 } 157 } 158 159 namespace std { 160 class type_info { }; 161 } 162 163 namespace { 164 // The typeid expression operand is evaluated only when the expression type is 165 // a glvalue of polymorphic class type. 166 167 struct B { 168 virtual void f() {} 169 }; 170 171 struct D : B { 172 void f() override {} 173 }; 174 175 struct C {}; 176 177 void g() { 178 // The typeid expression operand is evaluated only when the expression type is 179 // a glvalue of polymorphic class type; otherwise the expression operand is not 180 // evaluated and should not trigger a diagnostic. 181 D d; 182 C c; 183 (void)typeid(f(), c); // Should not warn. 184 (void)typeid(f(), d); // expected-warning {{ignoring return value}} expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}} 185 186 // The sizeof expression operand is never evaluated. 187 (void)sizeof(f(), c); // Should not warn. 188 189 // The noexcept expression operand is never evaluated. 190 (void)noexcept(f(), false); // Should not warn. 191 } 192 } 193 194 namespace { 195 // C++ Methods should warn even in their own class. 196 struct [[clang::warn_unused_result]] S { 197 S DoThing() { return {}; }; 198 S operator++(int) { return {}; }; 199 S operator--(int) { return {}; }; 200 // Improperly written prefix. 201 S operator++() { return {}; }; 202 S operator--() { return {}; }; 203 }; 204 205 struct [[clang::warn_unused_result]] P { 206 P DoThing() { return {}; }; 207 }; 208 209 P operator++(const P &, int) { return {}; }; 210 P operator--(const P &, int) { return {}; }; 211 // Improperly written prefix. 212 P operator++(const P &) { return {}; }; 213 P operator--(const P &) { return {}; }; 214 215 void f() { 216 S s; 217 P p; 218 s.DoThing(); // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} 219 p.DoThing(); // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} 220 // Only postfix is expected to warn when written correctly. 221 s++; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} 222 s--; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} 223 p++; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} 224 p--; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} 225 // Improperly written prefix operators should still warn. 226 ++s; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} 227 --s; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} 228 ++p; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} 229 --p; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} 230 231 // Silencing the warning by cast to void still works. 232 (void)s.DoThing(); 233 (void)s++; 234 (void)p++; 235 (void)++s; 236 (void)++p; 237 } 238 } // namespace 239 240 namespace PR39837 { 241 [[clang::warn_unused_result]] int f(int); 242 243 void g() { 244 int a[2]; 245 for (int b : a) 246 f(b); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} 247 } 248 } // namespace PR39837 249 250 namespace PR45520 { 251 [[nodiscard]] bool (*f)(); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}} 252 [[clang::warn_unused_result]] bool (*g)(); 253 __attribute__((warn_unused_result)) bool (*h)(); 254 255 void i([[nodiscard]] bool (*fp)()); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}} 256 } 257 258 namespace unused_typedef_result { 259 [[clang::warn_unused_result]] typedef void *a; 260 typedef a indirect; 261 a af1(); 262 indirect indirectf1(); 263 void af2() { 264 af1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}} 265 void *(*a1)(); 266 a1(); // no warning 267 a (*a2)(); 268 a2(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}} 269 indirectf1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}} 270 } 271 [[nodiscard]] typedef void *b1; // expected-warning {{'[[nodiscard]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}} 272 [[gnu::warn_unused_result]] typedef void *b2; // expected-warning {{'[[gnu::warn_unused_result]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}} 273 b1 b1f1(); 274 b2 b2f1(); 275 void bf2() { 276 b1f1(); // no warning 277 b2f1(); // no warning 278 } 279 __attribute__((warn_unused_result)) typedef void *c; 280 c cf1(); 281 void cf2() { 282 cf1(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}} 283 void *(*c1)(); 284 c1(); 285 c (*c2)(); 286 c2(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}} 287 } 288 } 289 290 namespace nodiscard_specialization { 291 // Test to only mark a specialization of class template as nodiscard 292 template<typename T> struct S { S(int) {} }; 293 template<> struct [[nodiscard]] S<int> { S(int) {} }; 294 template<typename T> struct [[clang::warn_unused_result]] S<const T> { S(int) {} }; 295 296 template<typename T> 297 S<T> obtain(const T&) { return {2}; } 298 299 template<typename T> 300 [[nodiscard]] S<T> obtain2(const T&) { return {2}; } 301 302 template<typename T> 303 __attribute__((warn_unused_result)) S<T> obtain3(const T&) { return {2}; } 304 305 void use() { 306 obtain(1.0); // no warning 307 obtain(1); // expected-warning {{ignoring return value of type 'S<int>' declared with 'nodiscard'}} 308 obtain<const double>(1); // expected-warning {{ignoring return value of type 'S<const double>' declared with 'warn_unused_result'}} 309 310 S<double>(2); // no warning 311 S<int>(2); // expected-warning {{ignoring temporary of type 'S<int>' declared with 'nodiscard'}} 312 S<const char>(2); // no warning (warn_unused_result does not diagnose constructor temporaries) 313 314 // function should take precedence over type 315 obtain2(1.0); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} 316 obtain2(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} 317 obtain2<const double>(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} 318 obtain3(1.0); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} 319 obtain3(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} 320 obtain3<const double>(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} 321 } 322 323 // Test on constructor nodiscard 324 struct H { 325 explicit H(int) {} 326 [[nodiscard]] explicit H(double) {} 327 __attribute__((warn_unused_result)) H(const char*) {} 328 }; 329 330 struct [[nodiscard]] G { 331 explicit G(int) {} 332 [[nodiscard]] explicit G(double) {} 333 [[clang::warn_unused_result]] G(const char*) {} 334 }; 335 336 void use2() { 337 H{2}; // no warning 338 H(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}} 339 H("Hello"); // no warning (warn_unused_result does not diagnose constructor temporaries) 340 341 // no warning for explicit cast to void 342 (void)H(2); 343 (void)H{2.0}; 344 (void)H{"Hello"}; 345 346 // warns for all these invocations 347 // here, constructor/function should take precedence over type 348 G{2}; // expected-warning {{ignoring temporary of type 'G' declared with 'nodiscard'}} 349 G(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}} 350 G("Hello"); // expected-warning {{ignoring temporary created by a constructor declared with 'warn_unused_result'}} 351 352 // no warning for explicit cast to void 353 (void)G(2); 354 (void)G{2.0}; 355 (void)G{"Hello"}; 356 } 357 } // namespace nodiscard_specialization 358 359 namespace GH117975 { 360 // Test for a regression for ICE in CallExpr::getUnusedResultAttr 361 int f() { return 0; } 362 void id_print_name() { 363 (int) // expected-warning {{expression result unused}} 364 ((int(*)())f)(); 365 } 366 } // namespace GH117975 367