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

>From 0a5beb71cb46ad5ef2df753098a6742ffeef3a71 Mon Sep 17 00:00:00 2001
From: Evianaive <153540...@qq.com>
Date: Tue, 25 Mar 2025 01:54:06 +0800
Subject: [PATCH 1/8] Implement missing visit function

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

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 003bad225e30c..775e9b83d1fb1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -68,6 +68,7 @@
 #include <optional>
 #include <type_traits>
 #include <utility>
+#include "ExprConcepts.h"
 
 namespace clang {
 
@@ -564,6 +565,9 @@ namespace clang {
     ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D);
     ExpectedDecl 
VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
     ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+    ExpectedDecl VisitConceptDecl(ConceptDecl* D);
+    ExpectedDecl VisitRequiresExprBodyDecl(RequiresExprBodyDecl* E);
+    ExpectedDecl 
VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl* D);
 
     // Importing statements
     ExpectedStmt VisitStmt(Stmt *S);
@@ -680,6 +684,8 @@ namespace clang {
     ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
     ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
     ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E);
+    ExpectedStmt VisitRequiresExpr(RequiresExpr* E);
+    ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E);
 
     // Helper for chaining together multiple imports. If an error is detected,
     // subsequent imports will return default constructed nodes, so that 
failure
@@ -1063,6 +1069,168 @@ Expected<LambdaCapture> ASTNodeImporter::import(const 
LambdaCapture &From) {
       EllipsisLoc);
 }
 
+template<>
+Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement* FromRequire) {
+  auto ImportStringRef = [this](const StringRef& FromString) {
+      char* ToDiagMessage = new (Importer.getToContext()) 
char[FromString.size()];
+      std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
+      return StringRef(ToDiagMessage,FromString.size());
+    };
+    
+  auto ImportSubstitutionDiagnos = [this, &ImportStringRef]
+  (concepts::Requirement::SubstitutionDiagnostic* FromDiagnos, Error& 
Err)->concepts::Requirement::SubstitutionDiagnostic* {
+    const auto& ToEntity = ImportStringRef(FromDiagnos->SubstitutedEntity);
+    Expected<SourceLocation> ToLoc = import(FromDiagnos->DiagLoc);
+    if(!ToLoc) {
+      Err = ToLoc.takeError();
+      return nullptr;
+    }
+    const auto& ToDiagMessage =  ImportStringRef(FromDiagnos->DiagMessage);
+    return new (Importer.getToContext()) 
concepts::Requirement::SubstitutionDiagnostic{
+      ToEntity,
+      ToLoc.get(),
+      ToDiagMessage};
+  };
+  switch (FromRequire->getKind()) {
+  case concepts::Requirement::RequirementKind::RK_Type: {
+    auto *From = cast<concepts::TypeRequirement>(FromRequire);
+    if(From->isSubstitutionFailure())
+    {
+      // Should we return Error directly if TypeRequirement 
isSubstitutionFailure?
+      Error Err = Error::success();
+      auto Diagnos = 
ImportSubstitutionDiagnos(From->getSubstitutionDiagnostic(),Err);
+      if (Err)
+        return std::move(Err);
+      return new (Importer.getToContext()) concepts::TypeRequirement(Diagnos);
+    }
+    else {
+      Expected<TypeSourceInfo *> ToType = import(From->getType());
+      if(!ToType)
+        return ToType.takeError();
+      return new (Importer.getToContext()) 
concepts::TypeRequirement(ToType.get());
+    }
+    break;
+  }
+  case concepts::Requirement::RequirementKind::RK_Compound: 
+  case concepts::Requirement::RequirementKind::RK_Simple: {
+    const auto *From = cast<concepts::ExprRequirement>(FromRequire);
+    
+    auto Status = From->getSatisfactionStatus();
+    llvm::PointerUnion<concepts::Requirement::SubstitutionDiagnostic *, Expr 
*> E;
+    if (Status == concepts::ExprRequirement::SS_ExprSubstitutionFailure) {
+      Error Err = Error::success();
+      E = ImportSubstitutionDiagnos(From->getExprSubstitutionDiagnostic(),Err);
+      if (Err)
+        return std::move(Err);
+    } else {
+      auto ExpectE = import(From->getExpr());
+      if (!ExpectE)
+        return ExpectE.takeError();
+      E = ExpectE.get();
+    }
+
+    std::optional<concepts::ExprRequirement::ReturnTypeRequirement> Req;
+    ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
+    SourceLocation NoexceptLoc;
+    bool IsRKSimple = FromRequire->getKind() == 
concepts::Requirement::RK_Simple;
+    if (IsRKSimple) {
+      Req.emplace();
+    } else {
+      auto NoexceptLoc = import(From->getNoexceptLoc());
+      if(!NoexceptLoc)
+        return NoexceptLoc.takeError();
+      auto& FromTypeRequirement = From->getReturnTypeRequirement();
+
+      if(FromTypeRequirement.isTypeConstraint()) {
+        auto ParamsOrErr = 
import(FromTypeRequirement.getTypeConstraintTemplateParameterList());
+        if (!ParamsOrErr)
+          return ParamsOrErr.takeError();
+        if (Status >=
+          concepts::ExprRequirement::SS_ConstraintsNotSatisfied) {
+          auto ExpectSubstitutedConstraintExpr = 
import(From->getReturnTypeRequirementSubstitutedConstraintExpr());
+          if (!ExpectSubstitutedConstraintExpr)
+            return ExpectSubstitutedConstraintExpr.takeError();
+          SubstitutedConstraintExpr = ExpectSubstitutedConstraintExpr.get();
+        }
+        Req.emplace(ParamsOrErr.get());
+      }      
+      else if(FromTypeRequirement.isSubstitutionFailure()) {
+        Error Err = Error::success();
+        concepts::Requirement::SubstitutionDiagnostic *ToDiagnos =
+            ImportSubstitutionDiagnos(
+                FromTypeRequirement.getSubstitutionDiagnostic(), Err);
+        if (Err)
+          return std::move(Err);
+       Req.emplace(ToDiagnos);
+      }
+      else {
+        Req.emplace();
+      }      
+    }
+    if (Expr *Ex = E.dyn_cast<Expr *>())
+      return new (Importer.getToContext()) concepts::ExprRequirement(
+              Ex, IsRKSimple, NoexceptLoc,
+              std::move(*Req), Status, SubstitutedConstraintExpr);
+    else
+      return new (Importer.getToContext()) concepts::ExprRequirement(
+              E.get<concepts::Requirement::SubstitutionDiagnostic *>(),
+              IsRKSimple, NoexceptLoc,
+              std::move(*Req));
+    break;
+  }
+  case concepts::Requirement::RequirementKind::RK_Nested: {
+    auto *From = cast<concepts::NestedRequirement>(FromRequire);
+    const auto& FromSatisfaction = From->getConstraintSatisfaction();
+    if(From->hasInvalidConstraint()) {
+      const auto& ToConstraintEntity = 
ImportStringRef(From->getInvalidConstraintEntity());
+      auto ToSatisfaction = 
ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),FromSatisfaction);
+      return new (Importer.getToContext()) 
concepts::NestedRequirement(ToConstraintEntity,ToSatisfaction);
+    } else {
+      Expected<Expr *> ToExpr = import(From->getConstraintExpr());
+      if(!ToExpr)
+        return ToExpr.takeError();
+      // FromSatisfaction.IsSatisfied;
+      if(ToExpr.get()->isInstantiationDependent())
+        return new (Importer.getToContext()) 
concepts::NestedRequirement(ToExpr.get());
+      else {
+        ConstraintSatisfaction Satisfaction;
+        Satisfaction.IsSatisfied = FromSatisfaction.IsSatisfied;
+        Satisfaction.ContainsErrors = FromSatisfaction.ContainsErrors;        
+        if (!Satisfaction.IsSatisfied) {
+          for (auto Record = FromSatisfaction.begin(); Record != 
FromSatisfaction.end(); ++Record) {
+            const Expr *ConstraintExpr = Record->first;
+            Expected<Expr *> ToConstraintExpr = import(ConstraintExpr);
+            if(!ToConstraintExpr)
+              return ToConstraintExpr.takeError();
+            if(Record->second.is<Expr*>()) {
+              Expected<Expr *> ToSecondExpr = 
import(Record->second.get<Expr*>());
+              if(!ToSecondExpr)
+                return ToSecondExpr.takeError();
+              
Satisfaction.Details.emplace_back(ToConstraintExpr.get(),ToSecondExpr.get());
+            } else {
+              std::pair<SourceLocation, StringRef> *pair = Record->second.get<
+                std::pair<SourceLocation, StringRef> *>();
+              Error Err = Error::success();
+
+              auto ToPairFirst = import(pair->first);
+              if(!ToPairFirst)
+                return ToPairFirst.takeError();
+              StringRef ToPairSecond = ImportStringRef(pair->second);
+              Satisfaction.Details.emplace_back(
+              ToConstraintExpr.get(), new (Importer.getToContext())
+                ConstraintSatisfaction::SubstitutionDiagnostic{
+                  ToPairFirst.get(), ToPairSecond});
+            }
+          }
+        }
+        return new (Importer.getToContext()) 
concepts::NestedRequirement(Importer.getToContext(),ToExpr.get(),Satisfaction);
+      }      
+    }
+    break;
+  }
+  }
+}
+
 template <typename T>
 bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) {
   if (Found->getLinkageInternal() != From->getLinkageInternal())
@@ -7359,6 +7527,121 @@ ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) {
   return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
 }
 
