File: warn-unused-value.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (180 lines) | stat: -rw-r--r-- 5,204 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++17 %s

// PR4806
namespace test0 {
  class Box {
  public:
    int i;
    volatile int j;
  };

  void doit() {
    // pointer to volatile has side effect (thus no warning)
    Box* box = new Box;
    box->i; // expected-warning {{expression result unused}}
    box->j;
#if __cplusplus <= 199711L
    // expected-warning@-2 {{expression result unused}}
#endif
  }
}

namespace test1 {
struct Foo {
  int i;
  bool operator==(const Foo& rhs) {
    return i == rhs.i;
  }
};

#define NOP(x) (x)
void b(Foo f1, Foo f2) {
  NOP(f1 == f2);  // expected-warning {{expression result unused}}
}
#undef NOP
}

namespace test2 {
  extern "C++" {
    namespace std {
      template<typename T> struct basic_string {
        struct X {};
        void method() const {
         X* x;
         &x[0];  // expected-warning {{expression result unused}}
        }
      };
      typedef basic_string<char> string;
      void func(const std::string& str) {
        str.method();  // expected-note {{in instantiation of member function}}
      }
    }
  }
}

namespace test3 {
struct Used {
  Used();
  Used(int);
  Used(int, int);
  ~Used() {}
};
struct __attribute__((warn_unused)) Unused {
  Unused();
  Unused(int);
  Unused(int, int);
  ~Unused() {}
};
void f() {
  Used();
  Used(1);
  Used(1, 1);
  Unused();     // expected-warning {{expression result unused}}
  Unused(1);    // expected-warning {{expression result unused}}
  Unused(1, 1); // expected-warning {{expression result unused}}
#if __cplusplus >= 201103L // C++11 or later
  Used({});
  Unused({}); // expected-warning {{expression result unused}}
#endif
}
}

namespace std {
  struct type_info {};
}

namespace test4 {
struct Good { Good &f(); };
struct Bad { virtual Bad& f(); };

void f() {
  int i = 0;
  (void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}

  Good g;
  (void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.

  // This is a polymorphic use of a glvalue, which results in the typeid being
  // evaluated instead of unevaluated.
  Bad b;
  (void)typeid(b.f()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}

  extern Bad * pb;
  // This typeid can throw but that is not a side-effect that we care about
  // warning for since this is idiomatic code
  (void)typeid(*pb);
  (void)sizeof(typeid(*pb));
  (void)typeid(*++pb); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
  (void)sizeof(typeid(*++pb)); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
  // FIXME: we should not warn about this in an unevaluated context
  // expected-warning@-2 {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}

  // A dereference of a volatile pointer is a side effecting operation, however
  // since it is idiomatic code, and the alternatives induce higher maintenance
  // costs, it is allowed.
  int * volatile x;
  (void)sizeof(*x); // Ok
}
}

static volatile char var1 = 'a';
volatile char var2 = 'a';
static volatile char arr1[] = "hello";
volatile char arr2[] = "hello";
void volatile_array() {
  static volatile char var3 = 'a';
  volatile char var4 = 'a';
  static volatile char arr3[] = "hello";
  volatile char arr4[] = "hello";

  // These all result in volatile loads in C and C++11. In C++98, they don't,
  // but we suppress the warning in the case where '(void)var;' might be
  // idiomatically suppressing an 'unused variable' warning.
  (void)var1;
  (void)var2;
#if __cplusplus < 201103L
  // expected-warning@-2 {{expression result unused; assign into a variable to force a volatile load}}
#endif
  (void)var3;
  (void)var4;

  // None of these result in volatile loads in any language mode, and it's not
  // really reasonable to assume that they would, since volatile array loads
  // don't really exist anywhere.
  (void)arr1;
  (void)arr2;
  (void)arr3;
  (void)arr4;
}

#if __cplusplus >= 201103L // C++11 or later
namespace test5 {
int v[(5, 6)]; // expected-warning {{left operand of comma operator has no effect}}
void foo() {
  new double[false ? (1, 2) : 3]
            // FIXME: We shouldn't diagnose the unreachable constant expression
            // here.
            [false ? (1, 2) : 3]; // expected-warning {{left operand of comma operator has no effect}}
}
} // namespace test5

// comma operator diagnostics should be suppressed in a SFINAE context.
template <typename T, int = (T{},0)> int c(int) { return 0; }
template <typename T, int> int c(double) { return 1; }
int foo() { return c<int>(0); }

#endif

#if __cplusplus >= 201703L // C++17 or later
namespace test6 {
auto b() {
  if constexpr (false)
    return (1,0);
  else
    return (1.0,0.0); // expected-warning {{left operand of comma operator has no effect}}
}
} // namespace test6
#endif