Skip to content

[clang-tidy] bugprone-assert-side-effect non-const operator methods #71974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 16, 2023

Conversation

schenker
Copy link
Contributor

@schenker schenker commented Nov 10, 2023

With this PR, bugprone-assert-side-effect reports non-const calls to << and >> operators and does no longer consider any const operator calls to have side effects.

E.g. the following snippet is now reported and was previously not:

std::stringstream ss;
assert(ss << 1);

The following snippet was previously a false-positive and is not reported anymore:

struct {
  int operator+=(int i) const { return i; }
} t;
assert(t += 1);

@llvmbot
Copy link
Member

llvmbot commented Nov 10, 2023

@llvm/pr-subscribers-clang-tidy

Author: None (schenker)

Changes

With this PR, bugprone-assert-side-effect assumes that operator methods that are not marked as const have side effects. This matches the existing rule for non-operator methods.

E.g. the following snippet is now reported and was previously not:

std::stringstream ss;
assert(ss &lt;&lt; 1);

Full diff: https://github.com/llvm/llvm-project/pull/71974.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp (+4)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp (+12-1)
diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
index 07a987359d4d8d7..599f5ac70e7a229 100644
--- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp
@@ -41,6 +41,10 @@ AST_MATCHER_P2(Expr, hasSideEffect, bool, CheckFunctionCalls,
   }
 
   if (const auto *OpCallExpr = dyn_cast<CXXOperatorCallExpr>(E)) {
+    if (const auto *FuncDecl = OpCallExpr->getDirectCallee())
+      if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
+        return !MethodDecl->isConst();
+
     OverloadedOperatorKind OpKind = OpCallExpr->getOperator();
     return OpKind == OO_Equal || OpKind == OO_PlusEqual ||
            OpKind == OO_MinusEqual || OpKind == OO_StarEqual ||
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp
index 6c41e1e320adeac..49d3d456deb9d35 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp
@@ -11,7 +11,7 @@ class MyClass {
 
   MyClass &operator=(const MyClass &rhs) { return *this; }
 
-  int operator-() { return 1; }
+  int operator-() const { return 1; }
 
   operator bool() const { return true; }
 
@@ -84,5 +84,16 @@ int main() {
   msvc_assert(mc2 = mc);
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in msvc_assert() condition discarded in release builds
 
+  struct {
+    int operator<<(int i) const { return i; }
+  } constOp;
+  assert(constOp << 1);
+
+  struct {
+    int operator<<(int i) { return i; }
+  } nonConstOp;
+  assert(nonConstOp << 1);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds
+
   return 0;
 }

Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update documentation of this check to mention this, and update release notes.
Code looks fine.

@schenker schenker force-pushed the check-operator-method-constness branch from e71a99f to 071e24c Compare November 10, 2023 20:10
@PiotrZSL
Copy link
Member

One more question, there is option for this check:
"CheckFunctionCalls
Whether to treat non-const member and non-member functions as they produce side effects. Disabled by default because it can increase the number of false positive warnings."

Won't this overlap this change ?

Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure now if this wont cause too much false-positives, after all this is why CheckFunctionCalls option were added. Sometimes object can have 2 same operators, one const and one not, in such case depend on "this" type, non-const could be used, this would be false-positive.

@schenker
Copy link
Contributor Author

schenker commented Nov 10, 2023

I'm not sure now if this wont cause too much false-positives, after all this is why CheckFunctionCalls option were added. Sometimes object can have 2 same operators, one const and one not, in such case depend on "this" type, non-const could be used, this would be false-positive.

I adapted the tests to handle the const overload situation.

But you are right, I misunderstood CheckFunctionCalls and things are trickier than I thought. I still think it could make sense to treat method calls and method operator calls the same way.

I will rethink my implementation, thanks for reviewing!

@schenker schenker force-pushed the check-operator-method-constness branch 3 times, most recently from 44a8165 to e50f360 Compare November 13, 2023 21:28
@schenker
Copy link
Contributor Author

@PiotrZSL I changed some things, please take another look.

All const operator calls are now considered to be side-effect free. This also fixes some false-positives, e.g.

struct t {
  int operator+=(int i) const { return i; }
} t;
assert(t += 1);

is no longer reported.

I added << and >> to the list of operators with side-effects.
Only const calls are reported, so

std::stringstream ss;
assert(ss << 1);

is reported, but

assert(5 << 1);

is not.

There is no overlap with CheckFunctionCalls, CXXOperatorCallExprs are not affected by the flag.

@schenker schenker requested a review from PiotrZSL November 15, 2023 14:36
@schenker schenker force-pushed the check-operator-method-constness branch from e50f360 to 2494d69 Compare November 15, 2023 19:09
Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, rebase code before merging

@schenker schenker force-pushed the check-operator-method-constness branch from b4ed2cf to 12b5edf Compare November 15, 2023 21:35
@schenker schenker requested a review from PiotrZSL November 16, 2023 07:15
Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code is fine and can be merged, unless you want it merged as "[email protected]" you may need to disable email privacy options or try to squash all commits in one.

With this PR, `bugprone-assert-side-effect` assumes that operator methods
that are not marked as `const` have side effects. This matches the
existing rule for non-operator methods.

E.g. the following snippet is now reported and was previously not:
```
std::stringstream ss;
assert(ss << 1);
```
@schenker schenker force-pushed the check-operator-method-constness branch from 12b5edf to d899ad4 Compare November 16, 2023 08:15
@schenker
Copy link
Contributor Author

Thanks for pointing out, I squashed and changed the settings.

@PiotrZSL PiotrZSL merged commit c95d581 into llvm:main Nov 16, 2023
sr-tream pushed a commit to sr-tream/llvm-project that referenced this pull request Nov 20, 2023
…lvm#71974)

With this PR, `bugprone-assert-side-effect` reports non-const calls to
`<<` and `>>` operators and does no longer consider any const operator
calls to have side effects.

E.g. the following snippet is now reported and was previously not:
```
std::stringstream ss;
assert(ss << 1);
```

The following snippet was previously a false-positive and is not
reported anymore:
```
struct {
  int operator+=(int i) const { return i; }
} t;
assert(t += 1);
```
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
…lvm#71974)

With this PR, `bugprone-assert-side-effect` reports non-const calls to
`<<` and `>>` operators and does no longer consider any const operator
calls to have side effects.

E.g. the following snippet is now reported and was previously not:
```
std::stringstream ss;
assert(ss << 1);
```

The following snippet was previously a false-positive and is not
reported anymore:
```
struct {
  int operator+=(int i) const { return i; }
} t;
assert(t += 1);
```
@schenker schenker deleted the check-operator-method-constness branch July 23, 2024 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants