[clang] [Clang][ASTImporter] Implement AST import for CXXParenListInitExpr, SubstNonTypeTemplateParmPackExpr, PseudoObjectExpr (PR #160904)

via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 14 09:02:44 PDT 2025


https://github.com/ganenkokb-yandex updated https://github.com/llvm/llvm-project/pull/160904

>From c66a8cd53799cae624b4155adc6f5d419636d654 Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Thu, 25 Sep 2025 18:11:46 +0300
Subject: [PATCH 1/7] Implement VisitSubstNonTypeTemplateParmPackExpr

---
 clang/lib/AST/ASTImporter.cpp | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f43fa8c90ad3b..46b101206b4aa 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -696,6 +696,8 @@ namespace clang {
     ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E);
     ExpectedStmt VisitRequiresExpr(RequiresExpr* E);
     ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E);
+    ExpectedStmt
+    VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E);
 
     // Helper for chaining together multiple imports. If an error is detected,
     // subsequent imports will return default constructed nodes, so that failure
@@ -9274,6 +9276,21 @@ ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
       const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
 }
 
+ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmPackExpr(
+    SubstNonTypeTemplateParmPackExpr *E) {
+  Error Err = Error::success();
+  auto ToType = importChecked(Err, E->getType());
+  auto ToNameLoc = importChecked(Err, E->getParameterPackLocation());
+  auto ToArgPack = importChecked(Err, E->getArgumentPack());
+  auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl());
+  if (Err)
+    return std::move(Err);
+
+  return new (Importer.getToContext()) SubstNonTypeTemplateParmPackExpr(
+      ToType, E->getValueKind(), ToNameLoc, ToArgPack, ToAssociatedDecl,
+      E->getIndex(), E->getFinal());
+}
+
 Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod,
                                                CXXMethodDecl *FromMethod) {
   Error ImportErrors = Error::success();

>From 2227fb8ab75db6be0215c77c72a5c25ee8ff7b33 Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Thu, 25 Sep 2025 18:13:07 +0300
Subject: [PATCH 2/7] Implement VisitPseudoObjectExpr

---
 clang/lib/AST/ASTImporter.cpp | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 46b101206b4aa..521a0b17a3778 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -698,6 +698,7 @@ namespace clang {
     ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E);
     ExpectedStmt
     VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E);
+    ExpectedStmt VisitPseudoObjectExpr(PseudoObjectExpr *E);
 
     // Helper for chaining together multiple imports. If an error is detected,
     // subsequent imports will return default constructed nodes, so that failure
@@ -9291,6 +9292,21 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmPackExpr(
       E->getIndex(), E->getFinal());
 }
 
+ExpectedStmt ASTNodeImporter::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
+  SmallVector<Expr *, 4> ToSemantics(E->getNumSemanticExprs());
+  if (Error Err = ImportContainerChecked(E->semantics(), ToSemantics))
+    return std::move(Err);
+  Expr *ToSynt = nullptr;
+  if (const Expr *FromSynt = E->getSyntacticForm()) {
+    if (auto ToSyntOrErr = import(FromSynt))
+      ToSynt = *ToSyntOrErr;
+    else
+      return ToSyntOrErr.takeError();
+  }
+  return PseudoObjectExpr::Create(Importer.getToContext(), ToSynt, ToSemantics,
+                                  E->getResultExprIndex());
+}
+
 Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod,
                                                CXXMethodDecl *FromMethod) {
   Error ImportErrors = Error::success();

>From ced227201888a89e67518a1815b8f2eb55ca4652 Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Thu, 25 Sep 2025 18:14:29 +0300
Subject: [PATCH 3/7] Implement VisitCXXParenListInitExpr

---
 clang/lib/AST/ASTImporter.cpp | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 521a0b17a3778..cb4bc4e6f41fb 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -699,6 +699,7 @@ namespace clang {
     ExpectedStmt
     VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E);
     ExpectedStmt VisitPseudoObjectExpr(PseudoObjectExpr *E);
+    ExpectedStmt VisitCXXParenListInitExpr(CXXParenListInitExpr *E);
 
     // Helper for chaining together multiple imports. If an error is detected,
     // subsequent imports will return default constructed nodes, so that failure
@@ -9307,6 +9308,24 @@ ExpectedStmt ASTNodeImporter::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
                                   E->getResultExprIndex());
 }
 
