Skip to content

[clang-tidy] fix match for binaryOperator in ExprMutationAnalyzer for misc-const-correctness #70559

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

Conversation

5chmidti
Copy link
Contributor

The ExprMutationAnalyzers matcher of binaryOperators
that contained the variable expr, were previously narrowing the
variable to be type dependent, when the binaryOperator should
have been narrowed as dependent.
The variable we are trying to find mutations for does
not need to be the dependent type, the other operand of
the binaryOperator could be dependent.

Fixes #57297

… misc-const-correctness

The `ExprMutationAnalyzer`s matcher of `binaryOperator`s
that contained the variable expr, were previously narrowing the
variable to be type dependent, when the `binaryOperator` should
have been narrowed as dependent.
The variable we are trying to find mutations for does
not need to be the dependent type, the other operand of
the `binaryOperator` could be dependent.

Fixes llvm#57297
@llvmbot llvmbot added clang Clang issues not falling into any other category clang-tidy clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang:analysis labels Oct 28, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 28, 2023

@llvm/pr-subscribers-clang-analysis
@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang

Author: Julian Schmidt (5chmidti)

Changes

The ExprMutationAnalyzers matcher of binaryOperators
that contained the variable expr, were previously narrowing the
variable to be type dependent, when the binaryOperator should
have been narrowed as dependent.
The variable we are trying to find mutations for does
not need to be the dependent type, the other operand of
the binaryOperator could be dependent.

Fixes #57297


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

5 Files Affected:

  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp (+11)
  • (modified) clang/docs/ReleaseNotes.rst (+3)
  • (modified) clang/lib/Analysis/ExprMutationAnalyzer.cpp (+3-3)
  • (modified) clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp (+11)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5ce38ab48bf295f..bb75c9a3ce08125 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -308,6 +308,11 @@ Changes in existing checks
   <clang-tidy/checks/misc/const-correctness>` check to avoid false positive when
   using pointer to member function.
 
+- Improved :doc:`misc-const-correctness
+  <clang-tidy/checks/misc/const-correctness>` check to not warn on uses in
+  type-dependent binary operators, when the variable that is being
+  looked at, is not the dependent operand.
+
 - Improved :doc:`misc-include-cleaner
   <clang-tidy/checks/misc/include-cleaner>` check by adding option
   `DeduplicateFindings` to output one finding per symbol occurrence, avoid
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp
index 7b5ccabdd6ef611..415bb06020b9dc3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-templates.cpp
@@ -20,3 +20,14 @@ void instantiate_template_cases() {
   type_dependent_variables<int>();
   type_dependent_variables<float>();
 }
+
+namespace gh57297{
+struct Stream {};
+// Explicitly not declaring a (templated) stream operator
+// so the `<<` is a `binaryOperator` with a dependent type.
+template <typename T> void f() {
+  T t;
+  Stream stream;
+  stream << t;
+}
+} // namespace gh57297
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2595737e8b3b143..fb9afc0646ac8cb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -683,6 +683,9 @@ Bug Fixes to AST Handling
 - Fixed a bug where RecursiveASTVisitor fails to visit the
   initializer of a bitfield.
   `Issue 64916 <https://github.com/llvm/llvm-project/issues/64916>`_