+ExpectedStmt ASTNodeImporter::VisitRequiresExpr(RequiresExpr* E) {
+  Error Err = Error::success();
+  // auto ToType = importChecked(Err, E->getType());
+  auto RequiresKWLoc = importChecked(Err,E->getRequiresKWLoc());
+  auto RParenLoc = importChecked(Err,E->getRParenLoc());
+  auto RBraceLoc = importChecked(Err,E->getRBraceLoc());
+
+  auto Body = importChecked(Err,E->getBody());
+  auto LParenLoc = importChecked(Err,E->getLParenLoc());
+  if(Err)
+    return std::move(Err);
+  SmallVector<ParmVarDecl*, 4> LocalParameters;
+  if (Error Err = 
ImportArrayChecked(E->getLocalParameters(),LocalParameters.begin()))
+    return std::move(Err);
+  SmallVector<concepts::Requirement*, 4> Requirements;
+  if (Error Err = 
ImportArrayChecked(E->getRequirements(),Requirements.begin()))
+    return std::move(Err);
+  return RequiresExpr::Create(Importer.getToContext(),RequiresKWLoc, Body, 
LParenLoc,
+                    LocalParameters, RParenLoc, Requirements, RBraceLoc);
+}
+
+ExpectedDecl ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl* 
D) {
+  DeclContext *DC, *LexicalDC;
+  Error Err = Error::success();
+  Err = ImportDeclContext(D, DC, LexicalDC);  
+  auto RequiresLoc = importChecked(Err,D->getLocation());
+  return RequiresExprBodyDecl::Create(Importer.getToContext(),DC,RequiresLoc);
+}
+
+ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr* E) {
+  Error Err = Error::success();
+  
+  auto CL = importChecked(Err,E->getConceptReference());
+  auto CSD = importChecked(Err,E->getSpecializationDecl());
+  // auto Satisfaction = importChecked(Err,E->getSatisfaction());  
+  if (Err)
+    return std::move(Err);
+  // E->getDependence();
+  if(E->isValueDependent()) {
+    return ConceptSpecializationExpr::Create(
+      Importer.getToContext(), CL,
+      const_cast<ImplicitConceptSpecializationDecl *>(CSD), nullptr);
+  }
+  const auto& FromSatisfaction = E->getSatisfaction();
+  auto ImportStringRef = [this](const StringRef& FromString) {
+    char* ToDiagMessage = new (Importer.getToContext()) 
char[FromString.size()];
+    std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
+    return StringRef(ToDiagMessage,FromString.size());
+  };
+  ConstraintSatisfaction Satisfaction;
+  Satisfaction.IsSatisfied = FromSatisfaction.IsSatisfied;
+  Satisfaction.ContainsErrors = FromSatisfaction.ContainsErrors;        
+  if (!Satisfaction.IsSatisfied) {
+    for (auto Record = FromSatisfaction.begin(); Record != 
FromSatisfaction.end(); ++Record) {
+      const Expr *ConstraintExpr = Record->first;
+      Expected<Expr *> ToConstraintExpr = import(ConstraintExpr);
+      if(!ToConstraintExpr)
+        return ToConstraintExpr.takeError();
+      if(Record->second.is<Expr*>()) {
+        Expected<Expr *> ToSecondExpr = import(Record->second.get<Expr*>());
+        if(!ToSecondExpr)
+          return ToSecondExpr.takeError();
+        
Satisfaction.Details.emplace_back(ToConstraintExpr.get(),ToSecondExpr.get());
+      } else {
+        std::pair<SourceLocation, StringRef> *pair = Record->second.get<
+          std::pair<SourceLocation, StringRef> *>();
+        Error Err = Error::success();
+
+        auto ToPairFirst = import(pair->first);
+        if(!ToPairFirst)
+          return ToPairFirst.takeError();
+        StringRef ToPairSecond = ImportStringRef(pair->second);
+        Satisfaction.Details.emplace_back(
+        ToConstraintExpr.get(), new(Importer.getToContext()) 
ConstraintSatisfaction::SubstitutionDiagnostic{
+                                  ToPairFirst.get(), ToPairSecond});
+      }
+    }
+  }
+  return ConceptSpecializationExpr::Create(
+    Importer.getToContext(), CL,
+    const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
+}
+
+ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl* D) {
+  // Import the context of this declaration.
+  DeclContext *DC, *LexicalDC;
+  Error Err = Error::success();
+  Err = ImportDeclContext(D, DC, LexicalDC);  
+  auto BeginLocOrErr = importChecked(Err, D->getBeginLoc());
+  auto LocationOrErr = importChecked(Err, D->getLocation());
+  auto NameDeclOrErr = importChecked(Err,D->getDeclName());
+  auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
+  auto ConstraintExpr = importChecked(Err, D->getConstraintExpr());
+  if(Err)
+    return std::move(Err);
+  return ConceptDecl::Create(
+    Importer.getToContext(),DC,
+    LocationOrErr,NameDeclOrErr,
+    ToTemplateParameters,ConstraintExpr);
+}
+
+ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl*
 D) {
+  DeclContext *DC, *LexicalDC;
+  Error Err = Error::success();
+  Err = ImportDeclContext(D, DC, LexicalDC);
+  auto ToSL = importChecked(Err,D->getLocation());
+  if(Err)
+    return std::move(Err);
+  SmallVector<TemplateArgument,2> ToArgs;
+  if(Error Err = ImportTemplateArguments(D->getTemplateArguments(),ToArgs))
+    return std::move(Err);
+
+  return 
ImplicitConceptSpecializationDecl::Create(Importer.getToContext(),DC,ToSL,ToArgs);
+}
+
 ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {
   Error Err = Error::success();
   auto ToType = importChecked(Err, E->getType());
@@ -10584,4 +10867,4 @@ bool ASTImporter::IsStructurallyEquivalent(QualType 
From, QualType To,
       getToContext().getLangOpts(), FromContext, ToContext, NonEquivalentDecls,
       getStructuralEquivalenceKind(*this), false, Complain);
   return Ctx.IsEquivalent(From, To);
-}
+}
\ No newline at end of file

