[clang] Ast importer visitors (PR #138838)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 7 02:59:14 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (ganenkokb-yandex)
<details>
<summary>Changes</summary>
I've rebased commit from [Evianaive](https://github.com/Evianaive/llvm-project/commits?author=Evianaive) and compiled it.
I hope it will speed up fix for #<!-- -->129393.
---
Full diff: https://github.com/llvm/llvm-project/pull/138838.diff
1 Files Affected:
- (modified) clang/lib/AST/ASTImporter.cpp (+266-1)
``````````diff
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index b481ad5df667e..cff0050208784 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -564,6 +564,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 +683,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
@@ -735,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>
@@ -1063,6 +1102,142 @@ 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 {
+ 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())
@@ -7322,6 +7497,96 @@ 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());
+ };
+ auto expected_satisfaction = FillConstraintSatisfaction(FromSatisfaction);
+ if (!expected_satisfaction) {
+ return expected_satisfaction.takeError();
+ }
+ return ConceptSpecializationExpr::Create(
+ Importer.getToContext(), CL,
+ const_cast<ImplicitConceptSpecializationDecl *>(CSD), &*expected_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());
@@ -10547,4 +10812,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
``````````
</details>
https://github.com/llvm/llvm-project/pull/138838
More information about the cfe-commits
mailing list