[PATCH] D146897: [clang:diagnostics] Turning off warn_self_assignment_overloaded for user-defined compound assignments

Aaron Ballman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 6 08:45:47 PDT 2023


aaron.ballman added inline comments.


================
Comment at: clang/lib/Sema/SemaExpr.cpp:14134
         return;
-
+    
     Sema.Diag(Loc, diag::warn_identity_field_assign) << 0;
----------------
Spurious whitespace change.


================
Comment at: clang/test/SemaCXX/warn-self-assign-field-overloaded.cpp:71-91
+    this->a *= a;
+    this->a /= a; // expected-warning {{assigning field to itself}}
+    this->a %= a; // expected-warning {{assigning field to itself}}
+    this->a += a;
+    this->a -= a; // expected-warning {{assigning field to itself}}
+    this->a <<= a;
+    this->a >>= a;
----------------
The behavior of this diagnostic is almost inscrutable without really sitting down to think about it... and I'm not even certain I get the logic for it despite thinking about it heavily for a while now. I think my confusion boils down to this diagnostic trying to diagnose two different kinds of problems.

Situation 1 is where there's a possible typo and the user meant a different object:
```
a /= a;
this->a /= this->a;

// Less-contrived example
a00 /= a01;
a01 /= a02;
a02 /= a02; // Oops, typo!
```
(Note, I think `this->a` and `a` should be handled the same in this case because there are coding styles out there that mandate adding `this->` to any member lookup, so there's no reason to think that `this->a /= this->a;` is any less of a typo than `a /= a;`.)

Situation 2 is where the user is trying to work around the user-unfriendly lookup rules of C++, or there is a typo, but got confused because lookup found the same object on both sides:
```
this->a /= a;
a /= this->a;

// Less-contrived example
int a;
struct S {
  int a;

  void foo() {
    // Divide the member variable by the global variable
    this->a /= a; // Oops, that's not how this works in practice
  }

  void bar(int ab) {
    // Divide the member variable by the parameter
    this->a /= a; // Oops, typo, meant to use 'ab' instead
  }
};
```

So I'm surprised that we'd want to silence the warnings on `a /= a;` as we're doing here. Frankly, I think we should be silent on `a *= a;` because that's an extremely common way to square a variable, but diagnose almost all the other cases with a "did you mean?" diagnostic. `a -= a;` and `a %= a;` are bad ways to write `a = 0`, `a += a;` is a bad way to write `a *= 2;` (but might be common enough we want to silence it as well), and `a /= a;` is a bad way to write `a = 1;` (The bitwise operators may still be reasonable to silence the warning on, but even `a &= a;` and `a |= a;` seems like weird no-ops...)

All that said, my understanding of the crux of #42469 is that we wanted to silence the warning whenever the operator being used is overloaded because we have no idea whether self-assign is intended in that case. So I would expect these cases to all consistently not diagnose because they're all using the overloaded operator.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146897/new/

https://reviews.llvm.org/D146897



More information about the cfe-commits mailing list