+ExpectedStmt
+ASTNodeImporter::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
+  Error Err = Error::success();
+  auto ToType = importChecked(Err, E->getType());
+  auto ToInitLoc = importChecked(Err, E->getInitLoc());
+  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+  auto ToEndLoc = importChecked(Err, E->getEndLoc());
+  if (Err)
+    return std::move(Err);
+
+  SmallVector<Expr *, 4> ToArgs(E->getInitExprs().size());
+  if (Error Err = ImportContainerChecked(E->getInitExprs(), ToArgs))
+    return std::move(Err);
+  return CXXParenListInitExpr::Create(Importer.getToContext(), ToArgs, ToType,
+                                      E->getUserSpecifiedInitExprs().size(),
+                                      ToInitLoc, ToBeginLoc, ToEndLoc);
+}
+
 Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod,
                                                CXXMethodDecl *FromMethod) {
   Error ImportErrors = Error::success();

>From 2b965111255f53f81a6981e64d73c250f727fd5d Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Fri, 10 Oct 2025 18:34:52 +0300
Subject: [PATCH 4/7] Add tests for VisitSubstNonTypeTemplateParmPackExpr

---
 clang/unittests/AST/ASTImporterTest.cpp | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index e7160bcf2e0c2..72192abeb59e0 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -3300,6 +3300,22 @@ TEST_P(ImportExpr, ConceptNestedNonInstantiationDependentRequirement) {
              conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
 }
 
+TEST_P(ImportExpr, ImportSubstNonTypeTemplateParmPackExpr) {
+  MatchVerifier<Decl> Verifier;
+  const char *Code = R"(
+    template<auto ...> struct X {};
+    template<typename ...> struct Z {};
+
+    template<int ...N> struct E {
+      template<int ...M> using B = Z<X<N, M>...>;
+      template<int M1, int M2> E(B<M1, M2>);
+    };
+    using declToImport = E<1, 3>;
+  )";
+  testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
+             typedefNameDecl(hasName("declToImport")));
+}
+
 class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
 public:
   static constexpr auto DefaultCode = R"(

>From bfa402edfd5e17b56383c718b29e5a1cd5874eec Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Mon, 13 Oct 2025 12:35:54 +0300
Subject: [PATCH 5/7] Add test for VisitCXXParenListInitExpr

---
 clang/unittests/AST/ASTImporterTest.cpp | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 72192abeb59e0..41659f3fcfdd0 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -3316,6 +3316,23 @@ TEST_P(ImportExpr, ImportSubstNonTypeTemplateParmPackExpr) {
              typedefNameDecl(hasName("declToImport")));
 }
 
+
+TEST_P(ImportExpr, ImportCXXParenListInitExpr) {
+  MatchVerifier<Decl> Verifier;
+  const char *Code = R"(
+    struct Node {
+      int val;
+      double d;
+    };
+    template <int N> struct Container {
+      Node* create() { return new Node(N, 3.14); }
+    };
+    using declToImport = Container<42>;
+  )";
+  testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
+             typedefNameDecl(hasName("declToImport")));
+}
+
 class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
 public:
   static constexpr auto DefaultCode = R"(

>From 2194a6a4a102dc34571e085e3652ded956ec18c8 Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Mon, 13 Oct 2025 14:21:38 +0300
Subject: [PATCH 6/7] Add test for VisitPseudoObjectExpr

---
 clang/unittests/AST/ASTImporterTest.cpp | 38 ++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 41659f3fcfdd0..a60ea9622e8e6 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -3316,7 +3316,6 @@ TEST_P(ImportExpr, ImportSubstNonTypeTemplateParmPackExpr) {
              typedefNameDecl(hasName("declToImport")));
 }
 
-
 TEST_P(ImportExpr, ImportCXXParenListInitExpr) {
   MatchVerifier<Decl> Verifier;
   const char *Code = R"(
@@ -3333,6 +3332,43 @@ TEST_P(ImportExpr, ImportCXXParenListInitExpr) {
              typedefNameDecl(hasName("declToImport")));
 }
 