>From 9cb45bbaf96f15531efbed443d46d28846f53e0f Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Tue, 6 May 2025 18:36:49 +0300
Subject: [PATCH 2/8] Fix patch compilation

---
 clang/lib/AST/ASTImporter.cpp | 102 ++++++++++++++--------------------
 1 file changed, 42 insertions(+), 60 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 775e9b83d1fb1..ec1bd5737f9a0 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -68,7 +68,6 @@
 #include <optional>
 #include <type_traits>
 #include <utility>
-#include "ExprConcepts.h"
 
 namespace clang {
 
@@ -741,6 +740,40 @@ namespace clang {
     // that type is declared inside the body of the function.
     // E.g. auto f() { struct X{}; return X(); }
     bool hasReturnTypeDeclaredInside(FunctionDecl *D);
+    
+    Expected<ConstraintSatisfaction> FillConstraintSatisfaction(const 
ASTConstraintSatisfaction& from) {
+      auto ImportStringRef = [this](const StringRef& FromString) {
+        char* ToDiagMessage = new (Importer.getToContext()) 
char[FromString.size()];
+        std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
+        return StringRef(ToDiagMessage,FromString.size());
+      };
+      ConstraintSatisfaction Satisfaction;
+      Satisfaction.IsSatisfied = from.IsSatisfied;
+      Satisfaction.ContainsErrors = from.ContainsErrors;        
+      if (!Satisfaction.IsSatisfied) {
+        using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
+        for (auto &Record : from) {
+          if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>()) {
+            Error Err = Error::success();
+    
+            auto ToPairFirst = import(SubstDiag->first);
+            if(!ToPairFirst)
+              return ToPairFirst.takeError();
+            StringRef ToPairSecond = ImportStringRef(SubstDiag->second);
+            Satisfaction.Details.emplace_back(new (Importer.getToContext())
+              ConstraintSatisfaction::SubstitutionDiagnostic{
+                ToPairFirst.get(), ToPairSecond});
+          } else { 
+            const Expr *ConstraintExpr = Record.dyn_cast<Expr *>();
+            Expected<Expr *> ToConstraintExpr = import(ConstraintExpr);
+            if(!ToConstraintExpr)
+              return ToConstraintExpr.takeError();
+            Satisfaction.Details.emplace_back(ToConstraintExpr.get());
+          }
+        }
+      }
+      return Satisfaction;
+    }
   };
 
 template <typename InContainerTy>
@@ -1193,37 +1226,11 @@ Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement*
       if(ToExpr.get()->isInstantiationDependent())
         return new (Importer.getToContext()) 
concepts::NestedRequirement(ToExpr.get());
       else {
-        ConstraintSatisfaction Satisfaction;
-        Satisfaction.IsSatisfied = FromSatisfaction.IsSatisfied;
-        Satisfaction.ContainsErrors = FromSatisfaction.ContainsErrors;        
-        if (!Satisfaction.IsSatisfied) {
-          for (auto Record = FromSatisfaction.begin(); Record != 
FromSatisfaction.end(); ++Record) {
-            const Expr *ConstraintExpr = Record->first;
-            Expected<Expr *> ToConstraintExpr = import(ConstraintExpr);
-            if(!ToConstraintExpr)
-              return ToConstraintExpr.takeError();
-            if(Record->second.is<Expr*>()) {
-              Expected<Expr *> ToSecondExpr = 
import(Record->second.get<Expr*>());
-              if(!ToSecondExpr)
-                return ToSecondExpr.takeError();
-              
Satisfaction.Details.emplace_back(ToConstraintExpr.get(),ToSecondExpr.get());
-            } else {
-              std::pair<SourceLocation, StringRef> *pair = Record->second.get<
-                std::pair<SourceLocation, StringRef> *>();
-              Error Err = Error::success();
-
-              auto ToPairFirst = import(pair->first);
-              if(!ToPairFirst)
-                return ToPairFirst.takeError();
-              StringRef ToPairSecond = ImportStringRef(pair->second);
-              Satisfaction.Details.emplace_back(
-              ToConstraintExpr.get(), new (Importer.getToContext())
-                ConstraintSatisfaction::SubstitutionDiagnostic{
-                  ToPairFirst.get(), ToPairSecond});
-            }
-          }
+        auto expected_satisfaction = 
FillConstraintSatisfaction(FromSatisfaction);
+        if (!expected_satisfaction) {
+          return expected_satisfaction.takeError();
         }
-        return new (Importer.getToContext()) 
concepts::NestedRequirement(Importer.getToContext(),ToExpr.get(),Satisfaction);
+        return new (Importer.getToContext()) 
concepts::NestedRequirement(Importer.getToContext(),ToExpr.get(), 
*expected_satisfaction);
       }      
     }
     break;
@@ -7576,38 +7583,13 @@ ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializati
     std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
     return StringRef(ToDiagMessage,FromString.size());
   };
-  ConstraintSatisfaction Satisfaction;
-  Satisfaction.IsSatisfied = FromSatisfaction.IsSatisfied;
-  Satisfaction.ContainsErrors = FromSatisfaction.ContainsErrors;        
-  if (!Satisfaction.IsSatisfied) {
-    for (auto Record = FromSatisfaction.begin(); Record != 
FromSatisfaction.end(); ++Record) {
-      const Expr *ConstraintExpr = Record->first;
-      Expected<Expr *> ToConstraintExpr = import(ConstraintExpr);
-      if(!ToConstraintExpr)
-        return ToConstraintExpr.takeError();
-      if(Record->second.is<Expr*>()) {
-        Expected<Expr *> ToSecondExpr = import(Record->second.get<Expr*>());
-        if(!ToSecondExpr)
-          return ToSecondExpr.takeError();
-        
Satisfaction.Details.emplace_back(ToConstraintExpr.get(),ToSecondExpr.get());
-      } else {
-        std::pair<SourceLocation, StringRef> *pair = Record->second.get<
-          std::pair<SourceLocation, StringRef> *>();
-        Error Err = Error::success();
-
-        auto ToPairFirst = import(pair->first);
-        if(!ToPairFirst)
-          return ToPairFirst.takeError();
-        StringRef ToPairSecond = ImportStringRef(pair->second);
-        Satisfaction.Details.emplace_back(
-        ToConstraintExpr.get(), new(Importer.getToContext()) 
ConstraintSatisfaction::SubstitutionDiagnostic{
-                                  ToPairFirst.get(), ToPairSecond});
-      }
-    }
+  auto expected_satisfaction = FillConstraintSatisfaction(FromSatisfaction);
+  if (!expected_satisfaction) {
+    return expected_satisfaction.takeError();
   }
   return ConceptSpecializationExpr::Create(
     Importer.getToContext(), CL,
-    const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
+    const_cast<ImplicitConceptSpecializationDecl *>(CSD), 
&*expected_satisfaction);
 }
 
 ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl* D) {

>From cab401278030eb6d77ef58f3e70d761856e1091d Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Thu, 15 May 2025 15:31:32 +0300
Subject: [PATCH 3/8] Fix non working code:

 - unchecked errors
 - changes Decls were not mapped with helper GetImportedOrCreateDecl
 - SmallVectors were non initialized
---
 clang/lib/AST/ASTImporter.cpp | 83 +++++++++++++++++++----------------
 1 file changed, 44 insertions(+), 39 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index ec1bd5737f9a0..7e090b582386e 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -754,8 +754,6 @@ namespace clang {
         using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
         for (auto &Record : from) {
           if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>()) {
-            Error Err = Error::success();
-    
             auto ToPairFirst = import(SubstDiag->first);
             if(!ToPairFirst)
               return ToPairFirst.takeError();
@@ -1112,6 +1110,9 @@ Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement*
     
   auto ImportSubstitutionDiagnos = [this, &ImportStringRef]
   (concepts::Requirement::SubstitutionDiagnostic* FromDiagnos, Error& 
Err)->concepts::Requirement::SubstitutionDiagnostic* {
+    if (Err) {
+      return nullptr;
+    }
     const auto& ToEntity = ImportStringRef(FromDiagnos->SubstitutedEntity);
     Expected<SourceLocation> ToLoc = import(FromDiagnos->DiagLoc);
     if(!ToLoc) {
@@ -1216,7 +1217,7 @@ Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement*
     const auto& FromSatisfaction = From->getConstraintSatisfaction();
     if(From->hasInvalidConstraint()) {
       const auto& ToConstraintEntity = 
ImportStringRef(From->getInvalidConstraintEntity());
-      auto ToSatisfaction = 
ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),FromSatisfaction);
+      auto* ToSatisfaction = 
ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),FromSatisfaction);
       return new (Importer.getToContext()) 
concepts::NestedRequirement(ToConstraintEntity,ToSatisfaction);
     } else {
       Expected<Expr *> ToExpr = import(From->getConstraintExpr());
@@ -7545,11 +7546,11 @@ ExpectedStmt 
ASTNodeImporter::VisitRequiresExpr(RequiresExpr* E) {
   auto LParenLoc = importChecked(Err,E->getLParenLoc());
   if(Err)
     return std::move(Err);
-  SmallVector<ParmVarDecl*, 4> LocalParameters;
-  if (Error Err = 
ImportArrayChecked(E->getLocalParameters(),LocalParameters.begin()))
+  SmallVector<ParmVarDecl*, 4> LocalParameters(E->getLocalParameters().size());
+  if (Error Err = ImportArrayChecked(E->getLocalParameters(), 
LocalParameters.begin()))
     return std::move(Err);
-  SmallVector<concepts::Requirement*, 4> Requirements;
-  if (Error Err = 
ImportArrayChecked(E->getRequirements(),Requirements.begin()))
+  SmallVector<concepts::Requirement*, 4> 
Requirements(E->getRequirements().size());
+  if (Error Err = ImportArrayChecked(E->getRequirements(), 
Requirements.begin()))
     return std::move(Err);
   return RequiresExpr::Create(Importer.getToContext(),RequiresKWLoc, Body, 
LParenLoc,
                     LocalParameters, RParenLoc, Requirements, RBraceLoc);
@@ -7557,32 +7558,31 @@ ExpectedStmt 
ASTNodeImporter::VisitRequiresExpr(RequiresExpr* E) {
 
 ExpectedDecl ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl* 
D) {
   DeclContext *DC, *LexicalDC;
-  Error Err = Error::success();
-  Err = ImportDeclContext(D, DC, LexicalDC);  
-  auto RequiresLoc = importChecked(Err,D->getLocation());
-  return RequiresExprBodyDecl::Create(Importer.getToContext(),DC,RequiresLoc);
+  Error Err = ImportDeclContext(D, DC, LexicalDC);
+  auto RequiresLoc = importChecked(Err, D->getLocation());
+  if (Err) {
+    return std::move(Err);
+  }
+  RequiresExprBodyDecl *To;
+  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, RequiresLoc))
+    return To;
+  To->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(To);
+  return To;
 }
 
 ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr* E) {
   Error Err = Error::success();
-  
   auto CL = importChecked(Err,E->getConceptReference());
   auto CSD = importChecked(Err,E->getSpecializationDecl());
-  // auto Satisfaction = importChecked(Err,E->getSatisfaction());  
   if (Err)
     return std::move(Err);
-  // E->getDependence();
   if(E->isValueDependent()) {
     return ConceptSpecializationExpr::Create(
       Importer.getToContext(), CL,
       const_cast<ImplicitConceptSpecializationDecl *>(CSD), nullptr);
   }
   const auto& FromSatisfaction = E->getSatisfaction();
-  auto ImportStringRef = [this](const StringRef& FromString) {
-    char* ToDiagMessage = new (Importer.getToContext()) 
char[FromString.size()];
-    std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
-    return StringRef(ToDiagMessage,FromString.size());
-  };
   auto expected_satisfaction = FillConstraintSatisfaction(FromSatisfaction);
   if (!expected_satisfaction) {
     return expected_satisfaction.takeError();
@@ -7594,34 +7594,39 @@ ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializati
 
 ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl* D) {
   // Import the context of this declaration.
-  DeclContext *DC, *LexicalDC;
-  Error Err = Error::success();
-  Err = ImportDeclContext(D, DC, LexicalDC);  
-  auto BeginLocOrErr = importChecked(Err, D->getBeginLoc());
+  DeclContext *DC = nullptr;
+  DeclContext *LexicalDC = nullptr;
+  Error Err = ImportDeclContext(D, DC, LexicalDC);
   auto LocationOrErr = importChecked(Err, D->getLocation());
   auto NameDeclOrErr = importChecked(Err,D->getDeclName());
-  auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
-  auto ConstraintExpr = importChecked(Err, D->getConstraintExpr());
-  if(Err)
+  auto* ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
+  auto* ConstraintExpr = importChecked(Err, D->getConstraintExpr());
+  if(Err) {
     return std::move(Err);
-  return ConceptDecl::Create(
-    Importer.getToContext(),DC,
-    LocationOrErr,NameDeclOrErr,
-    ToTemplateParameters,ConstraintExpr);
+  }
+  ConceptDecl *To;
+  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, 
LocationOrErr, NameDeclOrErr, ToTemplateParameters, ConstraintExpr))
+    return To;
+  To->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(To);
+  return To;
 }
 
 ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl*
 D) {
   DeclContext *DC, *LexicalDC;
-  Error Err = Error::success();
-  Err = ImportDeclContext(D, DC, LexicalDC);
-  auto ToSL = importChecked(Err,D->getLocation());
+  Error Err = ImportDeclContext(D, DC, LexicalDC);
+  auto ToSL = importChecked(Err, D->getLocation());
   if(Err)
     return std::move(Err);
-  SmallVector<TemplateArgument,2> ToArgs;
-  if(Error Err = ImportTemplateArguments(D->getTemplateArguments(),ToArgs))
+  SmallVector<TemplateArgument,2> ToArgs(D->getTemplateArguments().size());
+  if(Error Err = ImportTemplateArguments(D->getTemplateArguments(), ToArgs))
     return std::move(Err);
-
-  return 
ImplicitConceptSpecializationDecl::Create(Importer.getToContext(),DC,ToSL,ToArgs);
+  ImplicitConceptSpecializationDecl *To;
+  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, ToSL, 
ToArgs))
+    return To;
+  To->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(To);
+  return To;
 }
 
 ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {
@@ -7644,8 +7649,8 @@ ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr 
*E) {
 
   Error Err = Error::success();
   auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
-  auto ToSubExpr = importChecked(Err, E->getSubExpr());
-  auto ToWrittenTypeInfo = importChecked(Err, E->getWrittenTypeInfo());
+  auto* ToSubExpr = importChecked(Err, E->getSubExpr());
+  auto* ToWrittenTypeInfo = importChecked(Err, E->getWrittenTypeInfo());
   auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
   auto ToType = importChecked(Err, E->getType());
   if (Err)

>From 4492084b3e536fdbbe9ee01dad097d706ac42d67 Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Wed, 4 Jun 2025 16:08:00 +0300
Subject: [PATCH 4/8] Fix isDependent calculation in ReturnTypeRequirement
 ctor.

---
 clang/include/clang/AST/ExprConcepts.h | 1 +
 clang/lib/AST/ASTConcept.cpp           | 4 ++++
 clang/lib/AST/ASTImporter.cpp          | 3 ++-
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/AST/ExprConcepts.h 
b/clang/include/clang/AST/ExprConcepts.h
index f988d40cf73c3..319c9cb0eee96 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -310,6 +310,7 @@ class ExprRequirement : public Requirement {
       // TODO: Can we maybe not save the whole template parameter list and just
       //  the type constraint? Saving the whole TPL makes it easier to handle 
in
       //  serialization but is less elegant.
+      ReturnTypeRequirement(TemplateParameterList *TPL, bool IsDependent);
       ReturnTypeRequirement(TemplateParameterList *TPL);
 
       bool isDependent() const {
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index c9cfec6bd64b5..91ab66f4639fc 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -156,6 +156,10 @@ 
concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement(
   TypeConstraintInfo.setInt(Dependent ? true : false);
 }
 
+concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement(
+    TemplateParameterList *TPL, bool IsDependent)
+    : TypeConstraintInfo(TPL, IsDependent) {}
+
 concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T)
     : Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
                   T->getType()->containsUnexpandedParameterPack(),
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 7e090b582386e..6f73132d8e9c3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1176,6 +1176,7 @@ Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement*
       auto& FromTypeRequirement = From->getReturnTypeRequirement();
 
       if(FromTypeRequirement.isTypeConstraint()) {
+        const bool IsDependent = FromTypeRequirement.isDependent();
         auto ParamsOrErr = 
import(FromTypeRequirement.getTypeConstraintTemplateParameterList());
         if (!ParamsOrErr)
           return ParamsOrErr.takeError();
@@ -1186,7 +1187,7 @@ Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement*
             return ExpectSubstitutedConstraintExpr.takeError();
           SubstitutedConstraintExpr = ExpectSubstitutedConstraintExpr.get();
         }
-        Req.emplace(ParamsOrErr.get());
+        Req.emplace(ParamsOrErr.get(), IsDependent);
       }      
       else if(FromTypeRequirement.isSubstitutionFailure()) {
         Error Err = Error::success();

>From 3380e263eb06287e8c36ca88c60b1c38ec1ad0ae Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Wed, 4 Jun 2025 16:11:16 +0300
Subject: [PATCH 5/8] Add newly imported declarations into imported cache

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

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6f73132d8e9c3..0a1e39e484f84 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -7569,7 +7569,7 @@ ExpectedDecl 
ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl* D)
     return To;
   To->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(To);
-  return To;
+  return Importer.MapImported(D, To);
 }
 
 ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr* E) {
@@ -7610,7 +7610,7 @@ ExpectedDecl 
ASTNodeImporter::VisitConceptDecl(ConceptDecl* D) {
     return To;
   To->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(To);
-  return To;
+  return Importer.MapImported(D, To);
 }
 
 ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl*
 D) {
@@ -7627,7 +7627,7 @@ ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitCon
     return To;
   To->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(To);
-  return To;
+  return Importer.MapImported(D, To);
 }
 
 ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {

>From 8ba5bcf522cc7d01b36613c1e0c6f54e2019c84c Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Mon, 9 Jun 2025 10:04:44 +0300
Subject: [PATCH 6/8] Add debug build folder to ignore

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index a84268a7f6863..1f4a07d4b9e50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,7 @@
 
 # Nested build directory
 /build*
+/debug*
 
 
#==============================================================================#
 # Explicit files to ignore (only matches one).

>From 0839d38c3a227aa4d46f751ba97b0f57a6fb27f4 Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Mon, 9 Jun 2025 10:05:13 +0300
Subject: [PATCH 7/8] Revert "Add newly imported declarations into imported
 cache"

This reverts commit 3380e263eb06287e8c36ca88c60b1c38ec1ad0ae.
---
 clang/lib/AST/ASTImporter.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 0a1e39e484f84..6f73132d8e9c3 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -7569,7 +7569,7 @@ ExpectedDecl 
ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl* D)
     return To;
   To->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(To);
-  return Importer.MapImported(D, To);
+  return To;
 }
 
 ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr* E) {
@@ -7610,7 +7610,7 @@ ExpectedDecl 
ASTNodeImporter::VisitConceptDecl(ConceptDecl* D) {
     return To;
   To->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(To);
-  return Importer.MapImported(D, To);
+  return To;
 }
 
 ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl*
 D) {
@@ -7627,7 +7627,7 @@ ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitCon
     return To;
   To->setLexicalDeclContext(LexicalDC);
   LexicalDC->addDeclInternal(To);
-  return Importer.MapImported(D, To);
+  return To;
 }
 
 ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {

>From d5164739f9a968d8a569350d3332d1be41b7421f Mon Sep 17 00:00:00 2001
From: Konstantin Ganenko <ganenk...@yandex-team.ru>
Date: Mon, 9 Jun 2025 11:40:08 +0300
Subject: [PATCH 8/8] Reformat changes.

---
 clang/lib/AST/ASTImporter.cpp | 434 +++++++++++++++++-----------------
 1 file changed, 214 insertions(+), 220 deletions(-)

diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6f73132d8e9c3..87d6475e1b9ce 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -495,6 +495,16 @@ namespace clang {
     Expected<InheritedConstructor>
     ImportInheritedConstructor(const InheritedConstructor &From);
 
+    StringRef ImportASTStringRef(StringRef FromStr);
+    Error ImportConstraintSatisfaction(const ASTConstraintSatisfaction 
&FromSat,
+                                       ConstraintSatisfaction &ToSat);
+    Expected<concepts::Requirement *>
+    ImportTypeRequirement(concepts::TypeRequirement *From);
+    Expected<concepts::Requirement *>
+    ImportExprRequirement(concepts::ExprRequirement *From);
+    Expected<concepts::Requirement *>
+    ImportNestedRequirement(concepts::NestedRequirement *From);
+
     template <typename T>
     bool hasSameVisibilityContextAndLinkage(T *Found, T *From);
 
@@ -740,38 +750,6 @@ namespace clang {
     // that type is declared inside the body of the function.
     // E.g. auto f() { struct X{}; return X(); }
     bool hasReturnTypeDeclaredInside(FunctionDecl *D);
-    
-    Expected<ConstraintSatisfaction> FillConstraintSatisfaction(const 
ASTConstraintSatisfaction& from) {
-      auto ImportStringRef = [this](const StringRef& FromString) {
-        char* ToDiagMessage = new (Importer.getToContext()) 
char[FromString.size()];
-        std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
-        return StringRef(ToDiagMessage,FromString.size());
-      };
-      ConstraintSatisfaction Satisfaction;
-      Satisfaction.IsSatisfied = from.IsSatisfied;
-      Satisfaction.ContainsErrors = from.ContainsErrors;        
-      if (!Satisfaction.IsSatisfied) {
-        using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
-        for (auto &Record : from) {
-          if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>()) {
-            auto ToPairFirst = import(SubstDiag->first);
-            if(!ToPairFirst)
-              return ToPairFirst.takeError();
-            StringRef ToPairSecond = ImportStringRef(SubstDiag->second);
-            Satisfaction.Details.emplace_back(new (Importer.getToContext())
-              ConstraintSatisfaction::SubstitutionDiagnostic{
-                ToPairFirst.get(), ToPairSecond});
-          } else { 
-            const Expr *ConstraintExpr = Record.dyn_cast<Expr *>();
-            Expected<Expr *> ToConstraintExpr = import(ConstraintExpr);
-            if(!ToConstraintExpr)
-              return ToConstraintExpr.takeError();
-            Satisfaction.Details.emplace_back(ToConstraintExpr.get());
-          }
-        }
-      }
-      return Satisfaction;
-    }
   };
 
 template <typename InContainerTy>
@@ -1076,6 +1054,177 @@ Expected<ConceptReference *> 
ASTNodeImporter::import(ConceptReference *From) {
   return ConceptRef;
 }
 
+StringRef ASTNodeImporter::ImportASTStringRef(StringRef FromStr) {
+  char *ToStore = new (Importer.getToContext()) char[FromStr.size()];
+  std::copy(FromStr.begin(), FromStr.end(), ToStore);
+  return StringRef(ToStore, FromStr.size());
+}
+
+Error ASTNodeImporter::ImportConstraintSatisfaction(
+    const ASTConstraintSatisfaction &FromSat, ConstraintSatisfaction &ToSat) {
+  ToSat.IsSatisfied = FromSat.IsSatisfied;
+  ToSat.ContainsErrors = FromSat.ContainsErrors;
+  if (!ToSat.IsSatisfied) {
+    for (auto Record = FromSat.begin(); Record != FromSat.end(); ++Record) {
+      if (Expr *E = Record->dyn_cast<Expr *>()) {
+        ExpectedExpr ToSecondExpr = import(E);
+        if (!ToSecondExpr)
+          return ToSecondExpr.takeError();
+        ToSat.Details.emplace_back(ToSecondExpr.get());
+      } else {
+        auto Pair = Record->dyn_cast<std::pair<SourceLocation, StringRef> *>();
+
+        ExpectedSLoc ToPairFirst = import(Pair->first);
+        if (!ToPairFirst)
+          return ToPairFirst.takeError();
+        StringRef ToPairSecond = ImportASTStringRef(Pair->second);
+        ToSat.Details.emplace_back(
+            new (Importer.getToContext())
+                ConstraintSatisfaction::SubstitutionDiagnostic{
+                    ToPairFirst.get(), ToPairSecond});
+      }
+    }
+  }
+  return Error::success();
+}
+
+template <>
+Expected<concepts::Requirement::SubstitutionDiagnostic *>
+ASTNodeImporter::import(
+    concepts::Requirement::SubstitutionDiagnostic *FromDiag) {
+  StringRef ToEntity = ImportASTStringRef(FromDiag->SubstitutedEntity);
+  ExpectedSLoc ToLoc = import(FromDiag->DiagLoc);
+  if (!ToLoc)
+    return ToLoc.takeError();
+  StringRef ToDiagMessage = ImportASTStringRef(FromDiag->DiagMessage);
+  return new (Importer.getToContext())
+      concepts::Requirement::SubstitutionDiagnostic{ToEntity, ToLoc.get(),
+                                                    ToDiagMessage};
+}
+
+Expected<concepts::Requirement *>
+ASTNodeImporter::ImportTypeRequirement(concepts::TypeRequirement *From) {
+  using namespace concepts;
+
+  if (From->isSubstitutionFailure()) {
+    auto DiagOrErr = import(From->getSubstitutionDiagnostic());
+    if (!DiagOrErr)
+      return DiagOrErr.takeError();
+    return new (Importer.getToContext()) TypeRequirement(*DiagOrErr);
+  } else {
+    Expected<TypeSourceInfo *> ToType = import(From->getType());
+    if (!ToType)
+      return ToType.takeError();
+    return new (Importer.getToContext()) TypeRequirement(*ToType);
+  }
+}
+
+Expected<concepts::Requirement *>
+ASTNodeImporter::ImportExprRequirement(concepts::ExprRequirement *From) {
+  using namespace concepts;
+
+  bool IsRKSimple = From->getKind() == Requirement::RK_Simple;
+  ExprRequirement::SatisfactionStatus Status = From->getSatisfactionStatus();
+
+  std::optional<ExprRequirement::ReturnTypeRequirement> Req;
+  ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
+
+  if (IsRKSimple) {
+    Req.emplace();
+  } else {
+    const ExprRequirement::ReturnTypeRequirement &FromTypeRequirement =
+        From->getReturnTypeRequirement();
+
+    if (FromTypeRequirement.isTypeConstraint()) {
+      const bool IsDependent = FromTypeRequirement.isDependent();
+      auto ParamsOrErr =
+          import(FromTypeRequirement.getTypeConstraintTemplateParameterList());
+      if (!ParamsOrErr)
+        return ParamsOrErr.takeError();
+      if (Status >= ExprRequirement::SS_ConstraintsNotSatisfied) {
+        auto SubstConstraintExprOrErr =
+            import(From->getReturnTypeRequirementSubstitutedConstraintExpr());
+        if (!SubstConstraintExprOrErr)
+          return SubstConstraintExprOrErr.takeError();
+        SubstitutedConstraintExpr = SubstConstraintExprOrErr.get();
+      }
+      Req.emplace(ParamsOrErr.get(), IsDependent);
+    } else if (FromTypeRequirement.isSubstitutionFailure()) {
+      auto DiagOrErr = import(FromTypeRequirement.getSubstitutionDiagnostic());
+      if (DiagOrErr)
+        return DiagOrErr.takeError();
+      Req.emplace(DiagOrErr.get());
+    } else {
+      Req.emplace();
+    }
+  }
+
+  ExpectedSLoc NoexceptLocOrErr = import(From->getNoexceptLoc());
+  if (!NoexceptLocOrErr)
+    return NoexceptLocOrErr.takeError();
+
+  if (Status == ExprRequirement::SS_ExprSubstitutionFailure) {
+    auto DiagOrErr = import(From->getExprSubstitutionDiagnostic());
+    if (!DiagOrErr)
+      return DiagOrErr.takeError();
+    return new (Importer.getToContext()) ExprRequirement(
+        *DiagOrErr, IsRKSimple, *NoexceptLocOrErr, std::move(*Req));
+  } else {
+    Expected<Expr *> ExprOrErr = import(From->getExpr());
+    if (!ExprOrErr)
+      return ExprOrErr.takeError();
+    return new (Importer.getToContext()) concepts::ExprRequirement(
+        *ExprOrErr, IsRKSimple, *NoexceptLocOrErr, std::move(*Req), Status,
+        SubstitutedConstraintExpr);
+  }
+}
+
+Expected<concepts::Requirement *>
+ASTNodeImporter::ImportNestedRequirement(concepts::NestedRequirement *From) {
+  using namespace concepts;
+
+  const ASTConstraintSatisfaction &FromSatisfaction =
+      From->getConstraintSatisfaction();
+  if (From->hasInvalidConstraint()) {
+    StringRef ToEntity = 
ImportASTStringRef(From->getInvalidConstraintEntity());
+    ASTConstraintSatisfaction *ToSatisfaction =
+        ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),
+                                           FromSatisfaction);
+    return new (Importer.getToContext())
+        NestedRequirement(ToEntity, ToSatisfaction);
+  } else {
+    ExpectedExpr ToExpr = import(From->getConstraintExpr());
+    if (!ToExpr)
+      return ToExpr.takeError();
+    if (ToExpr.get()->isInstantiationDependent()) {
+      return new (Importer.getToContext()) NestedRequirement(ToExpr.get());
+    } else {
+      ConstraintSatisfaction Satisfaction;
+      if (Error Err =
+              ImportConstraintSatisfaction(FromSatisfaction, Satisfaction))
+        return std::move(Err);
+      return new (Importer.getToContext()) NestedRequirement(
+          Importer.getToContext(), ToExpr.get(), Satisfaction);
+    }
+  }
+}
+
+template <>
+Expected<concepts::Requirement *>
+ASTNodeImporter::import(concepts::Requirement *FromRequire) {
+  switch (FromRequire->getKind()) {
+  case concepts::Requirement::RequirementKind::RK_Type:
+    return ImportTypeRequirement(cast<concepts::TypeRequirement>(FromRequire));
+  case concepts::Requirement::RequirementKind::RK_Compound:
+  case concepts::Requirement::RequirementKind::RK_Simple:
+    return ImportExprRequirement(cast<concepts::ExprRequirement>(FromRequire));
+  case concepts::Requirement::RequirementKind::RK_Nested:
+    return ImportNestedRequirement(
+        cast<concepts::NestedRequirement>(FromRequire));
+  }
+  llvm_unreachable("Unhandled requirement kind");
+}
+
 template <>
 Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
   ValueDecl *Var = nullptr;
