llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Ding Fei (danix800) <details> <summary>Changes</summary> Related nodes including: - ConceptDecl - RequiresExprBodyDecl - ImplicitConceptSpecializationDecl - RequiresExpr - ConceptSpecializationExpr - concepts::Requirement - concepts::ExprRequirement - concepts::NestedRequirement - concepts::TypeRequirement - concepts::Requirement::ReturnTypeRequirement - concepts::Requirement::SubstitutionDiagnostic --- Patch is 27.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/104731.diff 5 Files Affected: - (modified) clang/include/clang/AST/ExprConcepts.h (+31-1) - (modified) clang/lib/AST/ASTImporter.cpp (+265) - (modified) clang/lib/AST/ExprConcepts.cpp (+98-8) - (modified) clang/lib/Sema/SemaConcept.cpp (-58) - (modified) clang/unittests/AST/ASTImporterTest.cpp (+43) ``````````diff diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h index 29913fd84c58b4..7c8972c0ced0bb 100644 --- a/clang/include/clang/AST/ExprConcepts.h +++ b/clang/include/clang/AST/ExprConcepts.h @@ -59,11 +59,21 @@ class ConceptSpecializationExpr final : public Expr { ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction); + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); + + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction, + bool Dependent, + bool ContainsUnexpandedParameterPack); ConceptSpecializationExpr(EmptyShell Empty); public: @@ -72,13 +82,25 @@ class ConceptSpecializationExpr final : public Expr { ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); + static ConceptSpecializationExpr * + Create(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction); + static ConceptSpecializationExpr * Create(const ASTContext &C, ConceptReference *ConceptRef, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); + static ConceptSpecializationExpr * + Create(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction, bool Dependent, + bool ContainsUnexpandedParameterPack); + ArrayRef<TemplateArgument> getTemplateArguments() const { + assert(hasSpecializationDecl() && "Template Argument Decl not initialized"); return SpecDecl->getTemplateArguments(); } @@ -113,8 +135,10 @@ class ConceptSpecializationExpr final : public Expr { return ConceptRef->getConceptNameInfo(); } + bool hasSpecializationDecl() const { return SpecDecl != nullptr; } + const ImplicitConceptSpecializationDecl *getSpecializationDecl() const { - assert(SpecDecl && "Template Argument Decl not initialized"); + assert(hasSpecializationDecl() && "Template Argument Decl not initialized"); return SpecDecl; } @@ -445,6 +469,12 @@ class NestedRequirement : public Requirement { "constructed with a ConstraintSatisfaction object"); } + NestedRequirement(Expr *Constraint, + const ASTConstraintSatisfaction *Satisfaction) + : Requirement(RK_Nested, Constraint->isInstantiationDependent(), + Constraint->containsUnexpandedParameterPack()), + Constraint(Constraint), Satisfaction(Satisfaction) {} + NestedRequirement(ASTContext &C, Expr *Constraint, const ConstraintSatisfaction &Satisfaction) : Requirement(RK_Nested, Constraint->isInstantiationDependent(), diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 3bc0a647ebf94f..0910f854e3e1c3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -574,6 +574,10 @@ namespace clang { ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D); ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D); + ExpectedDecl VisitConceptDecl(ConceptDecl *D); + ExpectedDecl VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); + ExpectedDecl VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D); // Importing statements ExpectedStmt VisitStmt(Stmt *S); @@ -690,6 +694,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 @@ -1072,6 +1078,136 @@ Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) { EllipsisLoc); } +template <> +Expected<concepts::Requirement::SubstitutionDiagnostic *> +ASTNodeImporter::import(concepts::Requirement::SubstitutionDiagnostic *SD) { + ExpectedSLoc ToDiagLoc = Importer.Import(SD->DiagLoc); + if (!ToDiagLoc) + return ToDiagLoc.takeError(); + + auto &ToC = Importer.ToContext; + return new (ToC) concepts::Requirement::SubstitutionDiagnostic{ + ToC.backupStr(SD->SubstitutedEntity), *ToDiagLoc, + ToC.backupStr(SD->DiagMessage)}; +} + +template <> +Expected<concepts::ExprRequirement::ReturnTypeRequirement> +ASTNodeImporter::import( + const concepts::ExprRequirement::ReturnTypeRequirement &R) { + if (R.isEmpty()) + return concepts::ExprRequirement::ReturnTypeRequirement{}; + + if (R.isSubstitutionFailure()) { + auto ToSubstDiagOrErr = import(R.getSubstitutionDiagnostic()); + if (!ToSubstDiagOrErr) + return ToSubstDiagOrErr.takeError(); + return concepts::ExprRequirement::ReturnTypeRequirement(*ToSubstDiagOrErr); + } + + auto TPLOrErr = import(R.getTypeConstraintTemplateParameterList()); + if (!TPLOrErr) + return TPLOrErr.takeError(); + + return concepts::ExprRequirement::ReturnTypeRequirement(*TPLOrErr); +} + +template <> +Expected<concepts::ExprRequirement *> +ASTNodeImporter::import(concepts::ExprRequirement *R) { + SourceLocation ToNoexceptLoc; + if (R->hasNoexceptRequirement()) { + auto ToNoexceptLocOrErr = Importer.Import(R->getNoexceptLoc()); + if (!ToNoexceptLocOrErr) + return ToNoexceptLocOrErr.takeError(); + ToNoexceptLoc = *ToNoexceptLocOrErr; + } + + auto RetTypeRequirementOrErr = import(R->getReturnTypeRequirement()); + if (!RetTypeRequirementOrErr) + return RetTypeRequirementOrErr.takeError(); + + auto RetTypeRequirement = *RetTypeRequirementOrErr; + auto &ToC = Importer.ToContext; + if (R->isExprSubstitutionFailure()) { + auto ToSubstDiagOrErr = import(R->getExprSubstitutionDiagnostic()); + if (!ToSubstDiagOrErr) + return ToSubstDiagOrErr.takeError(); + + return new (ToC) concepts::ExprRequirement( + *ToSubstDiagOrErr, R->isSimple(), ToNoexceptLoc, RetTypeRequirement); + } + + auto ToExprOrErr = Importer.Import(R->getExpr()); + if (!ToExprOrErr) + return ToExprOrErr.takeError(); + + ConceptSpecializationExpr *ToCSE = nullptr; + if (R->getSatisfactionStatus() >= + concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure) { + auto ToCSEOrErr = + import(R->getReturnTypeRequirementSubstitutedConstraintExpr()); + if (!ToCSEOrErr) + return ToCSEOrErr.takeError(); + ToCSE = *ToCSEOrErr; + } + + return new (ToC) concepts::ExprRequirement(*ToExprOrErr, R->isSimple(), + ToNoexceptLoc, RetTypeRequirement, + R->getSatisfactionStatus(), ToCSE); +} + +template <> +Expected<concepts::NestedRequirement *> +ASTNodeImporter::import(concepts::NestedRequirement *R) { + auto &ToC = Importer.ToContext; + auto *ToASTSat = + ASTConstraintSatisfaction::Rebuild(ToC, R->getConstraintSatisfaction()); + + if (R->hasInvalidConstraint()) { + R->getInvalidConstraintEntity(); + return new (ToC) concepts::NestedRequirement( + ToC.backupStr(R->getInvalidConstraintEntity()), ToASTSat); + } + + Expr *FromExpr = R->getConstraintExpr(); + auto ToExprOrErr = Importer.Import(FromExpr); + if (!ToExprOrErr) + return ToExprOrErr.takeError(); + + return new (ToC) concepts::NestedRequirement( + *ToExprOrErr, + ASTConstraintSatisfaction::Rebuild(ToC, R->getConstraintSatisfaction())); +} + +template <> +Expected<concepts::TypeRequirement *> +ASTNodeImporter::import(concepts::TypeRequirement *R) { + auto &ToC = Importer.ToContext; + if (R->isSubstitutionFailure()) { + auto ToSubstDiagOrErr = import(R->getSubstitutionDiagnostic()); + if (!ToSubstDiagOrErr) + return ToSubstDiagOrErr.takeError(); + return new (ToC) concepts::TypeRequirement(*ToSubstDiagOrErr); + } + + Expected<TypeSourceInfo *> ToTSI = Importer.Import(R->getType()); + if (!ToTSI) + return ToTSI.takeError(); + return new (ToC) concepts::TypeRequirement(*ToTSI); +} + +template <> +Expected<concepts::Requirement *> +ASTNodeImporter::import(concepts::Requirement *R) { + auto Kind = R->getKind(); + if (Kind == concepts::Requirement::RK_Type) + return import(cast<concepts::TypeRequirement>(R)); + else if (Kind == concepts::Requirement::RK_Nested) + return import(cast<concepts::NestedRequirement>(R)); + return import(cast<concepts::ExprRequirement>(R)); +} + template <typename T> bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) { if (Found->getLinkageInternal() != From->getLinkageInternal()) @@ -6788,6 +6924,81 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { return ToFunc; } +ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); + + if (ToD) + return ToD; + + auto ParamsOrErr = import(D->getTemplateParameters()); + if (!ParamsOrErr) + return ParamsOrErr.takeError(); + TemplateParameterList *Params = *ParamsOrErr; + + ExpectedExpr ToConstraintClauseOrErr = import(D->getConstraintExpr()); + if (!ToConstraintClauseOrErr) + return ToConstraintClauseOrErr.takeError(); + + Expr *ToConstraintClause = *ToConstraintClauseOrErr; + + ConceptDecl *ToConcept = nullptr; + if (GetImportedOrCreateDecl(ToConcept, D, Importer.getToContext(), DC, Loc, + Name, Params, ToConstraintClause)) + return ToConcept; + + addDeclToContexts(D, ToConcept); + + return ToConcept; +} + +ExpectedDecl +ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); + + ExpectedSLoc ToStartLocOrErr = import(D->getLocation()); + if (!ToStartLocOrErr) + return ToStartLocOrErr.takeError(); + + SourceLocation ToStartLoc = *ToStartLocOrErr; + + RequiresExprBodyDecl *ToD = nullptr; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, ToStartLoc)) + return ToD; + + return ToD; +} + +ExpectedDecl ASTNodeImporter::VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D) { + DeclContext *DC, *LexicalDC; + if (Error Err = ImportDeclContext(D, DC, LexicalDC)) + return std::move(Err); + + ExpectedSLoc ToLocOrErr = import(D->getLocation()); + if (!ToLocOrErr) + return ToLocOrErr.takeError(); + + const auto &FromArgs = D->getTemplateArguments(); + SmallVector<TemplateArgument, 4> ToArgs(FromArgs.size()); + if (Error Err = ImportContainerChecked(FromArgs, ToArgs)) + return std::move(Err); + + ImplicitConceptSpecializationDecl *ToD = nullptr; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *ToLocOrErr, + ToArgs)) + return ToD; + + return ToD; +} + //---------------------------------------------------------------------------- // Import Statements //---------------------------------------------------------------------------- @@ -9003,6 +9214,60 @@ ExpectedStmt ASTNodeImporter::VisitCXXFoldExpr(CXXFoldExpr *E) { ToEllipsisLoc, ToRHS, ToRParenLoc, E->getNumExpansions()); } +ExpectedStmt ASTNodeImporter::VisitRequiresExpr(RequiresExpr *E) { + auto ToBodyOrErr = import(E->getBody()); + if (!ToBodyOrErr) + return ToBodyOrErr.takeError(); + + const auto &FromLocalParams = E->getLocalParameters(); + SmallVector<ParmVarDecl *, 4> ToLocalParams(FromLocalParams.size()); + if (Error Err = ImportContainerChecked(FromLocalParams, ToLocalParams)) + return std::move(Err); + + const auto &FromRequirements = E->getRequirements(); + SmallVector<concepts::Requirement *, 4> ToRequirements( + FromRequirements.size()); + if (Error Err = ImportContainerChecked(FromRequirements, ToRequirements)) + return std::move(Err); + + Error Err = Error::success(); + SourceLocation RequiresKWLoc = importChecked(Err, E->getRequiresKWLoc()); + SourceLocation ToLParenLoc = importChecked(Err, E->getLParenLoc()); + SourceLocation ToRParenLoc = importChecked(Err, E->getRParenLoc()); + SourceLocation ToRBrackeLoc = importChecked(Err, E->getRBraceLoc()); + + if (Err) + return std::move(Err); + + return RequiresExpr::Create(Importer.getToContext(), RequiresKWLoc, + *ToBodyOrErr, ToLParenLoc, ToLocalParams, + ToRParenLoc, ToRequirements, ToRBrackeLoc); +} + +ExpectedStmt +ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) { + auto ToConceptRefOrErr = import(E->getConceptReference()); + if (!ToConceptRefOrErr) + return ToConceptRefOrErr.takeError(); + + ImplicitConceptSpecializationDecl *ToSpecDecl = nullptr; + if (E->hasSpecializationDecl()) { + auto ToSpecDeclOrErr = import(E->getSpecializationDecl()); + if (!ToSpecDeclOrErr) + return ToSpecDeclOrErr.takeError(); + ToSpecDecl = *ToSpecDeclOrErr; + } + + auto &ToC = Importer.ToContext; + auto IsDependent = E->isValueDependent(); + return ConceptSpecializationExpr::Create( + ToC, *ToConceptRefOrErr, ToSpecDecl, + !IsDependent + ? ASTConstraintSatisfaction::Rebuild(ToC, E->getSatisfaction()) + : nullptr, + IsDependent, E->containsUnexpandedParameterPack()); +} + Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod) { Error ImportErrors = Error::success(); diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp index 0704630c0fc266..072a5a4b25d0fb 100644 --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -34,11 +34,17 @@ ConceptSpecializationExpr::ConceptSpecializationExpr( const ASTContext &C, ConceptReference *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction) + : ConceptSpecializationExpr( + C, Loc, SpecDecl, + Satisfaction ? ASTConstraintSatisfaction::Create(C, *Satisfaction) + : nullptr) {} + +ConceptSpecializationExpr::ConceptSpecializationExpr( + const ASTContext &C, ConceptReference *Loc, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction) : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), - ConceptRef(Loc), SpecDecl(SpecDecl), - Satisfaction(Satisfaction - ? ASTConstraintSatisfaction::Create(C, *Satisfaction) - : nullptr) { + ConceptRef(Loc), SpecDecl(SpecDecl), Satisfaction(Satisfaction) { setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction)); // Currently guaranteed by the fact concepts can only be at namespace-scope. @@ -63,16 +69,31 @@ ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction); } +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction) { + return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction); +} + ConceptSpecializationExpr::ConceptSpecializationExpr( const ASTContext &C, ConceptReference *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack) + : ConceptSpecializationExpr( + C, Loc, SpecDecl, + Satisfaction ? ASTConstraintSatisfaction::Create(C, *Satisfaction) + : nullptr, + Dependent, ContainsUnexpandedParameterPack) {} + +ConceptSpecializationExpr::ConceptSpecializationExpr( + const ASTContext &C, ConceptReference *Loc, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction, bool Dependent, + bool ContainsUnexpandedParameterPack) : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), - ConceptRef(Loc), SpecDecl(SpecDecl), - Satisfaction(Satisfaction - ? ASTConstraintSatisfaction::Create(C, *Satisfaction) - : nullptr) { + ConceptRef(Loc), SpecDecl(SpecDecl), Satisfaction(Satisfaction) { ExprDependence D = ExprDependence::None; if (!Satisfaction) D |= ExprDependence::Value; @@ -94,6 +115,17 @@ ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, ContainsUnexpandedParameterPack); } +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, + ImplicitConceptSpecializationDecl *SpecDecl, + ASTConstraintSatisfaction *Satisfaction, + bool Dependent, + bool ContainsUnexpandedParameterPack) { + return new (C) + ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent, + ContainsUnexpandedParameterPack); +} + const TypeConstraint * concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { assert(isTypeConstraint()); @@ -193,3 +225,61 @@ RequiresExpr::Create(ASTContext &C, EmptyShell Empty, alignof(RequiresExpr)); return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); } + +concepts::ExprRequirement::ExprRequirement( + Expr *E, bool IsSimple, SourceLocation NoexceptLoc, + ReturnTypeRequirement Req, SatisfactionStatus Status, + ConceptSpecializationExpr *SubstitutedConstraintExpr) + : Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, + Status == SS_Dependent && + (E->containsUnexpandedParameterPack() || + Req.containsUnexpandedParameterPack()), + Status == SS_Satisfied), + Value(E), NoexceptLoc(NoexceptLoc), TypeReq(Req), + SubstitutedConstraintExpr(SubstitutedConstraintExpr), Status(Status) { + assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && + "Simple requirement must not have a return type requirement or a " + "noexcept specification"); + assert((Status > SS_TypeRequirementSubstitutionFailure && + Req.isTypeConstraint()) == (SubstitutedConstraintExpr != nullptr)); +} + +concepts::ExprRequirement::ExprRequirement( + SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, + SourceLocation NoexceptLoc, ReturnTypeRequirement Req) + : Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), + Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), + Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), + Status(SS_ExprSubstitutionFailure) { + assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && + "Simple requirement must not have a return type requirement or a " + "noexcept specification"); +}... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/104731 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits