1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2
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
36struct X {
37 int foo() __attribute__((warn_unused_result));
38};
39
40void bah() {
41  X x, *x2;
42  x.foo(); // expected-warning {{ignoring return value}}
43  x2->foo(); // expected-warning {{ignoring return value}}
44}
45
46namespace warn_unused_CXX11 {
47class Status;
48class Foo {
49 public:
50  Status doStuff();
51};
52
53struct [[clang::warn_unused_result]] Status {
54  bool ok() const;
55  Status& operator=(const Status& x);
56  inline void Update(const Status& new_status) {
57    if (ok()) {
58      *this = new_status; //no-warning
59    }
60  }
61};
62Status DoSomething();
63Status& DoSomethingElse();
64Status* DoAnotherThing();
65Status** DoYetAnotherThing();
66void lazy() {
67  Status s = DoSomething();
68  if (!s.ok()) return;
69  Status &rs = DoSomethingElse();
70  if (!rs.ok()) return;
71  Status *ps = DoAnotherThing();
72  if (!ps->ok()) return;
73  Status **pps = DoYetAnotherThing();
74  if (!(*pps)->ok()) return;
75
76  (void)DoSomething();
77  (void)DoSomethingElse();
78  (void)DoAnotherThing();
79  (void)DoYetAnotherThing();
80
81  DoSomething(); // expected-warning {{ignoring return value}}
82  DoSomethingElse();
83  DoAnotherThing();
84  DoYetAnotherThing();
85}
86
87template <typename T>
88class [[clang::warn_unused_result]] StatusOr {
89};
90StatusOr<int> doit();
91void test() {
92  Foo f;
93  f.doStuff(); // expected-warning {{ignoring return value}}
94  doit(); // expected-warning {{ignoring return value}}
95
96  auto func = []() { return Status(); };
97  func(); // expected-warning {{ignoring return value}}
98}
99}
100
101namespace PR17587 {
102struct [[clang::warn_unused_result]] Status;
103
104struct Foo {
105  Status Bar();
106};
107
108struct Status {};
109
110void Bar() {
111  Foo f;
112  f.Bar(); // expected-warning {{ignoring return value}}
113};
114
115}
116
117namespace PR18571 {
118// Unevaluated contexts should not trigger unused result warnings.
119template <typename T>
120auto foo(T) -> decltype(f(), bool()) { // Should not warn.
121  return true;
122}
123
124void g() {
125  foo(1);
126}
127}
128
129namespace std {
130class type_info { };
131}
132
133namespace {
134// The typeid expression operand is evaluated only when the expression type is
135// a glvalue of polymorphic class type.
136
137struct B {
138  virtual void f() {}
139};
140
141struct D : B {
142  void f() override {}
143};
144
145struct C {};
146
147void g() {
148  // The typeid expression operand is evaluated only when the expression type is
149  // a glvalue of polymorphic class type; otherwise the expression operand is not
150  // evaluated and should not trigger a diagnostic.
151  D d;
152  C c;
153  (void)typeid(f(), c); // Should not warn.
154  (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'}}
155
156  // The sizeof expression operand is never evaluated.
157  (void)sizeof(f(), c); // Should not warn.
158
159   // The noexcept expression operand is never evaluated.
160  (void)noexcept(f(), false); // Should not warn.
161}
162}
163