1 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++98 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++11 %s
4 
5 // PR4806
6 namespace test0 {
7   class Box {
8   public:
9     int i;
10     volatile int j;
11   };
12 
doit()13   void doit() {
14     // pointer to volatile has side effect (thus no warning)
15     Box* box = new Box;
16     box->i; // expected-warning {{expression result unused}}
17     box->j;
18 #if __cplusplus <= 199711L
19     // expected-warning@-2 {{expression result unused}}
20 #endif
21   }
22 }
23 
24 namespace test1 {
25 struct Foo {
26   int i;
operator ==test1::Foo27   bool operator==(const Foo& rhs) {
28     return i == rhs.i;
29   }
30 };
31 
32 #define NOP(x) (x)
b(Foo f1,Foo f2)33 void b(Foo f1, Foo f2) {
34   NOP(f1 == f2);  // expected-warning {{expression result unused}}
35 }
36 #undef NOP
37 }
38 
39 namespace test2 {
40   extern "C++" {
41     namespace std {
42       template<typename T> struct basic_string {
43         struct X {};
methodtest2::std::basic_string44         void method() const {
45          X* x;
46          &x[0];  // expected-warning {{expression result unused}}
47         }
48       };
49       typedef basic_string<char> string;
func(const std::string & str)50       void func(const std::string& str) {
51         str.method();  // expected-note {{in instantiation of member function}}
52       }
53     }
54   }
55 }
56 
57 namespace test3 {
58 struct Used {
59   Used();
60   Used(int);
61   Used(int, int);
~Usedtest3::Used62   ~Used() {}
63 };
64 struct __attribute__((warn_unused)) Unused {
65   Unused();
66   Unused(int);
67   Unused(int, int);
~Unusedtest3::Unused68   ~Unused() {}
69 };
f()70 void f() {
71   Used();
72   Used(1);
73   Used(1, 1);
74   Unused();     // expected-warning {{expression result unused}}
75   Unused(1);    // expected-warning {{expression result unused}}
76   Unused(1, 1); // expected-warning {{expression result unused}}
77 #if __cplusplus >= 201103L // C++11 or later
78   Used({});
79   Unused({}); // expected-warning {{expression result unused}}
80 #endif
81 }
82 }
83 
84 namespace std {
85   struct type_info {};
86 }
87 
88 namespace test4 {
89 struct Good { Good &f(); };
90 struct Bad { virtual Bad& f(); };
91 
f()92 void f() {
93   int i = 0;
94   (void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
95 
96   Good g;
97   (void)typeid(g.f()); // Ok; not a polymorphic use of a glvalue.
98 
99   // This is a polymorphic use of a glvalue, which results in the typeid being
100   // evaluated instead of unevaluated.
101   Bad b;
102   (void)typeid(b.f()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
103 
104   // A dereference of a volatile pointer is a side effecting operation, however
105   // since it is idiomatic code, and the alternatives induce higher maintenance
106   // costs, it is allowed.
107   int * volatile x;
108   (void)sizeof(*x); // Ok
109 }
110 }
111 
112 static volatile char var1 = 'a';
113 volatile char var2 = 'a';
114 static volatile char arr1[] = "hello";
115 volatile char arr2[] = "hello";
volatile_array()116 void volatile_array() {
117   static volatile char var3 = 'a';
118   volatile char var4 = 'a';
119   static volatile char arr3[] = "hello";
120   volatile char arr4[] = "hello";
121 
122   // These all result in volatile loads in C and C++11. In C++98, they don't,
123   // but we suppress the warning in the case where '(void)var;' might be
124   // idiomatically suppressing an 'unused variable' warning.
125   (void)var1;
126   (void)var2;
127 #if __cplusplus < 201103L
128   // expected-warning@-2 {{expression result unused; assign into a variable to force a volatile load}}
129 #endif
130   (void)var3;
131   (void)var4;
132 
133   // None of these result in volatile loads in any language mode, and it's not
134   // really reasonable to assume that they would, since volatile array loads
135   // don't really exist anywhere.
136   (void)arr1;
137   (void)arr2;
138   (void)arr3;
139   (void)arr4;
140 }
141