kimgr updated this revision to Diff 400381.
kimgr added a comment.

Fix spurious semicolon


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117391

Files:
  clang/lib/AST/Expr.cpp
  clang/unittests/Tooling/CastExprTest.cpp


Index: clang/unittests/Tooling/CastExprTest.cpp
===================================================================
--- clang/unittests/Tooling/CastExprTest.cpp
+++ clang/unittests/Tooling/CastExprTest.cpp
@@ -14,12 +14,19 @@
 
 struct CastExprVisitor : TestVisitor<CastExprVisitor> {
   std::function<void(ExplicitCastExpr *)> OnExplicitCast;
+  std::function<void(CastExpr *)> OnCast;
 
   bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) {
     if (OnExplicitCast)
       OnExplicitCast(Expr);
     return true;
   }
+
+  bool VisitCastExpr(CastExpr *Expr) {
+    if (OnCast)
+      OnCast(Expr);
+    return true;
+  }
 };
 
 TEST(CastExprTest, GetSubExprAsWrittenThroughMaterializedTemporary) {
@@ -54,4 +61,57 @@
                   CastExprVisitor::Lang_CXX2a);
 }
 
+// Verify that getConversionFunction looks through a ConstantExpr for implicit
+// constructor conversions (https://github.com/llvm/llvm-project/issues/53044):
+//
+// `-ImplicitCastExpr 'S' <ConstructorConversion>
+// `-ConstantExpr 'S'
+//   |-value: Struct
+//   `-CXXConstructExpr 'S' 'void (const char *)'
+//     `-ImplicitCastExpr 'const char *' <ArrayToPointerDecay>
+//       `-StringLiteral 'const char [7]' lvalue "foobar"
+TEST(CastExprTest, GetCtorConversionFunctionThroughConstantExpr) {
+  CastExprVisitor Visitor;
+  Visitor.OnCast = [](CastExpr *Expr) {
+    if (Expr->getCastKind() == CK_ConstructorConversion) {
+      auto *Conv = Expr->getConversionFunction();
+      EXPECT_TRUE(isa<CXXConstructorDecl>(Conv))
+          << "Expected CXXConstructorDecl, but saw " << 
Conv->getDeclKindName();
+    }
+  };
+  Visitor.runOver("struct X { consteval X(const char *) {} };\n"
+                  "void f() { X x = \"foobar\"; }\n",
+                  CastExprVisitor::Lang_CXX2a);
+}
+
+// Verify that getConversionFunction looks through a ConstantExpr for implicit
+// user-defined conversions.
+//
+// `-ImplicitCastExpr 'const char *' <UserDefinedConversion>
+//   `-ConstantExpr 'const char *'
+//     |-value: LValue
+//     `-CXXMemberCallExpr 'const char *'
+//       `-MemberExpr '<bound member function type>' .operator const char *
+//         `-DeclRefExpr 'const X' lvalue Var 'x' 'const X'
+TEST(CastExprTest, GetUserDefinedConversionFunctionThroughConstantExpr) {
+  CastExprVisitor Visitor;
+  Visitor.OnCast = [](CastExpr *Expr) {
+    if (Expr->getCastKind() == CK_UserDefinedConversion) {
+      auto *Conv = Expr->getConversionFunction();
+      EXPECT_TRUE(isa<CXXMethodDecl>(Conv))
+          << "Expected CXXMethodDecl, but saw " << Conv->getDeclKindName();
+    }
+  };
+  Visitor.runOver("struct X {\n"
+                  "  consteval operator const char *() const {\n"
+                  "    return nullptr;\n"
+                  "  }\n"
+                  "};\n"
+                  "const char *f() {\n"
+                  "  constexpr X x;\n"
+                  "  return x;\n"
+                  "}\n",
+                  CastExprVisitor::Lang_CXX2a);
+}
+
 } // namespace
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -1944,6 +1944,7 @@
 
   for (const CastExpr *E = this; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) {
     SubExpr = skipImplicitTemporary(E->getSubExpr());
+    SubExpr = SubExpr->IgnoreImplicit();
 
     if (E->getCastKind() == CK_ConstructorConversion)
       return cast<CXXConstructExpr>(SubExpr)->getConstructor();


Index: clang/unittests/Tooling/CastExprTest.cpp
===================================================================
--- clang/unittests/Tooling/CastExprTest.cpp
+++ clang/unittests/Tooling/CastExprTest.cpp
@@ -14,12 +14,19 @@
 
 struct CastExprVisitor : TestVisitor<CastExprVisitor> {
   std::function<void(ExplicitCastExpr *)> OnExplicitCast;
+  std::function<void(CastExpr *)> OnCast;
 
   bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) {
     if (OnExplicitCast)
       OnExplicitCast(Expr);
     return true;
   }
+
+  bool VisitCastExpr(CastExpr *Expr) {
+    if (OnCast)
+      OnCast(Expr);
+    return true;
+  }
 };
 
 TEST(CastExprTest, GetSubExprAsWrittenThroughMaterializedTemporary) {
@@ -54,4 +61,57 @@
                   CastExprVisitor::Lang_CXX2a);
 }
 
