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