+- Fixed a bug where ``ExprMutationAnalyzer`` did not find a potential mutation
+  for uses in type-dependent binary operators, when the variable that is being
+  looked at, is not the dependent operand.
 
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
index f2e1beb025423cf..624a643cc60e4ba 100644
--- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp
+++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
@@ -296,9 +296,9 @@ const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) {
       // resolved and modelled as `binaryOperator` on a dependent type.
       // Such instances are considered a modification, because they can modify
       // in different instantiations of the template.
-      binaryOperator(hasEitherOperand(
-          allOf(ignoringImpCasts(canResolveToExpr(equalsNode(Exp))),
-                isTypeDependent()))),
+      binaryOperator(
+          hasEitherOperand(ignoringImpCasts(canResolveToExpr(equalsNode(Exp)))),
+          isTypeDependent()),
       // Within class templates and member functions the member expression might
       // not be resolved. In that case, the `callExpr` is considered to be a
       // modification.
diff --git a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
index c0a398394093c48..cfa3c535ce35292 100644
--- a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
+++ b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
@@ -343,6 +343,17 @@ TEST(ExprMutationAnalyzerTest, UnresolvedOperator) {
   EXPECT_TRUE(isMutated(Results, AST.get()));
 }
 
+TEST(ExprMutationAnalyzerTest, DependentOperatorWithNonDependentOperand) {
+  // gh57297
+  // Explicitly not declaring a (templated) stream operator
+  // so the `<<` is a `binaryOperator` with a dependent type.
+  const auto AST = buildASTFromCode("struct Stream {}; template <typename T> "
+                                    "void f() { T t; Stream x; x << t;}");
+  const auto Results =
+      match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x << t"));
+}
+
 // Section: expression as call argument
 
 TEST(ExprMutationAnalyzerTest, ByValueArgument) {

@5chmidti
Copy link
Contributor Author

CC @JonasToth for your work on ExprMutationAnalyzer

@5chmidti
Copy link
Contributor Author

The top-level Linux and Windows tests work, but inside the Trigger Build/clang-ci run, the windows test step fails. I'm not sure what the difference is between these two Windows tests.

@jcsxky
Copy link
Contributor

jcsxky commented Oct 31, 2023

The top-level Linux and Windows tests work, but inside the Trigger Build/clang-ci run, the windows test step fails. I'm not sure what the difference is between these two Windows tests.

It is interesting! Generally speaking, AST of the code in Windows and Linux platform is identical with clang compiled. Probably need debuging in Windows.

@5chmidti
Copy link
Contributor Author

5chmidti commented Nov 3, 2023

I found the issue, but I have not looked for a solution.
See https://godbolt.org/z/or4EnMfWj and #71203.
When using clang with -target to specify x86_64-pc-win32 and x86_64-linux, the body for the function f is NULL in the AST with the windows target. This only happens for -target x86_64-windows pre c++20.

Although the tested code does not directly depend on being c++20 (it is valid in c++11), maybe I constrain the tests in this pr to be in c++20 mode until the issue is fixed? What do you think?

@jcsxky
Copy link
Contributor

jcsxky commented Nov 7, 2023

how about adding a function call like f<int>()? will this can prevent clang to emit empty function body?

- explicitly instantiate template
- provide operator int() to Stream to ensure << is a BinaryOperator,
  not a CXXOperatorCallExpr
@5chmidti
Copy link
Contributor Author

5chmidti commented Nov 9, 2023

how about adding a function call like f<int>()? will this can prevent clang to emit empty function body?

Yep, thanks. I went this route, but I had to define a conversion operator to compile and keep the << a BinaryOperator. The CI now passes

@PiotrZSL
Copy link
Member

PiotrZSL commented Nov 9, 2023

In tests we usually use -fno-delayed-template-parsing to overcome this issue with templates and windows.

@5chmidti
Copy link
Contributor Author

In tests we usually use -fno-delayed-template-parsing to overcome this issue with templates and windows.

Done. I changed the test in ExprMutationAnalyzerTest.cpp to use the flag, const-correctness-templates.cpp already had it, and I changed the tested code back to what it was before (-formatting).

@PiotrZSL PiotrZSL merged commit a3d76b3 into llvm:main Nov 14, 2023
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
… misc-const-correctness (llvm#70559)

The `ExprMutationAnalyzer`s matcher of `binaryOperator`s
that contained the variable expr, were previously narrowing the
variable to be type dependent, when the `binaryOperator` should
have been narrowed as dependent.
The variable we are trying to find mutations for does
not need to be the dependent type, the other operand of
the `binaryOperator` could be dependent.

Fixes llvm#57297
@5chmidti 5chmidti deleted the clang_tidy_misc_const_correctness_gh57297 branch November 2, 2024 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:analysis clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang Clang issues not falling into any other category clang-tidy
Projects
None yet
Development

Successfully merging this pull request may close these issues.

misc-const-correctness false positive with variable in template
4 participants