+// Verify that getConversionFunction looks through a ConstantExpr for implicit
+// constructor conversions (https://github.com/llvm/llvm-project/issues/53044):
+//
+// `-ImplicitCastExpr 'S' <ConstructorConversion>
+// `-ConstantExpr 'S'
+//   |-value: Struct
+//   `-CXXConstructExpr 'S' 'void (const char *)'
+//     `-ImplicitCastExpr 'const char *' <ArrayToPointerDecay>
+//       `-StringLiteral 'const char [7]' lvalue "foobar"
+TEST(CastExprTest, GetCtorConversionFunctionThroughConstantExpr) {
+  CastExprVisitor Visitor;
+  Visitor.OnCast = [](CastExpr *Expr) {
+    if (Expr->getCastKind() == CK_ConstructorConversion) {
+      auto *Conv = Expr->getConversionFunction();
+      EXPECT_TRUE(isa<CXXConstructorDecl>(Conv))
+          << "Expected CXXConstructorDecl, but saw " << Conv->getDeclKindName();
+    }
+  };
+  Visitor.runOver("struct X { consteval X(const char *) {} };\n"
+                  "void f() { X x = \"foobar\"; }\n",
+                  CastExprVisitor::Lang_CXX2a);
+}
+
+// Verify that getConversionFunction looks through a ConstantExpr for implicit
+// user-defined conversions.
+//
+// `-ImplicitCastExpr 'const char *' <UserDefinedConversion>
+//   `-ConstantExpr 'const char *'
+//     |-value: LValue
+//     `-CXXMemberCallExpr 'const char *'
+//       `-MemberExpr '<bound member function type>' .operator const char *
+//         `-DeclRefExpr 'const X' lvalue Var 'x' 'const X'
+TEST(CastExprTest, GetUserDefinedConversionFunctionThroughConstantExpr) {
+  CastExprVisitor Visitor;
+  Visitor.OnCast = [](CastExpr *Expr) {
+    if (Expr->getCastKind() == CK_UserDefinedConversion) {
+      auto *Conv = Expr->getConversionFunction();
+      EXPECT_TRUE(isa<CXXMethodDecl>(Conv))
+          << "Expected CXXMethodDecl, but saw " << Conv->getDeclKindName();
+    }
+  };
+  Visitor.runOver("struct X {\n"
+                  "  consteval operator const char *() const {\n"
+                  "    return nullptr;\n"
+                  "  }\n"
+                  "};\n"
+                  "const char *f() {\n"
+                  "  constexpr X x;\n"
+                  "  return x;\n"
+                  "}\n",
+                  CastExprVisitor::Lang_CXX2a);
+}
+
 } // namespace
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -1944,6 +1944,7 @@
 
   for (const CastExpr *E = this; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) {
     SubExpr = skipImplicitTemporary(E->getSubExpr());
+    SubExpr = SubExpr->IgnoreImplicit();
 
     if (E->getCastKind() == CK_ConstructorConversion)
       return cast<CXXConstructExpr>(SubExpr)->getConstructor();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to