495 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s2 3int f() __attribute__((warn_unused_result));4 5struct S {6 void t() const;7};8S g1() __attribute__((warn_unused_result));9S *g2() __attribute__((warn_unused_result));10S &g3() __attribute__((warn_unused_result));11 12void 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 36void 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 else47 f(); // expected-warning {{ignoring return value}}48 49 while (i)50 f(); // expected-warning {{ignoring return value}}51 52 do53 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 66struct X {67 int foo() __attribute__((warn_unused_result));68};69 70void bah() {71 X x, *x2;72 x.foo(); // expected-warning {{ignoring return value}}73 x2->foo(); // expected-warning {{ignoring return value}}74}75 76namespace warn_unused_CXX11 {77class Status;78class Foo {79 public:80 Status doStuff();81};82 83struct [[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-warning89 }90 }91};92Status DoSomething();93Status& DoSomethingElse();94Status* DoAnotherThing();95Status** DoYetAnotherThing();96void 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 'clang::warn_unused_result'}}112 DoSomethingElse();113 DoAnotherThing();114 DoYetAnotherThing();115}116 117template <typename T>118class [[clang::warn_unused_result]] StatusOr {119};120StatusOr<int> doit();121void test() {122 Foo f;123 f.doStuff(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}}124 doit(); // expected-warning {{ignoring return value of type 'StatusOr<int>' declared with 'clang::warn_unused_result'}}125 126 auto func = []() { return Status(); };127 func(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}}128}129}130 131namespace PR17587 {132struct [[clang::warn_unused_result]] Status;133 134struct Foo {135 Status Bar();136};137 138struct Status {};139 140void Bar() {141 Foo f;142 f.Bar(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}}143};144 145}146 147namespace PR18571 {148// Unevaluated contexts should not trigger unused result warnings.149template <typename T>150auto foo(T) -> decltype(f(), bool()) { // Should not warn.151 return true;152}153 154void g() {155 foo(1);156}157}158 159namespace std {160class type_info { };161}162 163namespace {164// The typeid expression operand is evaluated only when the expression type is165// a glvalue of polymorphic class type.166 167struct B {168 virtual void f() {}169};170 171struct D : B {172 void f() override {}173};174 175struct C {};176 177void g() {178 // The typeid expression operand is evaluated only when the expression type is179 // a glvalue of polymorphic class type; otherwise the expression operand is not180 // 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 194namespace {195// C++ Methods should warn even in their own class.196struct [[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 205struct [[clang::warn_unused_result]] P {206 P DoThing() { return {}; };207};208 209P operator++(const P &, int) { return {}; };210P operator--(const P &, int) { return {}; };211// Improperly written prefix.212P operator++(const P &) { return {}; };213P operator--(const P &) { return {}; };214 215void f() {216 S s;217 P p;218 s.DoThing(); // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}}219 p.DoThing(); // expected-warning {{ignoring return value of type 'P' declared with 'clang::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 'clang::warn_unused_result'}}222 s--; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}}223 p++; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}}224 p--; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}}225 // Improperly written prefix operators should still warn.226 ++s; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}}227 --s; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}}228 ++p; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}}229 --p; // expected-warning {{ignoring return value of type 'P' declared with 'clang::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} // namespace239 240namespace PR39837 {241[[clang::warn_unused_result]] int f(int);242 243void g() {244 int a[2];245 for (int b : a)246 f(b); // expected-warning {{ignoring return value of function declared with 'clang::warn_unused_result'}}247}248} // namespace PR39837249 250namespace 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 255void i([[nodiscard]] bool (*fp)()); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}}256}257 258namespace unused_typedef_result {259[[clang::warn_unused_result]] typedef void *a;260typedef a indirect;261a af1();262indirect indirectf1();263void af2() {264 af1(); // expected-warning {{ignoring return value of type 'a' declared with 'clang::warn_unused_result'}}265 void *(*a1)();266 a1(); // no warning267 a (*a2)();268 a2(); // expected-warning {{ignoring return value of type 'a' declared with 'clang::warn_unused_result'}}269 indirectf1(); // expected-warning {{ignoring return value of type 'a' declared with 'clang::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}}273b1 b1f1();274b2 b2f1();275void bf2() {276 b1f1(); // no warning277 b2f1(); // no warning278}279__attribute__((warn_unused_result)) typedef void *c;280c cf1();281void 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 290namespace nodiscard_specialization {291// Test to only mark a specialization of class template as nodiscard292template<typename T> struct S { S(int) {} };293template<> struct [[nodiscard]] S<int> { S(int) {} };294template<typename T> struct [[clang::warn_unused_result]] S<const T> { S(int) {} };295 296template<typename T>297S<T> obtain(const T&) { return {2}; }298 299template<typename T>300[[nodiscard]] S<T> obtain2(const T&) { return {2}; }301 302template<typename T>303__attribute__((warn_unused_result)) S<T> obtain3(const T&) { return {2}; }304 305void use() {306 obtain(1.0); // no warning307 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 'clang::warn_unused_result'}}309 310 S<double>(2); // no warning311 S<int>(2); // expected-warning {{ignoring temporary of type 'S<int>' declared with 'nodiscard'}}312 S<const char>(2); // expected-warning {{ignoring temporary of type 'S<const char>' declared with 'clang::warn_unused_result' attribute}}313 314 // function should take precedence over type315 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 nodiscard324struct H {325 explicit H(int) {}326 [[nodiscard]] explicit H(double) {}327 __attribute__((warn_unused_result)) H(const char*) {}328};329 330struct [[nodiscard]] G {331 explicit G(int) {}332 [[nodiscard]] explicit G(double) {}333 [[clang::warn_unused_result]] G(const char*) {}334};335 336void use2() {337 H{2}; // no warning338 H(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}}339 H("Hello"); // expected-warning {{ignoring temporary created by a constructor declared with 'warn_unused_result' attribute}}340 341 // no warning for explicit cast to void342 (void)H(2);343 (void)H{2.0};344 (void)H{"Hello"};345 346 // warns for all these invocations347 // here, constructor/function should take precedence over type348 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 'clang::warn_unused_result'}}351 352 // no warning for explicit cast to void353 (void)G(2);354 (void)G{2.0};355 (void)G{"Hello"};356}357} // namespace nodiscard_specialization358 359namespace GH117975 {360// Test for a regression for ICE in CallExpr::getUnusedResultAttr361int f() { return 0; }362void id_print_name() {363 (int) // expected-warning {{expression result unused}}364 ((int(*)())f)();365}366} // namespace GH117975367 368namespace inheritance {369// Test that [[nodiscard]] is not inherited by derived class types,370// but is inherited by member functions371struct [[nodiscard]] E {372 [[nodiscard]] explicit E(int);373 explicit E(const char*);374 [[nodiscard]] int f();375};376struct F : E {377 using E::E;378};379E e();380F f();381void test() {382 e(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}}383 f(); // no warning: derived class type does not inherit the attribute384 E(1); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}385 E("x"); // expected-warning {{ignoring temporary of type 'E' declared with 'nodiscard' attribute}}386 F(1); // no warning: inherited constructor does not inherit the attribute either387 F("x"); // no warning388 e().f(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}389 f().f(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}390}391} // namespace inheritance392 393namespace BuildStringOnClangScope {394 395[[clang::warn_unused_result("Discarded result")]]396bool makeClangTrue() { return true; }397 398[[gnu::warn_unused_result("Discarded result")]]399bool makeGccTrue() { return true; }400 401void doClangThings() {402 makeClangTrue(); // expected-warning {{ignoring return value of function declared with 'clang::warn_unused_result' attribute: Discarded result}}403}404 405void doGccThings() {406 makeGccTrue(); // expected-warning {{ignoring return value of function declared with 'gnu::warn_unused_result' attribute}}407}408 409} // namespace BuildStringOnClangScope410 411namespace candiscard {412 413struct [[nodiscard]] NoDiscard {414 [[nodiscard]] NoDiscard(int);415 NoDiscard(const char *);416};417 418struct [[gnu::warn_unused]] WarnUnused {419 [[gnu::warn_unused]] WarnUnused(int); // expected-warning {{'gnu::warn_unused' attribute only applies to structs, unions, and classes}}420 WarnUnused(const char*);421};422 423struct [[gnu::warn_unused_result]] WarnUnusedResult {424 [[gnu::warn_unused_result]] WarnUnusedResult(int);425 WarnUnusedResult(const char*);426};427 428NoDiscard return_nodiscard();429WarnUnused return_warnunused();430WarnUnusedResult return_warnunusedresult();431 432NoDiscard (*p_return_nodiscard)();433WarnUnused (*p_return_warnunused)();434WarnUnusedResult (*p_return_warnunusedresult)();435 436NoDiscard (*(*pp_return_nodiscard)())();437WarnUnused (*(*pp_return_warnunused)())();438WarnUnusedResult (*(*pp_return_warnunusedresult)())();439 440template <class T> T from_a_template();441 442void test() {443 // Unused but named variables444 NoDiscard unused_variable1(1); // no warning445 NoDiscard unused_variable2(""); // no warning446 WarnUnused unused_variable3(1); // no warning447 WarnUnused unused_variable4(""); // no warning448 WarnUnusedResult unused_variable5(1); // no warning449 WarnUnusedResult unused_variable6(""); // no warning450 451 // Constructor return values452 NoDiscard(1); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}453 NoDiscard(""); // expected-warning {{ignoring temporary of type 'NoDiscard' declared with 'nodiscard' attribute}}454 WarnUnused(1); // expected-warning {{expression result unused}}455 WarnUnused(""); // expected-warning {{expression result unused}}456 WarnUnusedResult(1); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}}457 WarnUnusedResult(""); // expected-warning {{ignoring temporary of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}458 459 NoDiscard{1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}460 NoDiscard{""}; // expected-warning {{ignoring temporary of type 'NoDiscard' declared with 'nodiscard' attribute}}461 WarnUnused{1}; // expected-warning {{expression result unused}}462 WarnUnused{""}; // expected-warning {{expression result unused}}463 WarnUnusedResult{1}; // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}}464 WarnUnusedResult{""}; // expected-warning {{ignoring temporary of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}465 466 static_cast<NoDiscard>(1); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}467 static_cast<NoDiscard>(""); // expected-warning {{ignoring temporary of type 'NoDiscard' declared with 'nodiscard' attribute}}468 static_cast<WarnUnused>(1); // expected-warning {{expression result unused}}469 static_cast<WarnUnused>(""); // expected-warning {{expression result unused}}470 static_cast<WarnUnusedResult>(1); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}}471 static_cast<WarnUnusedResult>(""); // expected-warning {{ignoring temporary of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}472 473 // Function return values474 return_nodiscard(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}}475 return_warnunused(); // no warning476 return_warnunusedresult(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}477 478 // Function pointer return values479 p_return_nodiscard(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}}480 p_return_warnunused(); // no warning481 p_return_warnunusedresult(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}482 483 // Function pointer expression return values484 pp_return_nodiscard()(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}}485 pp_return_warnunused()(); // no warning486 pp_return_warnunusedresult()(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}487 488 // From a template489 from_a_template<NoDiscard>(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}}490 from_a_template<WarnUnused>(); // no warning491 from_a_template<WarnUnusedResult>(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}}492}493 494} // namespace candiscard495