// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s int f() __attribute__((warn_unused_result)); struct S { void t() const; }; S g1() __attribute__((warn_unused_result)); S *g2() __attribute__((warn_unused_result)); S &g3() __attribute__((warn_unused_result)); void test() { f(); // expected-warning {{ignoring return value}} g1(); // expected-warning {{ignoring return value}} g2(); // expected-warning {{ignoring return value}} g3(); // expected-warning {{ignoring return value}} (void)f(); (void)g1(); (void)g2(); (void)g3(); if (f() == 0) return; g1().t(); g2()->t(); g3().t(); int i = f(); S s1 = g1(); S *s2 = g2(); S &s3 = g3(); const S &s4 = g1(); } void testSubstmts(int i) { switch (i) { case 0: f(); // expected-warning {{ignoring return value}} default: f(); // expected-warning {{ignoring return value}} } if (i) f(); // expected-warning {{ignoring return value}} else f(); // expected-warning {{ignoring return value}} while (i) f(); // expected-warning {{ignoring return value}} do f(); // expected-warning {{ignoring return value}} while (i); for (f(); // expected-warning {{ignoring return value}} ; f() // expected-warning {{ignoring return value}} ) f(); // expected-warning {{ignoring return value}} f(), // expected-warning {{ignoring return value}} (void)f(); } struct X { int foo() __attribute__((warn_unused_result)); }; void bah() { X x, *x2; x.foo(); // expected-warning {{ignoring return value}} x2->foo(); // expected-warning {{ignoring return value}} } namespace warn_unused_CXX11 { class Status; class Foo { public: Status doStuff(); }; struct [[clang::warn_unused_result]] Status { bool ok() const; Status& operator=(const Status& x); inline void Update(const Status& new_status) { if (ok()) { *this = new_status; //no-warning } } }; Status DoSomething(); Status& DoSomethingElse(); Status* DoAnotherThing(); Status** DoYetAnotherThing(); void lazy() { Status s = DoSomething(); if (!s.ok()) return; Status &rs = DoSomethingElse(); if (!rs.ok()) return; Status *ps = DoAnotherThing(); if (!ps->ok()) return; Status **pps = DoYetAnotherThing(); if (!(*pps)->ok()) return; (void)DoSomething(); (void)DoSomethingElse(); (void)DoAnotherThing(); (void)DoYetAnotherThing(); DoSomething(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}} DoSomethingElse(); DoAnotherThing(); DoYetAnotherThing(); } template class [[clang::warn_unused_result]] StatusOr { }; StatusOr doit(); void test() { Foo f; f.doStuff(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}} doit(); // expected-warning {{ignoring return value of type 'StatusOr' declared with 'clang::warn_unused_result'}} auto func = []() { return Status(); }; func(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}} } } namespace PR17587 { struct [[clang::warn_unused_result]] Status; struct Foo { Status Bar(); }; struct Status {}; void Bar() { Foo f; f.Bar(); // expected-warning {{ignoring return value of type 'Status' declared with 'clang::warn_unused_result'}} }; } namespace PR18571 { // Unevaluated contexts should not trigger unused result warnings. template auto foo(T) -> decltype(f(), bool()) { // Should not warn. return true; } void g() { foo(1); } } namespace std { class type_info { }; } namespace { // The typeid expression operand is evaluated only when the expression type is // a glvalue of polymorphic class type. struct B { virtual void f() {} }; struct D : B { void f() override {} }; struct C {}; void g() { // The typeid expression operand is evaluated only when the expression type is // a glvalue of polymorphic class type; otherwise the expression operand is not // evaluated and should not trigger a diagnostic. D d; C c; (void)typeid(f(), c); // Should not warn. (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'}} // The sizeof expression operand is never evaluated. (void)sizeof(f(), c); // Should not warn. // The noexcept expression operand is never evaluated. (void)noexcept(f(), false); // Should not warn. } } namespace { // C++ Methods should warn even in their own class. struct [[clang::warn_unused_result]] S { S DoThing() { return {}; }; S operator++(int) { return {}; }; S operator--(int) { return {}; }; // Improperly written prefix. S operator++() { return {}; }; S operator--() { return {}; }; }; struct [[clang::warn_unused_result]] P { P DoThing() { return {}; }; }; P operator++(const P &, int) { return {}; }; P operator--(const P &, int) { return {}; }; // Improperly written prefix. P operator++(const P &) { return {}; }; P operator--(const P &) { return {}; }; void f() { S s; P p; s.DoThing(); // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}} p.DoThing(); // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}} // Only postfix is expected to warn when written correctly. s++; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}} s--; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}} p++; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}} p--; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}} // Improperly written prefix operators should still warn. ++s; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}} --s; // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}} ++p; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}} --p; // expected-warning {{ignoring return value of type 'P' declared with 'clang::warn_unused_result'}} // Silencing the warning by cast to void still works. (void)s.DoThing(); (void)s++; (void)p++; (void)++s; (void)++p; } } // namespace namespace PR39837 { [[clang::warn_unused_result]] int f(int); void g() { int a[2]; for (int b : a) f(b); // expected-warning {{ignoring return value of function declared with 'clang::warn_unused_result'}} } } // namespace PR39837 namespace PR45520 { [[nodiscard]] bool (*f)(); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}} [[clang::warn_unused_result]] bool (*g)(); __attribute__((warn_unused_result)) bool (*h)(); void i([[nodiscard]] bool (*fp)()); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}} } namespace unused_typedef_result { [[clang::warn_unused_result]] typedef void *a; typedef a indirect; a af1(); indirect indirectf1(); void af2() { af1(); // expected-warning {{ignoring return value of type 'a' declared with 'clang::warn_unused_result'}} void *(*a1)(); a1(); // no warning a (*a2)(); a2(); // expected-warning {{ignoring return value of type 'a' declared with 'clang::warn_unused_result'}} indirectf1(); // expected-warning {{ignoring return value of type 'a' declared with 'clang::warn_unused_result'}} } [[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}} [[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}} b1 b1f1(); b2 b2f1(); void bf2() { b1f1(); // no warning b2f1(); // no warning } __attribute__((warn_unused_result)) typedef void *c; c cf1(); void cf2() { cf1(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}} void *(*c1)(); c1(); c (*c2)(); c2(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}} } } namespace nodiscard_specialization { // Test to only mark a specialization of class template as nodiscard template struct S { S(int) {} }; template<> struct [[nodiscard]] S { S(int) {} }; template struct [[clang::warn_unused_result]] S { S(int) {} }; template S obtain(const T&) { return {2}; } template [[nodiscard]] S obtain2(const T&) { return {2}; } template __attribute__((warn_unused_result)) S obtain3(const T&) { return {2}; } void use() { obtain(1.0); // no warning obtain(1); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard'}} obtain(1); // expected-warning {{ignoring return value of type 'S' declared with 'clang::warn_unused_result'}} S(2); // no warning S(2); // expected-warning {{ignoring temporary of type 'S' declared with 'nodiscard'}} S(2); // expected-warning {{ignoring temporary of type 'S' declared with 'clang::warn_unused_result' attribute}} // function should take precedence over type obtain2(1.0); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} obtain2(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} obtain2(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} obtain3(1.0); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} obtain3(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} obtain3(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} } // Test on constructor nodiscard struct H { explicit H(int) {} [[nodiscard]] explicit H(double) {} __attribute__((warn_unused_result)) H(const char*) {} }; struct [[nodiscard]] G { explicit G(int) {} [[nodiscard]] explicit G(double) {} [[clang::warn_unused_result]] G(const char*) {} }; void use2() { H{2}; // no warning H(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}} H("Hello"); // expected-warning {{ignoring temporary created by a constructor declared with 'warn_unused_result' attribute}} // no warning for explicit cast to void (void)H(2); (void)H{2.0}; (void)H{"Hello"}; // warns for all these invocations // here, constructor/function should take precedence over type G{2}; // expected-warning {{ignoring temporary of type 'G' declared with 'nodiscard'}} G(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}} G("Hello"); // expected-warning {{ignoring temporary created by a constructor declared with 'clang::warn_unused_result'}} // no warning for explicit cast to void (void)G(2); (void)G{2.0}; (void)G{"Hello"}; } } // namespace nodiscard_specialization namespace GH117975 { // Test for a regression for ICE in CallExpr::getUnusedResultAttr int f() { return 0; } void id_print_name() { (int) // expected-warning {{expression result unused}} ((int(*)())f)(); } } // namespace GH117975 namespace inheritance { // Test that [[nodiscard]] is not inherited by derived class types, // but is inherited by member functions struct [[nodiscard]] E { [[nodiscard]] explicit E(int); explicit E(const char*); [[nodiscard]] int f(); }; struct F : E { using E::E; }; E e(); F f(); void test() { e(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}} f(); // no warning: derived class type does not inherit the attribute E(1); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} E("x"); // expected-warning {{ignoring temporary of type 'E' declared with 'nodiscard' attribute}} F(1); // no warning: inherited constructor does not inherit the attribute either F("x"); // no warning e().f(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} f().f(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} } } // namespace inheritance namespace BuildStringOnClangScope { [[clang::warn_unused_result("Discarded result")]] bool makeClangTrue() { return true; } [[gnu::warn_unused_result("Discarded result")]] bool makeGccTrue() { return true; } void doClangThings() { makeClangTrue(); // expected-warning {{ignoring return value of function declared with 'clang::warn_unused_result' attribute: Discarded result}} } void doGccThings() { makeGccTrue(); // expected-warning {{ignoring return value of function declared with 'gnu::warn_unused_result' attribute}} } } // namespace BuildStringOnClangScope namespace candiscard { struct [[nodiscard]] NoDiscard { [[nodiscard]] NoDiscard(int); NoDiscard(const char *); }; struct [[gnu::warn_unused]] WarnUnused { [[gnu::warn_unused]] WarnUnused(int); // expected-warning {{'gnu::warn_unused' attribute only applies to structs, unions, and classes}} WarnUnused(const char*); }; struct [[gnu::warn_unused_result]] WarnUnusedResult { [[gnu::warn_unused_result]] WarnUnusedResult(int); WarnUnusedResult(const char*); }; NoDiscard return_nodiscard(); WarnUnused return_warnunused(); WarnUnusedResult return_warnunusedresult(); NoDiscard (*p_return_nodiscard)(); WarnUnused (*p_return_warnunused)(); WarnUnusedResult (*p_return_warnunusedresult)(); NoDiscard (*(*pp_return_nodiscard)())(); WarnUnused (*(*pp_return_warnunused)())(); WarnUnusedResult (*(*pp_return_warnunusedresult)())(); template T from_a_template(); void test() { // Unused but named variables NoDiscard unused_variable1(1); // no warning NoDiscard unused_variable2(""); // no warning WarnUnused unused_variable3(1); // no warning WarnUnused unused_variable4(""); // no warning WarnUnusedResult unused_variable5(1); // no warning WarnUnusedResult unused_variable6(""); // no warning // Constructor return values NoDiscard(1); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} NoDiscard(""); // expected-warning {{ignoring temporary of type 'NoDiscard' declared with 'nodiscard' attribute}} WarnUnused(1); // expected-warning {{expression result unused}} WarnUnused(""); // expected-warning {{expression result unused}} WarnUnusedResult(1); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}} WarnUnusedResult(""); // expected-warning {{ignoring temporary of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} NoDiscard{1}; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} NoDiscard{""}; // expected-warning {{ignoring temporary of type 'NoDiscard' declared with 'nodiscard' attribute}} WarnUnused{1}; // expected-warning {{expression result unused}} WarnUnused{""}; // expected-warning {{expression result unused}} WarnUnusedResult{1}; // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}} WarnUnusedResult{""}; // expected-warning {{ignoring temporary of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} static_cast(1); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}} static_cast(""); // expected-warning {{ignoring temporary of type 'NoDiscard' declared with 'nodiscard' attribute}} static_cast(1); // expected-warning {{expression result unused}} static_cast(""); // expected-warning {{expression result unused}} static_cast(1); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}} static_cast(""); // expected-warning {{ignoring temporary of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} // Function return values return_nodiscard(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}} return_warnunused(); // no warning return_warnunusedresult(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} // Function pointer return values p_return_nodiscard(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}} p_return_warnunused(); // no warning p_return_warnunusedresult(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} // Function pointer expression return values pp_return_nodiscard()(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}} pp_return_warnunused()(); // no warning pp_return_warnunusedresult()(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} // From a template from_a_template(); // expected-warning {{ignoring return value of type 'NoDiscard' declared with 'nodiscard' attribute}} from_a_template(); // no warning from_a_template(); // expected-warning {{ignoring return value of type 'WarnUnusedResult' declared with 'gnu::warn_unused_result' attribute}} } } // namespace candiscard