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 
test()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 
testSubstmts(int i)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 
bah()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);
Updatewarn_unused_CXX11::Status86   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();
lazy()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}}
112   DoSomethingElse();
113   DoAnotherThing();
114   DoYetAnotherThing();
115 }
116 
117 template <typename T>
118 class [[clang::warn_unused_result]] StatusOr {
119 };
120 StatusOr<int> doit();
test()121 void test() {
122   Foo f;
123   f.doStuff(); // expected-warning {{ignoring return value}}
124   doit(); // expected-warning {{ignoring return value}}
125 
126   auto func = []() { return Status(); };
127   func(); // expected-warning {{ignoring return value}}
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 
Bar()140 void Bar() {
141   Foo f;
142   f.Bar(); // expected-warning {{ignoring return value}}
143 };
144 
145 }
146 
147 namespace PR18571 {
148 // Unevaluated contexts should not trigger unused result warnings.
149 template <typename T>
foo(T)150 auto foo(T) -> decltype(f(), bool()) { // Should not warn.
151   return true;
152 }
153 
g()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 {
f__anon5b6b9b3e0211::B168   virtual void f() {}
169 };
170 
171 struct D : B {
f__anon5b6b9b3e0211::D172   void f() override {}
173 };
174 
175 struct C {};
176 
g()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 {
DoThing__anon5b6b9b3e0311::S197   S DoThing() { return {}; };
operator ++__anon5b6b9b3e0311::S198   S operator++(int) { return {}; };
operator --__anon5b6b9b3e0311::S199   S operator--(int) { return {}; };
200   // Improperly written prefix.
operator ++__anon5b6b9b3e0311::S201   S operator++() { return {}; };
operator --__anon5b6b9b3e0311::S202   S operator--() { return {}; };
203 };
204 
205 struct [[clang::warn_unused_result]] P {
DoThing__anon5b6b9b3e0311::P206   P DoThing() { return {}; };
207 };
208 
operator ++(const P &,int)209 P operator++(const P &, int) { return {}; };
operator --(const P &,int)210 P operator--(const P &, int) { return {}; };
211 // Improperly written prefix.
operator ++(const P &)212 P operator++(const P &) { return {}; };
operator --(const P &)213 P operator--(const P &) { return {}; };
214 
f()215 void f() {
216   S s;
217   P p;
218   s.DoThing(); // expected-warning {{ignoring return value}}
219   p.DoThing(); // expected-warning {{ignoring return value}}
220   // Only postfix is expected to warn when written correctly.
221   s++; // expected-warning {{ignoring return value}}
222   s--; // expected-warning {{ignoring return value}}
223   p++; // expected-warning {{ignoring return value}}
224   p--; // expected-warning {{ignoring return value}}
225   // Improperly written prefix operators should still warn.
226   ++s; // expected-warning {{ignoring return value}}
227   --s; // expected-warning {{ignoring return value}}
228   ++p; // expected-warning {{ignoring return value}}
229   --p; // expected-warning {{ignoring return value}}
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 
g()243 void g() {
244   int a[2];
245   for (int b : a)
246     f(b); // expected-warning {{ignoring return value}}
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