@@ -1100,146 +1249,6 @@ Expected<LambdaCapture> ASTNodeImporter::import(const 
LambdaCapture &From) {
       EllipsisLoc);
 }
 
-template<>
-Expected<concepts::Requirement*> 
ASTNodeImporter::import(concepts::Requirement* FromRequire) {
-  auto ImportStringRef = [this](const StringRef& FromString) {
-      char* ToDiagMessage = new (Importer.getToContext()) 
char[FromString.size()];
-      std::copy(FromString.begin(),FromString.end(),ToDiagMessage);
-      return StringRef(ToDiagMessage,FromString.size());
-    };
-    
-  auto ImportSubstitutionDiagnos = [this, &ImportStringRef]
-  (concepts::Requirement::SubstitutionDiagnostic* FromDiagnos, Error& 
Err)->concepts::Requirement::SubstitutionDiagnostic* {
-    if (Err) {
-      return nullptr;
-    }
-    const auto& ToEntity = ImportStringRef(FromDiagnos->SubstitutedEntity);
-    Expected<SourceLocation> ToLoc = import(FromDiagnos->DiagLoc);
-    if(!ToLoc) {
-      Err = ToLoc.takeError();
-      return nullptr;
-    }
-    const auto& ToDiagMessage =  ImportStringRef(FromDiagnos->DiagMessage);
-    return new (Importer.getToContext()) 
concepts::Requirement::SubstitutionDiagnostic{
-      ToEntity,
-      ToLoc.get(),
-      ToDiagMessage};
-  };
-  switch (FromRequire->getKind()) {
-  case concepts::Requirement::RequirementKind::RK_Type: {
-    auto *From = cast<concepts::TypeRequirement>(FromRequire);
-    if(From->isSubstitutionFailure())
-    {
-      // Should we return Error directly if TypeRequirement 
isSubstitutionFailure?
-      Error Err = Error::success();
-      auto Diagnos = 
ImportSubstitutionDiagnos(From->getSubstitutionDiagnostic(),Err);
-      if (Err)
-        return std::move(Err);
-      return new (Importer.getToContext()) concepts::TypeRequirement(Diagnos);
-    }
-    else {
-      Expected<TypeSourceInfo *> ToType = import(From->getType());
-      if(!ToType)
-        return ToType.takeError();
-      return new (Importer.getToContext()) 
concepts::TypeRequirement(ToType.get());
-    }
-    break;
-  }
-  case concepts::Requirement::RequirementKind::RK_Compound: 
-  case concepts::Requirement::RequirementKind::RK_Simple: {
-    const auto *From = cast<concepts::ExprRequirement>(FromRequire);
-    
-    auto Status = From->getSatisfactionStatus();
-    llvm::PointerUnion<concepts::Requirement::SubstitutionDiagnostic *, Expr 
*> E;
-    if (Status == concepts::ExprRequirement::SS_ExprSubstitutionFailure) {
-      Error Err = Error::success();
-      E = ImportSubstitutionDiagnos(From->getExprSubstitutionDiagnostic(),Err);
-      if (Err)
-        return std::move(Err);
-    } else {
-      auto ExpectE = import(From->getExpr());
-      if (!ExpectE)
-        return ExpectE.takeError();
-      E = ExpectE.get();
-    }
-
-    std::optional<concepts::ExprRequirement::ReturnTypeRequirement> Req;
-    ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;
-    SourceLocation NoexceptLoc;
-    bool IsRKSimple = FromRequire->getKind() == 
concepts::Requirement::RK_Simple;
-    if (IsRKSimple) {
-      Req.emplace();
-    } else {
-      auto NoexceptLoc = import(From->getNoexceptLoc());
-      if(!NoexceptLoc)
-        return NoexceptLoc.takeError();
-      auto& FromTypeRequirement = From->getReturnTypeRequirement();
-
-      if(FromTypeRequirement.isTypeConstraint()) {
-        const bool IsDependent = FromTypeRequirement.isDependent();
-        auto ParamsOrErr = 
import(FromTypeRequirement.getTypeConstraintTemplateParameterList());
-        if (!ParamsOrErr)
-          return ParamsOrErr.takeError();
-        if (Status >=
-          concepts::ExprRequirement::SS_ConstraintsNotSatisfied) {
-          auto ExpectSubstitutedConstraintExpr = 
import(From->getReturnTypeRequirementSubstitutedConstraintExpr());
-          if (!ExpectSubstitutedConstraintExpr)
-            return ExpectSubstitutedConstraintExpr.takeError();
-          SubstitutedConstraintExpr = ExpectSubstitutedConstraintExpr.get();
-        }
-        Req.emplace(ParamsOrErr.get(), IsDependent);
-      }      
-      else if(FromTypeRequirement.isSubstitutionFailure()) {
-        Error Err = Error::success();
-        concepts::Requirement::SubstitutionDiagnostic *ToDiagnos =
-            ImportSubstitutionDiagnos(
-                FromTypeRequirement.getSubstitutionDiagnostic(), Err);
-        if (Err)
-          return std::move(Err);
-       Req.emplace(ToDiagnos);
-      }
-      else {
-        Req.emplace();
-      }      
-    }
-    if (Expr *Ex = E.dyn_cast<Expr *>())
-      return new (Importer.getToContext()) concepts::ExprRequirement(
-              Ex, IsRKSimple, NoexceptLoc,
-              std::move(*Req), Status, SubstitutedConstraintExpr);
-    else
-      return new (Importer.getToContext()) concepts::ExprRequirement(
-              E.get<concepts::Requirement::SubstitutionDiagnostic *>(),
-              IsRKSimple, NoexceptLoc,
-              std::move(*Req));
-    break;
-  }
-  case concepts::Requirement::RequirementKind::RK_Nested: {
-    auto *From = cast<concepts::NestedRequirement>(FromRequire);
-    const auto& FromSatisfaction = From->getConstraintSatisfaction();
-    if(From->hasInvalidConstraint()) {
-      const auto& ToConstraintEntity = 
ImportStringRef(From->getInvalidConstraintEntity());
-      auto* ToSatisfaction = 
ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),FromSatisfaction);
-      return new (Importer.getToContext()) 
concepts::NestedRequirement(ToConstraintEntity,ToSatisfaction);
-    } else {
-      Expected<Expr *> ToExpr = import(From->getConstraintExpr());
-      if(!ToExpr)
-        return ToExpr.takeError();
-      // FromSatisfaction.IsSatisfied;
-      if(ToExpr.get()->isInstantiationDependent())
-        return new (Importer.getToContext()) 
concepts::NestedRequirement(ToExpr.get());
-      else {
-        auto expected_satisfaction = 
FillConstraintSatisfaction(FromSatisfaction);
-        if (!expected_satisfaction) {
-          return expected_satisfaction.takeError();
-        }
-        return new (Importer.getToContext()) 
concepts::NestedRequirement(Importer.getToContext(),ToExpr.get(), 
*expected_satisfaction);
-      }      
-    }
-    break;
-  }
-  }
-}
-
 template <typename T>
 bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) {
   if (Found->getLinkageInternal() != From->getLinkageInternal())
@@ -7538,38 +7547,33 @@ ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) {
 
 ExpectedStmt ASTNodeImporter::VisitRequiresExpr(RequiresExpr* E) {
   Error Err = Error::success();
-  // auto ToType = importChecked(Err, E->getType());
-  auto RequiresKWLoc = importChecked(Err,E->getRequiresKWLoc());
-  auto RParenLoc = importChecked(Err,E->getRParenLoc());
-  auto RBraceLoc = importChecked(Err,E->getRBraceLoc());
+  auto RequiresKWLoc = importChecked(Err, E->getRequiresKWLoc());
+  auto RParenLoc = importChecked(Err, E->getRParenLoc());
+  auto RBraceLoc = importChecked(Err, E->getRBraceLoc());
 
-  auto Body = importChecked(Err,E->getBody());
-  auto LParenLoc = importChecked(Err,E->getLParenLoc());
-  if(Err)
+  auto Body = importChecked(Err, E->getBody());
+  auto LParenLoc = importChecked(Err, E->getLParenLoc());
+  if (Err)
     return std::move(Err);
   SmallVector<ParmVarDecl*, 4> LocalParameters(E->getLocalParameters().size());
   if (Error Err = ImportArrayChecked(E->getLocalParameters(), 
LocalParameters.begin()))
     return std::move(Err);
-  SmallVector<concepts::Requirement*, 4> 
Requirements(E->getRequirements().size());
+  SmallVector<concepts::Requirement *, 4> Requirements(
+      E->getRequirements().size());
   if (Error Err = ImportArrayChecked(E->getRequirements(), 
Requirements.begin()))
     return std::move(Err);
-  return RequiresExpr::Create(Importer.getToContext(),RequiresKWLoc, Body, 
LParenLoc,
-                    LocalParameters, RParenLoc, Requirements, RBraceLoc);
+  return RequiresExpr::Create(Importer.getToContext(), RequiresKWLoc, Body,
+                              LParenLoc, LocalParameters, RParenLoc,
+                              Requirements, RBraceLoc);
 }
 
 ExpectedDecl ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl* 
D) {
   DeclContext *DC, *LexicalDC;
   Error Err = ImportDeclContext(D, DC, LexicalDC);
   auto RequiresLoc = importChecked(Err, D->getLocation());
-  if (Err) {
+  if (Err)
     return std::move(Err);
-  }
-  RequiresExprBodyDecl *To;
-  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, RequiresLoc))
-    return To;
-  To->setLexicalDeclContext(LexicalDC);
-  LexicalDC->addDeclInternal(To);
-  return To;
+  return RequiresExprBodyDecl::Create(Importer.getToContext(), DC, 
RequiresLoc);
 }
 
 ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr* E) {
@@ -7578,56 +7582,46 @@ ExpectedStmt 
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializati
   auto CSD = importChecked(Err,E->getSpecializationDecl());
   if (Err)
     return std::move(Err);
-  if(E->isValueDependent()) {
+  if (E->isValueDependent())
     return ConceptSpecializationExpr::Create(
       Importer.getToContext(), CL,
       const_cast<ImplicitConceptSpecializationDecl *>(CSD), nullptr);
-  }
-  const auto& FromSatisfaction = E->getSatisfaction();
-  auto expected_satisfaction = FillConstraintSatisfaction(FromSatisfaction);
-  if (!expected_satisfaction) {
-    return expected_satisfaction.takeError();
-  }
+  ConstraintSatisfaction Satisfaction;
+  if (Error Err =
+          ImportConstraintSatisfaction(E->getSatisfaction(), Satisfaction))
+    return std::move(Err);
   return ConceptSpecializationExpr::Create(
-    Importer.getToContext(), CL,
-    const_cast<ImplicitConceptSpecializationDecl *>(CSD), 
&*expected_satisfaction);
+      Importer.getToContext(), CL,
+      const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
 }
 
 ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl* D) {
-  // Import the context of this declaration.
-  DeclContext *DC = nullptr;
-  DeclContext *LexicalDC = nullptr;
+  DeclContext *DC, *LexicalDC;
   Error Err = ImportDeclContext(D, DC, LexicalDC);
   auto LocationOrErr = importChecked(Err, D->getLocation());
   auto NameDeclOrErr = importChecked(Err,D->getDeclName());
-  auto* ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
-  auto* ConstraintExpr = importChecked(Err, D->getConstraintExpr());
-  if(Err) {
+  auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
+  auto ConstraintExpr = importChecked(Err, D->getConstraintExpr());
+  if (Err)
     return std::move(Err);
-  }
-  ConceptDecl *To;
-  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, 
LocationOrErr, NameDeclOrErr, ToTemplateParameters, ConstraintExpr))
-    return To;
-  To->setLexicalDeclContext(LexicalDC);
-  LexicalDC->addDeclInternal(To);
-  return To;
+
+  return ConceptDecl::Create(Importer.getToContext(), DC, LocationOrErr,
+                             NameDeclOrErr, ToTemplateParameters,
+                             ConstraintExpr);
 }
 
 ExpectedDecl 
ASTNodeImporter::VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl*
 D) {
   DeclContext *DC, *LexicalDC;
   Error Err = ImportDeclContext(D, DC, LexicalDC);
   auto ToSL = importChecked(Err, D->getLocation());
-  if(Err)
+  if (Err)
     return std::move(Err);
+
   SmallVector<TemplateArgument,2> ToArgs(D->getTemplateArguments().size());
-  if(Error Err = ImportTemplateArguments(D->getTemplateArguments(), ToArgs))
+  if (Error Err = ImportTemplateArguments(D->getTemplateArguments(), ToArgs))
     return std::move(Err);
-  ImplicitConceptSpecializationDecl *To;
-  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, ToSL, 
ToArgs))
-    return To;
-  To->setLexicalDeclContext(LexicalDC);
-  LexicalDC->addDeclInternal(To);
-  return To;
+  return ImplicitConceptSpecializationDecl::Create(Importer.getToContext(), DC,
+                                                   ToSL, ToArgs);
 }
 
 ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to