llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Victor Chernyakin (localspook)

<details>
<summary>Changes</summary>

PR #<!-- -->122265 taught `IgnoreUnlessSpelledInSource` to ignore certain 
`CallExpr`s. Because that PR was only concerned with decompositions, it was 
very conservative with which `CallExpr`s it ignored. Issue #<!-- -->150874, 
however, shows that we need to be more aggressive about ignoring `CallExpr`s. 
This snippet:

```cpp
struct S {
  operator int(this const S&amp;);
};

void f() {
  int(S {});
}
```

Generates an AST like:

```cpp
CXXFunctionalCastExpr &lt;col:3, col:11&gt; 'int' functional cast to int 
&lt;NoOp&gt;
`-ImplicitCastExpr &lt;col:7, col:10&gt; 'int' &lt;UserDefinedConversion&gt; 
part_of_explicit_cast
  `-CallExpr &lt;col:7, col:10&gt; 'int'
    |-ImplicitCastExpr &lt;col:7&gt; 'int (*)(const S &amp;)' 
&lt;FunctionToPointerDecay&gt;
    | `-DeclRefExpr &lt;col:7&gt; 'int (const S &amp;)' lvalue CXXConversion 
0x3641e4b0 'operator int' 'int (const S &amp;)'
    `-MaterializeTemporaryExpr &lt;col:7, col:10&gt; 'const S' lvalue
      `-ImplicitCastExpr &lt;col:7, col:10&gt; 'const S' &lt;NoOp&gt;
        `-CXXFunctionalCastExpr &lt;col:7, col:10&gt; 'S' functional cast to S 
&lt;NoOp&gt;
          `-InitListExpr &lt;col:9, col:10&gt; 'S'
```

The `CallExpr` there should be ignored, but isn't. This change fixes that.

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


3 Files Affected:

- (modified) 
clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp 
(+19) 
- (modified) clang/lib/AST/Expr.cpp (+4-20) 
- (modified) clang/unittests/AST/ASTTraverserTest.cpp (+36) 


``````````diff
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
index 3e723b8b61d1d..67b65d2e7f799 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp
@@ -13,6 +13,8 @@
 // RUN: %check_clang_tidy -std=c++20 -check-suffix=,ALIASES %s 
readability-redundant-casting %t -- \
 // RUN:   -config='{CheckOptions: { 
readability-redundant-casting.IgnoreTypeAliases: true }}' \
 // RUN:   -- -fno-delayed-template-parsing -D CXX_20=1
+// RUN: %check_clang_tidy -std=c++23-or-later -check-suffix=,CXX23 %s 
readability-redundant-casting %t -- \
+// RUN:   -- -fno-delayed-template-parsing
 
 struct A {};
 struct B : A {};
@@ -245,3 +247,20 @@ int g1() {
   return fp();
 }
 } // namespace gh170476
+
+
+#if __cplusplus >= 202302L
+
+struct S {
+  operator int(this const S&);
+};
+
+void testCastingWithExplicitObjectParameterConversionOperator() {
+  int i = int(S {});
+
+  int j = int(S {}.operator int());
+  // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:11: warning: redundant explicit 
casting to the same type 'int' as the sub-expression, remove this casting 
[readability-redundant-casting]
+  // CHECK-FIXES-CXX23: int j = S {}.operator int();
+}
+
+#endif // __cplusplus >= 202302L
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9632d88fae4e4..45daed276547d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2550,18 +2550,6 @@ Stmt *BlockExpr::getBody() {
 // Generic Expression Routines
 
//===----------------------------------------------------------------------===//
 
-/// Helper to determine wether \c E is a CXXConstructExpr constructing
-/// a DecompositionDecl. Used to skip Clang-generated calls to std::get
-/// for structured bindings.
-static bool IsDecompositionDeclRefExpr(const Expr *E) {
-  const auto *Unwrapped = E->IgnoreUnlessSpelledInSource();
-  const auto *Ref = dyn_cast<DeclRefExpr>(Unwrapped);
-  if (!Ref)
-    return false;
-
-  return isa_and_nonnull<DecompositionDecl>(Ref->getDecl());
-}
-
 bool Expr::isReadIfDiscardedInCPlusPlus11() const {
   // In C++11, discarded-value expressions of a certain form are special,
   // according to [expr]p10:
@@ -3178,10 +3166,11 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
   };
 
   // Used when Clang generates calls to std::get for decomposing
-  // structured bindings.
+  // structured bindings or for implicit calls to member functions
+  // with explicit object parameters.
   auto IgnoreImplicitCallSingleStep = [](Expr *E) {
     auto *C = dyn_cast<CallExpr>(E);
-    if (!C)
+    if (!C || isa<UserDefinedLiteral>(C))
       return E;
 
     // Looking for calls to a std::get, which usually just takes
@@ -3197,12 +3186,7 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
     if (A->getSourceRange() != E->getSourceRange())
       return E;
 
-    // If the argument refers to a DecompositionDecl construction,
-    // ignore it.
-    if (IsDecompositionDeclRefExpr(A))
-      return A;
-
-    return E;
+    return A;
   };
 
   return IgnoreExprNodes(
diff --git a/clang/unittests/AST/ASTTraverserTest.cpp 
b/clang/unittests/AST/ASTTraverserTest.cpp
index bcbf01b6b0385..53b6096edb5ce 100644
--- a/clang/unittests/AST/ASTTraverserTest.cpp
+++ b/clang/unittests/AST/ASTTraverserTest.cpp
@@ -1659,6 +1659,42 @@ CallExpr
                       FN[0].getNodeAs<CallExpr>("decomp_call_with_default")),
         R"cpp(
 DeclRefExpr ''
+)cpp");
+  }
+
+  auto AST3 = buildASTFromCodeWithArgs(R"cpp(
+
+struct S {
+  operator int(this const S&);
+};
+
+void f() {
+  S s;
+  int i = int(s);
+}
+
+)cpp",
+                                       {"-std=c++23"});
+  {
+    auto FN = ast_matchers::match(
+        explicitCastExpr(hasSourceExpression(expr().bind("sourceExpr"))),
+        AST3->getASTContext());
+    EXPECT_EQ(FN.size(), 1u);
+
+    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Expr>("sourceExpr")),
+              R"cpp(
+ImplicitCastExpr
+`-CallExpr
+  |-ImplicitCastExpr
+  | `-DeclRefExpr 'operator int'
+  `-ImplicitCastExpr
+    `-DeclRefExpr 's'
+)cpp");
+
+    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+                            FN[0].getNodeAs<Expr>("sourceExpr")),
+              R"cpp(
+DeclRefExpr 's'
 )cpp");
   }
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/183882
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to