1// RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify %s
2// RUN: %clang_cc1 -Wparentheses -fixit %s -o - | %clang_cc1 -Wparentheses -Werror -
3
4bool someConditionFunc();
5
6void conditional_op(int x, int y, bool b) {
7  (void)(x + someConditionFunc() ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '+'}} \
8                                           // expected-note {{place parentheses around the '?:' expression to evaluate it first}} \
9                                           // expected-note {{place parentheses around the '+' expression to silence this warning}}
10
11  (void)(x - b ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '-'}} \
12                         // expected-note {{place parentheses around the '?:' expression to evaluate it first}} \
13                         // expected-note {{place parentheses around the '-' expression to silence this warning}}
14
15  (void)(x * (x == y) ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '*'}} \
16                                // expected-note {{place parentheses around the '?:' expression to evaluate it first}} \
17                                // expected-note {{place parentheses around the '*' expression to silence this warning}}
18}
19
20class Stream {
21public:
22  operator int();
23  Stream &operator<<(int);
24  Stream &operator<<(const char*);
25  Stream &operator>>(int);
26  Stream &operator>>(const char*);
27};
28
29void f(Stream& s, bool b) {
30  (void)(s << b ? "foo" : "bar"); // expected-warning {{operator '?:' has lower precedence than '<<'}} \
31                                  // expected-note {{place parentheses around the '?:' expression to evaluate it first}} \
32                                  // expected-note {{place parentheses around the '<<' expression to silence this warning}}
33}
34
35struct S {
36  operator int() { return 42; }
37  friend S operator+(const S &lhs, bool) { return S(); }
38};
39
40void test(S *s, bool (S::*m_ptr)()) {
41  (void)(*s + true ? "foo" : "bar"); // expected-warning {{operator '?:' has lower precedence than '+'}} \
42                                     // expected-note {{place parentheses around the '?:' expression to evaluate it first}} \
43                                     // expected-note {{place parentheses around the '+' expression to silence this warning}}
44
45  (void)((*s + true) ? "foo" : "bar"); // No warning.
46
47  // Don't crash on unusual member call expressions.
48  (void)((s->*m_ptr)() ? "foo" : "bar");
49}
50
51void test(int a, int b, int c) {
52  (void)(a >> b + c); // expected-warning {{operator '>>' has lower precedence than '+'; '+' will be evaluated first}} \
53                         expected-note {{place parentheses around the '+' expression to silence this warning}}
54  (void)(a - b << c); // expected-warning {{operator '<<' has lower precedence than '-'; '-' will be evaluated first}} \
55                         expected-note {{place parentheses around the '-' expression to silence this warning}}
56  Stream() << b + c;
57  Stream() >> b + c; // expected-warning {{operator '>>' has lower precedence than '+'; '+' will be evaluated first}} \
58                        expected-note {{place parentheses around the '+' expression to silence this warning}}
59}
60