+TEST_P(ImportExpr, ImportPseudoObjectExpr) {
+  MatchVerifier<Decl> Verifier;
+  const char *Code = R"(
+  namespace std {
+    struct strong_ordering {
+      int n;
+      constexpr operator int() const { return n; }
+      static const strong_ordering less, equal, greater;
+    };
+    constexpr strong_ordering strong_ordering::less{-1},
+        strong_ordering::equal{0}, strong_ordering::greater{1};
+  }
+
+  struct A {
+    std::strong_ordering operator<=>(const A&) const;
+  };
+  struct B {
+    bool operator==(const B&) const;
+    bool operator<(const B&) const;
+  };
+
+  template<typename T> struct Cmp : T {
+    std::strong_ordering operator<=>(const Cmp&) const = default;
+  };
+
+  void use(...);
+  void declToImport() {
+    use(
+      Cmp<A>() <=> Cmp<A>(),
+      Cmp<B>() <=> Cmp<B>()
+    );
+  }
+  )";
+  testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
+             functionDecl(hasName("declToImport")));
+}
+
 class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
 public:
   static constexpr auto DefaultCode = R"(

>From 3f343d7cd9d5a84542c58a91bda0937792ad0aef Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenkokb at yandex-team.ru>
Date: Tue, 14 Oct 2025 19:02:19 +0300
Subject: [PATCH 7/7] Code review

Skip null check in VisitPseudoObjectExpr
Fix bad naming in VisitConceptSpecializationExpr
Simplify test for ImportCXXParenListInitExpr
---
 clang/lib/AST/ASTImporter.cpp           | 18 +++++++-----------
 clang/unittests/AST/ASTImporterTest.cpp |  7 ++-----
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index cb4bc4e6f41fb..7b9c7e4abff82 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -9282,14 +9282,14 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmPackExpr(
     SubstNonTypeTemplateParmPackExpr *E) {
   Error Err = Error::success();
   auto ToType = importChecked(Err, E->getType());
-  auto ToNameLoc = importChecked(Err, E->getParameterPackLocation());
+  auto ToPackLoc = importChecked(Err, E->getParameterPackLocation());
   auto ToArgPack = importChecked(Err, E->getArgumentPack());
   auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl());
   if (Err)
     return std::move(Err);
 
   return new (Importer.getToContext()) SubstNonTypeTemplateParmPackExpr(
-      ToType, E->getValueKind(), ToNameLoc, ToArgPack, ToAssociatedDecl,
+      ToType, E->getValueKind(), ToPackLoc, ToArgPack, ToAssociatedDecl,
       E->getIndex(), E->getFinal());
 }
 
@@ -9297,15 +9297,11 @@ ExpectedStmt ASTNodeImporter::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
   SmallVector<Expr *, 4> ToSemantics(E->getNumSemanticExprs());
   if (Error Err = ImportContainerChecked(E->semantics(), ToSemantics))
     return std::move(Err);
-  Expr *ToSynt = nullptr;
-  if (const Expr *FromSynt = E->getSyntacticForm()) {
-    if (auto ToSyntOrErr = import(FromSynt))
-      ToSynt = *ToSyntOrErr;
-    else
-      return ToSyntOrErr.takeError();
-  }
-  return PseudoObjectExpr::Create(Importer.getToContext(), ToSynt, ToSemantics,
-                                  E->getResultExprIndex());
+  auto ToSyntOrErr = import(E->getSyntacticForm());
+  if (!ToSyntOrErr)
+    return ToSyntOrErr.takeError();
+  return PseudoObjectExpr::Create(Importer.getToContext(), *ToSyntOrErr,
+                                  ToSemantics, E->getResultExprIndex());
 }
 
 ExpectedStmt
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index a60ea9622e8e6..a9bfcc296d9b3 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -3323,13 +3323,10 @@ TEST_P(ImportExpr, ImportCXXParenListInitExpr) {
       int val;
       double d;
     };
-    template <int N> struct Container {
-      Node* create() { return new Node(N, 3.14); }
-    };
-    using declToImport = Container<42>;
+    Node* declToImport() { return new Node(2, 3.14); }
   )";
   testImport(Code, Lang_CXX20, "", Lang_CXX20, Verifier,
-             typedefNameDecl(hasName("declToImport")));
+             functionDecl(hasName("declToImport")));
 }
 
 TEST_P(ImportExpr, ImportPseudoObjectExpr) {



More information about the cfe-commits mailing list