Clang Project

clang_source_code/test/SemaCXX/warn-self-assign-field-builtin.cpp
1// RUN: %clang_cc1 -fsyntax-only -Wself-assign-field -verify %s
2
3struct C {
4  int a;
5  int b;
6
7  void f() {
8    a = a; // expected-warning {{assigning field to itself}}
9    b = b; // expected-warning {{assigning field to itself}}
10    a = b;
11
12    this->a = a;       // expected-warning {{assigning field to itself}}
13    this->b = b;       // expected-warning {{assigning field to itself}}
14    a = this->a;       // expected-warning {{assigning field to itself}}
15    b = this->b;       // expected-warning {{assigning field to itself}}
16    this->a = this->a; // expected-warning {{assigning field to itself}}
17    this->b = this->b; // expected-warning {{assigning field to itself}}
18
19    a = b;
20    a = this->b;
21    this->a = b;
22    this->a = this->b;
23
24    a *= a;
25    a /= a;
26    a %= a;
27    a += a;
28    a -= a;
29    a <<= a;
30    a >>= a;
31    a &= a;
32    a |= a;
33    a ^= a;
34  }
35
36  void false_positives() {
37#define OP =
38#define LHS a
39#define RHS a
40    // These shouldn't warn due to the use of the preprocessor.
41    a OP a;
42    LHS = a;
43    a = RHS;
44    LHS OP RHS;
45#undef OP
46#undef LHS
47#undef RHS
48
49    // A way to silence the warning.
50    a = (int &)a;
51  }
52
53  // Do not diagnose self-assigment in an unevaluated context
54  void false_positives_unevaluated_ctx() noexcept(noexcept(a = a)) // expected-warning {{expression with side effects has no effect in an unevaluated context}}
55  {
56    decltype(a = a) b = a;              // expected-warning {{expression with side effects has no effect in an unevaluated context}}
57    static_assert(noexcept(a = a), ""); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
58    static_assert(sizeof(a = a), "");   // expected-warning {{expression with side effects has no effect in an unevaluated context}}
59  }
60
61  volatile int vol_a;
62  void vol_test() {
63    // Volatile stores aren't side-effect free.
64    vol_a = vol_a;
65    volatile int &vol_a_ref = vol_a;
66    vol_a_ref = vol_a_ref;
67  }
68};
69
70// Dummy type.
71struct Dummy {};
72
73template <typename T>
74struct TemplateClass {
75  T var;
76  void f() {
77    var = var; // expected-warning {{assigning field to itself}}
78  }
79};
80void instantiate() {
81  {
82    TemplateClass<int> c;
83    c.f();
84  }
85  {
86    TemplateClass<Dummy> c;
87    c.f();
88  }
89}
90
91// It may make sense not to warn on the rest of the tests.
92// It may be a valid use-case to self-assign to tell the compiler that
93// it is ok to vectorize the store.
94
95void f0(C *s, C *t) {
96  s->a = s->a;
97  t->a = s->a;
98}
99
100void f1(C &s, C &t) {
101  s.a = s.a;
102  t.a = s.a;
103}
104
105struct T {
106  C *s;
107};
108
109void f2(T *t, T *t2) {
110  t->s->a = t->s->a;
111  t2->s->a = t->s->a;
112}
113
114void f3(T &t, T &t2) {
115  t.s->a = t.s->a;
116  t2.s->a = t.s->a;
117}
118