https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/133190
>From 4a6c03876d9f106df9913aeb66d484afc362454f Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Wed, 26 Mar 2025 18:38:34 -0300 Subject: [PATCH] [clang] support pack expansions for trailing requires clauses This fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded. --- .../refactor/tweaks/ExtractVariable.cpp | 6 +-- clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/AST/ASTContext.h | 8 +++ clang/include/clang/AST/ASTNodeTraverser.h | 4 +- clang/include/clang/AST/Decl.h | 37 +++++++------- clang/include/clang/AST/DeclCXX.h | 20 ++++---- clang/include/clang/AST/ExprCXX.h | 2 +- clang/include/clang/AST/RecursiveASTVisitor.h | 9 ++-- clang/include/clang/Sema/Sema.h | 14 ++--- clang/lib/AST/ASTContext.cpp | 13 ++++- clang/lib/AST/ASTImporter.cpp | 5 +- clang/lib/AST/Decl.cpp | 15 +++--- clang/lib/AST/DeclCXX.cpp | 33 +++++++----- clang/lib/AST/DeclPrinter.cpp | 10 ++-- clang/lib/AST/DeclTemplate.cpp | 4 +- clang/lib/AST/ExprCXX.cpp | 2 +- clang/lib/AST/ItaniumMangle.cpp | 2 +- clang/lib/ASTMatchers/ASTMatchFinder.cpp | 3 +- clang/lib/Index/IndexDecl.cpp | 4 +- clang/lib/Sema/SemaConcept.cpp | 6 +-- clang/lib/Sema/SemaDecl.cpp | 21 ++++---- clang/lib/Sema/SemaDeclCXX.cpp | 4 +- clang/lib/Sema/SemaFunctionEffects.cpp | 2 +- clang/lib/Sema/SemaLambda.cpp | 18 ++++--- clang/lib/Sema/SemaOverload.cpp | 12 +++-- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 51 ++++++++++++------- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 +- clang/lib/Sema/TreeTransform.h | 7 ++- clang/lib/Serialization/ASTReaderDecl.cpp | 3 +- clang/lib/Serialization/ASTWriterDecl.cpp | 5 +- .../SemaCXX/fold_lambda_with_variadics.cpp | 9 ++++ clang/tools/libclang/CIndex.cpp | 2 +- 32 files changed, 204 insertions(+), 133 deletions(-) diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp index d84e501b87ce7..90dac3b76c648 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp @@ -100,9 +100,9 @@ computeReferencedDecls(const clang::Expr *Expr) { TraverseLambdaCapture(LExpr, &Capture, Initializer); } - if (clang::Expr *const RequiresClause = - LExpr->getTrailingRequiresClause()) { - TraverseStmt(RequiresClause); + if (const clang::Expr *RequiresClause = + LExpr->getTrailingRequiresClause().ConstraintExpr) { + TraverseStmt(const_cast<clang::Expr *>(RequiresClause)); } for (auto *const TemplateParam : LExpr->getExplicitTemplateParameters()) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c4e82678949ff..fa6daad80604a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -373,6 +373,8 @@ Bug Fixes to C++ Support - Improved fix for an issue with pack expansions of type constraints, where this now also works if the constraint has non-type or template template parameters. (#GH131798) +- Fix crash when evaluating the trailing requires clause of generic lambdas which are part of + a pack expansion. - Fixes matching of nested template template parameters. (#GH130362) - Correctly diagnoses template template paramters which have a pack parameter not in the last position. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a24f30815e6b9..526d4c7c12b6e 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2906,6 +2906,14 @@ class ASTContext : public RefCountedBase<ASTContext> { /// that they may be used in declarations of the same template. bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const; + /// Determine whether two 'requires' expressions are similar enough that they + /// may be used in re-declarations. + /// + /// Use of 'requires' isn't mandatory, works with constraints expressed in + /// other ways too. + bool isSameAssociatedConstraint(const AssociatedConstraint &ACX, + const AssociatedConstraint &ACY) const; + /// Determine whether two 'requires' expressions are similar enough that they /// may be used in re-declarations. /// diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index f086d8134a64b..7bb435146f752 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -538,8 +538,8 @@ class ASTNodeTraverser for (const auto *Parameter : D->parameters()) Visit(Parameter); - if (const Expr *TRC = D->getTrailingRequiresClause()) - Visit(TRC); + if (const AssociatedConstraint &TRC = D->getTrailingRequiresClause()) + Visit(TRC.ConstraintExpr); if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isDefaulted()) return; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 9e7e93d98c9d1..e4f1e2921bef8 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -81,13 +81,19 @@ enum class ImplicitParamKind; // Holds a constraint expression along with a pack expansion index, if // expanded. struct AssociatedConstraint { - const Expr *ConstraintExpr; - int ArgumentPackSubstitutionIndex; + const Expr *ConstraintExpr = nullptr; + int ArgumentPackSubstitutionIndex = -1; + + constexpr AssociatedConstraint() = default; explicit AssociatedConstraint(const Expr *ConstraintExpr, int ArgumentPackSubstitutionIndex = -1) : ConstraintExpr(ConstraintExpr), ArgumentPackSubstitutionIndex(ArgumentPackSubstitutionIndex) {} + + explicit operator bool() const { return ConstraintExpr != nullptr; } + + bool isNull() const { return !operator bool(); } }; /// The top declaration context. @@ -754,7 +760,7 @@ class DeclaratorDecl : public ValueDecl { // and constrained function decls. struct ExtInfo : public QualifierInfo { TypeSourceInfo *TInfo = nullptr; - Expr *TrailingRequiresClause = nullptr; + AssociatedConstraint TrailingRequiresClause; }; llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo; @@ -823,17 +829,12 @@ class DeclaratorDecl : public ValueDecl { /// \brief Get the constraint-expression introduced by the trailing /// requires-clause in the function/member declaration, or null if no /// requires-clause was provided. - Expr *getTrailingRequiresClause() { - return hasExtInfo() ? getExtInfo()->TrailingRequiresClause - : nullptr; - } - - const Expr *getTrailingRequiresClause() const { - return hasExtInfo() ? getExtInfo()->TrailingRequiresClause - : nullptr; + const AssociatedConstraint &getTrailingRequiresClause() const { + static constexpr AssociatedConstraint Null; + return hasExtInfo() ? getExtInfo()->TrailingRequiresClause : Null; } - void setTrailingRequiresClause(Expr *TrailingRequiresClause); + void setTrailingRequiresClause(const AssociatedConstraint &AC); unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; @@ -2102,7 +2103,7 @@ class FunctionDecl : public DeclaratorDecl, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin, bool isInlineSpecified, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause = nullptr); + const AssociatedConstraint &TrailingRequiresClause); using redeclarable_base = Redeclarable<FunctionDecl>; @@ -2138,7 +2139,7 @@ class FunctionDecl : public DeclaratorDecl, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin = false, bool isInlineSpecified = false, bool hasWrittenPrototype = true, ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified, - Expr *TrailingRequiresClause = nullptr) { + const AssociatedConstraint &TrailingRequiresClause = {}) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, isInlineSpecified, @@ -2151,7 +2152,7 @@ class FunctionDecl : public DeclaratorDecl, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified, bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause); + const AssociatedConstraint &TrailingRequiresClause); static FunctionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -2644,9 +2645,9 @@ class FunctionDecl : public DeclaratorDecl, /// Use this instead of getTrailingRequiresClause for concepts APIs that /// accept an ArrayRef of constraint expressions. void - getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &AC) const { - if (auto *TRC = getTrailingRequiresClause()) - AC.emplace_back(TRC); + getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &ACs) const { + if (const AssociatedConstraint &AC = getTrailingRequiresClause()) + ACs.emplace_back(AC); } /// Get the message that indicates why this function was deleted. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index dbd02ef7f8011..c1a144ff2970b 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1974,7 +1974,7 @@ class CXXDeductionGuideDecl : public FunctionDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor, DeductionCandidate Kind, - Expr *TrailingRequiresClause, + const AssociatedConstraint &TrailingRequiresClause, const CXXDeductionGuideDecl *GeneratedFrom, SourceDeductionGuideKind SourceKind) : FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo, @@ -2007,7 +2007,7 @@ class CXXDeductionGuideDecl : public FunctionDecl { TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor = nullptr, DeductionCandidate Kind = DeductionCandidate::Normal, - Expr *TrailingRequiresClause = nullptr, + const AssociatedConstraint &TrailingRequiresClause = {}, const CXXDeductionGuideDecl *SourceDG = nullptr, SourceDeductionGuideKind SK = SourceDeductionGuideKind::None); @@ -2115,7 +2115,7 @@ class CXXMethodDecl : public FunctionDecl { QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInline, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr) + const AssociatedConstraint &TrailingRequiresClause = {}) : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, isInline, ConstexprKind, TrailingRequiresClause) { if (EndLocation.isValid()) @@ -2128,7 +2128,7 @@ class CXXMethodDecl : public FunctionDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInline, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + const AssociatedConstraint &TrailingRequiresClause = {}); static CXXMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -2596,7 +2596,7 @@ class CXXConstructorDecl final bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited, - Expr *TrailingRequiresClause); + const AssociatedConstraint &TrailingRequiresClause); void anchor() override; @@ -2639,7 +2639,7 @@ class CXXConstructorDecl final ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited = InheritedConstructor(), - Expr *TrailingRequiresClause = nullptr); + const AssociatedConstraint &TrailingRequiresClause = {}); void setExplicitSpecifier(ExplicitSpecifier ES) { assert((!ES.getExpr() || @@ -2858,7 +2858,7 @@ class CXXDestructorDecl : public CXXMethodDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause = nullptr) + const AssociatedConstraint &TrailingRequiresClause = {}) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, UsesFPIntrin, isInline, ConstexprKind, SourceLocation(), TrailingRequiresClause) { @@ -2873,7 +2873,7 @@ class CXXDestructorDecl : public CXXMethodDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause = nullptr); + const AssociatedConstraint &TrailingRequiresClause = {}); static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2919,7 +2919,7 @@ class CXXConversionDecl : public CXXMethodDecl { TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr) + const AssociatedConstraint &TrailingRequiresClause = {}) : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, UsesFPIntrin, isInline, ConstexprKind, EndLocation, TrailingRequiresClause), @@ -2937,7 +2937,7 @@ class CXXConversionDecl : public CXXMethodDecl { const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, - Expr *TrailingRequiresClause = nullptr); + const AssociatedConstraint &TrailingRequiresClause = {}); static CXXConversionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); ExplicitSpecifier getExplicitSpecifier() { diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 223d74993e9e6..bdc0eb81b5f02 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2129,7 +2129,7 @@ class LambdaExpr final : public Expr, ArrayRef<NamedDecl *> getExplicitTemplateParameters() const; /// Get the trailing requires clause, if any. - Expr *getTrailingRequiresClause() const; + const AssociatedConstraint &getTrailingRequiresClause() const; /// Whether this is a generic lambda. bool isGenericLambda() const { return getTemplateParameterList(); } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 0530996ed20d3..3edc8684d0a19 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2253,8 +2253,10 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { } // Visit the trailing requires clause, if any. - if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) { - TRY_TO(TraverseStmt(TrailingRequiresClause)); + if (const AssociatedConstraint &TrailingRequiresClause = + D->getTrailingRequiresClause()) { + TRY_TO(TraverseStmt( + const_cast<Expr *>(TrailingRequiresClause.ConstraintExpr))); } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { @@ -2768,7 +2770,8 @@ DEF_TRAVERSE_STMT(LambdaExpr, { if (S->hasExplicitResultType()) TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getTrailingRequiresClause()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT( + const_cast<Expr *>(S->getTrailingRequiresClause().ConstraintExpr)); TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 822cae99ddae7..3a18bcb8a38da 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8866,12 +8866,14 @@ class Sema final : public SemaBase { CXXMethodDecl *CallOperator, CXXRecordDecl *Class, TemplateParameterList *TemplateParams); - void CompleteLambdaCallOperator( - CXXMethodDecl *Method, SourceLocation LambdaLoc, - SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, - TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind, - StorageClass SC, ArrayRef<ParmVarDecl *> Params, - bool HasExplicitResultType); + void + CompleteLambdaCallOperator(CXXMethodDecl *Method, SourceLocation LambdaLoc, + SourceLocation CallOperatorLoc, + const AssociatedConstraint &TrailingRequiresClause, + TypeSourceInfo *MethodTyInfo, + ConstexprSpecKind ConstexprKind, StorageClass SC, + ArrayRef<ParmVarDecl *> Params, + bool HasExplicitResultType); /// Returns true if the explicit object parameter was invalid. bool DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 552b5823add36..5483503fefddf 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7070,6 +7070,15 @@ bool ASTContext::hasSameTemplateName(const TemplateName &X, getCanonicalTemplateName(Y, IgnoreDeduced); } +bool ASTContext::isSameAssociatedConstraint( + const AssociatedConstraint &ACX, const AssociatedConstraint &ACY) const { + if (ACX.ArgumentPackSubstitutionIndex != ACY.ArgumentPackSubstitutionIndex) + return false; + if (!isSameConstraintExpr(ACX.ConstraintExpr, ACY.ConstraintExpr)) + return false; + return true; +} + bool ASTContext::isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const { if (!XCE != !YCE) return false; @@ -7386,8 +7395,8 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { return false; } - if (!isSameConstraintExpr(FuncX->getTrailingRequiresClause(), - FuncY->getTrailingRequiresClause())) + if (!isSameAssociatedConstraint(FuncX->getTrailingRequiresClause(), + FuncY->getTrailingRequiresClause())) return false; auto GetTypeAsWritten = [](const FunctionDecl *FD) { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 81acb013b0f7d..286d159b46ab2 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3915,8 +3915,9 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { auto ToEndLoc = importChecked(Err, D->getEndLoc()); auto ToDefaultLoc = importChecked(Err, D->getDefaultLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); - auto TrailingRequiresClause = - importChecked(Err, D->getTrailingRequiresClause()); + AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause(); + TrailingRequiresClause.ConstraintExpr = + importChecked(Err, TrailingRequiresClause.ConstraintExpr); if (Err) return std::move(Err); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5f5568518e0b9..568d74cc7df0b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2009,8 +2009,8 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } } -void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) { - assert(TrailingRequiresClause); +void DeclaratorDecl::setTrailingRequiresClause(const AssociatedConstraint &AC) { + assert(AC); // Make sure the extended decl info is allocated. if (!hasExtInfo()) { // Save (non-extended) type source info pointer. @@ -2021,7 +2021,7 @@ void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) { getExtInfo()->TInfo = savedTInfo; } // Set requires clause info. - getExtInfo()->TrailingRequiresClause = TrailingRequiresClause; + getExtInfo()->TrailingRequiresClause = AC; } void DeclaratorDecl::setTemplateParameterListsInfo( @@ -3047,7 +3047,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin, bool isInlineSpecified, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause) + const AssociatedConstraint &TrailingRequiresClause) : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, StartLoc), DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0), @@ -3571,7 +3571,7 @@ bool FunctionDecl::isMemberLikeConstrainedFriend() const { // If these friends don't have constraints, they aren't constrained, and // thus don't fall under temp.friend p9. Else the simple presence of a // constraint makes them unique. - return getTrailingRequiresClause(); + return !getTrailingRequiresClause().isNull(); } return FriendConstraintRefersToEnclosingTemplate(); @@ -5453,7 +5453,7 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified, bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind, - Expr *TrailingRequiresClause) { + const AssociatedConstraint &TrailingRequiresClause) { FunctionDecl *New = new (C, DC) FunctionDecl( Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, isInlineSpecified, ConstexprKind, TrailingRequiresClause); @@ -5464,7 +5464,8 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { return new (C, ID) FunctionDecl( Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), - nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr); + nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, + /*TrailingRequiresClause=*/{}); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 7eff776882629..61f6f92084834 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2304,7 +2304,7 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation StartLoc, ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor, - DeductionCandidate Kind, Expr *TrailingRequiresClause, + DeductionCandidate Kind, const AssociatedConstraint &TrailingRequiresClause, const CXXDeductionGuideDecl *GeneratedFrom, SourceDeductionGuideKind SourceKind) { return new (C, DC) CXXDeductionGuideDecl( @@ -2318,7 +2318,7 @@ CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { C, /*DC=*/nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), QualType(), /*TInfo=*/nullptr, SourceLocation(), /*Ctor=*/nullptr, DeductionCandidate::Normal, - /*TrailingRequiresClause=*/nullptr, + /*TrailingRequiresClause=*/{}, /*GeneratedFrom=*/nullptr, SourceDeductionGuideKind::None); } @@ -2427,7 +2427,7 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInline, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, - Expr *TrailingRequiresClause) { + const AssociatedConstraint &TrailingRequiresClause) { return new (C, RD) CXXMethodDecl( CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin, isInline, ConstexprKind, EndLocation, TrailingRequiresClause); @@ -2435,10 +2435,11 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { - return new (C, ID) CXXMethodDecl( - CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), - QualType(), nullptr, SC_None, false, false, - ConstexprSpecKind::Unspecified, SourceLocation(), nullptr); + return new (C, ID) + CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), nullptr, SC_None, false, + false, ConstexprSpecKind::Unspecified, SourceLocation(), + /*TrailingRequiresClause=*/{}); } CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, @@ -2834,7 +2835,8 @@ CXXConstructorDecl::CXXConstructorDecl( const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - InheritedConstructor Inherited, Expr *TrailingRequiresClause) + InheritedConstructor Inherited, + const AssociatedConstraint &TrailingRequiresClause) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, UsesFPIntrin, isInline, ConstexprKind, SourceLocation(), TrailingRequiresClause) { @@ -2861,7 +2863,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, auto *Result = new (C, ID, Extra) CXXConstructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, ExplicitSpecifier(), false, false, false, ConstexprSpecKind::Unspecified, - InheritedConstructor(), nullptr); + InheritedConstructor(), /*TrailingRequiresClause=*/{}); Result->setInheritingConstructor(isInheritingConstructor); Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier = hasTrailingExplicit; @@ -2874,7 +2876,8 @@ CXXConstructorDecl *CXXConstructorDecl::Create( const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - InheritedConstructor Inherited, Expr *TrailingRequiresClause) { + InheritedConstructor Inherited, + const AssociatedConstraint &TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName && "Name must refer to a constructor"); @@ -3000,14 +3003,16 @@ CXXDestructorDecl *CXXDestructorDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { return new (C, ID) CXXDestructorDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, - false, false, false, ConstexprSpecKind::Unspecified, nullptr); + false, false, false, ConstexprSpecKind::Unspecified, + /*TrailingRequiresClause=*/{}); } CXXDestructorDecl *CXXDestructorDecl::Create( ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) { + ConstexprSpecKind ConstexprKind, + const AssociatedConstraint &TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); @@ -3055,7 +3060,7 @@ CXXConversionDecl *CXXConversionDecl::CreateDeserialized(ASTContext &C, return new (C, ID) CXXConversionDecl( C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, - SourceLocation(), nullptr); + SourceLocation(), /*TrailingRequiresClause=*/{}); } CXXConversionDecl *CXXConversionDecl::Create( @@ -3063,7 +3068,7 @@ CXXConversionDecl *CXXConversionDecl::Create( const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, - Expr *TrailingRequiresClause) { + const AssociatedConstraint &TrailingRequiresClause) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXConversionFunctionName && "Name must refer to a conversion function"); diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 6368531cef3be..28098b242d494 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -842,10 +842,14 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } Out << Proto; - if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) { + if (const AssociatedConstraint &TrailingRequiresClause = + D->getTrailingRequiresClause()) { Out << " requires "; - TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation, - "\n", &Context); + // FIXME: The printer could support printing expressions and types as if + // expanded by an index. Pass in the ArgumentPackSubstitutionIndex when + // that's supported. + TrailingRequiresClause.ConstraintExpr->printPretty( + Out, nullptr, SubPolicy, Indentation, "\n", &Context); } } else { Ty.print(Out, Policy, Proto); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 8f6916aeb4bd6..b0bba8408f2b9 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -291,7 +291,7 @@ void TemplateDecl::getAssociatedConstraints( llvm::SmallVectorImpl<AssociatedConstraint> &ACs) const { TemplateParams->getAssociatedConstraints(ACs); if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) - if (const Expr *TRC = FD->getTrailingRequiresClause()) + if (const AssociatedConstraint &TRC = FD->getTrailingRequiresClause()) ACs.emplace_back(TRC); } @@ -299,7 +299,7 @@ bool TemplateDecl::hasAssociatedConstraints() const { if (TemplateParams->hasAssociatedConstraints()) return true; if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) - return FD->getTrailingRequiresClause(); + return static_cast<bool>(FD->getTrailingRequiresClause()); return false; } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index a000e988e6834..232a23223f556 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1402,7 +1402,7 @@ ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const { return Record->getLambdaExplicitTemplateParameters(); } -Expr *LambdaExpr::getTrailingRequiresClause() const { +const AssociatedConstraint &LambdaExpr::getTrailingRequiresClause() const { return getCallOperator()->getTrailingRequiresClause(); } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index b81981606866a..eb9c9c30622ad 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3781,7 +3781,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto, if (FD) { FunctionTypeDepth.enterResultType(); - mangleRequiresClause(FD->getTrailingRequiresClause()); + mangleRequiresClause(FD->getTrailingRequiresClause().ConstraintExpr); } FunctionTypeDepth.pop(saved); diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index e9ec7eff1e0ab..6d0ba0b7907a1 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -584,7 +584,8 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>, if (LE->hasExplicitResultType()) TraverseTypeLoc(Proto.getReturnLoc()); - TraverseStmt(LE->getTrailingRequiresClause()); + TraverseStmt( + const_cast<Expr *>(LE->getTrailingRequiresClause().ConstraintExpr)); } TraverseStmt(LE->getBody()); diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 6c971bf0f381b..df875e0b40079 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -132,8 +132,8 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { } } } - if (auto *C = D->getTrailingRequiresClause()) - IndexCtx.indexBody(C, Parent); + if (const AssociatedConstraint &C = D->getTrailingRequiresClause()) + IndexCtx.indexBody(C.ConstraintExpr, Parent); } bool handleObjCMethod(const ObjCMethodDecl *D, diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index e6117f97ad1f4..eccdaf2400e00 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -928,10 +928,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, ForOverloadResolution); return CheckConstraintSatisfaction( - FD, - AssociatedConstraint(FD->getTrailingRequiresClause(), - ArgumentPackSubstitutionIndex), - *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), + FD, FD->getTrailingRequiresClause(), *MLTAL, + SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), Satisfaction); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index bbefbbf294dd1..cf05b1c55bb72 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9358,7 +9358,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, SemaRef.getCurFPFeatures().isFPConstrained(), isInline, HasPrototype, ConstexprSpecKind::Unspecified, - /*TrailingRequiresClause=*/nullptr); + /*TrailingRequiresClause=*/{}); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -9366,7 +9366,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, } ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier(); - Expr *TrailingRequiresClause = D.getTrailingRequiresClause(); + AssociatedConstraint TrailingRequiresClause(D.getTrailingRequiresClause()); SemaRef.CheckExplicitObjectMemberFunction(DC, D, Name, R); @@ -10536,7 +10536,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::ext_operator_new_delete_declared_inline) << NewFD->getDeclName(); - if (Expr *TRC = NewFD->getTrailingRequiresClause()) { + if (const Expr *TRC = NewFD->getTrailingRequiresClause().ConstraintExpr) { // C++20 [dcl.decl.general]p4: // The optional requires-clause in an init-declarator or // member-declarator shall be present only if the declarator declares a @@ -12266,7 +12266,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (Method->isVirtual() && NewFD->getTrailingRequiresClause()) // C++2a [class.virtual]p6 // A virtual method shall not have a requires-clause. - Diag(NewFD->getTrailingRequiresClause()->getBeginLoc(), + Diag(NewFD->getTrailingRequiresClause().ConstraintExpr->getBeginLoc(), diag::err_constrained_virtual_method); if (Method->isStatic()) @@ -19090,8 +19090,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, SmallVector<bool, 4> SatisfactionStatus; for (CXXMethodDecl *Method : Methods) { - const Expr *Constraints = Method->getTrailingRequiresClause(); - if (!Constraints) + if (!Method->getTrailingRequiresClause()) SatisfactionStatus.push_back(true); else { ConstraintSatisfaction Satisfaction; @@ -19110,7 +19109,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, if (FunctionDecl *MF = OrigMethod->getInstantiatedFromMemberFunction()) OrigMethod = cast<CXXMethodDecl>(MF); - const Expr *Constraints = OrigMethod->getTrailingRequiresClause(); + AssociatedConstraint Orig = OrigMethod->getTrailingRequiresClause(); bool AnotherMethodIsMoreConstrained = false; for (size_t j = 0; j < Methods.size(); j++) { if (i == j || !SatisfactionStatus[j]) @@ -19123,15 +19122,13 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record, CSM)) continue; - const Expr *OtherConstraints = OtherMethod->getTrailingRequiresClause(); - if (!OtherConstraints) + AssociatedConstraint Other = OtherMethod->getTrailingRequiresClause(); + if (!Other) continue; - if (!Constraints) { + if (!Orig) { AnotherMethodIsMoreConstrained = true; break; } - AssociatedConstraint Other(OtherConstraints); - AssociatedConstraint Orig(Constraints); if (S.IsAtLeastAsConstrained(OtherMethod, {Other}, OrigMethod, {Orig}, AnotherMethodIsMoreConstrained)) { // There was an error with the constraints comparison. Exit the loop diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 43bf9b7cd0f95..87c2b1b7eee1e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -19017,8 +19017,8 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { return true; // Check the trailing requires clause - if (Expr *E = Method->getTrailingRequiresClause()) - if (!Finder.TraverseStmt(E)) + if (const AssociatedConstraint &TRC = Method->getTrailingRequiresClause()) + if (!Finder.TraverseStmt(const_cast<Expr *>(TRC.ConstraintExpr))) return true; return checkThisInStaticMemberFunctionAttributes(Method); diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 31980abd23fd1..1592862416bf9 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -990,7 +990,7 @@ class Analyzer { followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor); if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) { - TrailingRequiresClause = FD->getTrailingRequiresClause(); + TrailingRequiresClause = FD->getTrailingRequiresClause().ConstraintExpr; // Note that FD->getType->getAs<FunctionProtoType>() can yield a // noexcept Expr which has been boiled down to a constant expression. diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 292406f886362..9f82433a0b335 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1015,7 +1015,7 @@ CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange, QualType(), /*Tinfo=*/nullptr, SC_None, getCurFPFeatures().isFPConstrained(), /*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(), - /*TrailingRequiresClause=*/nullptr); + /*TrailingRequiresClause=*/{}); Method->setAccess(AS_public); return Method; } @@ -1033,7 +1033,8 @@ void Sema::AddTemplateParametersToLambdaCallOperator( void Sema::CompleteLambdaCallOperator( CXXMethodDecl *Method, SourceLocation LambdaLoc, - SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, + SourceLocation CallOperatorLoc, + const AssociatedConstraint &TrailingRequiresClause, TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind, StorageClass SC, ArrayRef<ParmVarDecl *> Params, bool HasExplicitResultType) { @@ -1461,8 +1462,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CompleteLambdaCallOperator( Method, Intro.Range.getBegin(), CallOperatorLoc, - ParamInfo.getTrailingRequiresClause(), MethodTyInfo, - ParamInfo.getDeclSpec().getConstexprSpecifier(), + AssociatedConstraint(ParamInfo.getTrailingRequiresClause(), + /*ArgumentPackSubstitutionIndex=*/-1), + MethodTyInfo, ParamInfo.getDeclSpec().getConstexprSpecifier(), IsLambdaStatic ? SC_Static : SC_None, Params, ExplicitResultType); CheckCXXDefaultArguments(Method); @@ -1545,7 +1547,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // The optional requires-clause ([temp.pre]) in an init-declarator or // member-declarator shall be present only if the declarator declares a // templated function ([dcl.fct]). - if (Expr *TRC = Method->getTrailingRequiresClause()) { + if (const AssociatedConstraint &TRC = Method->getTrailingRequiresClause()) { // [temp.pre]/8: // An entity is templated if it is // - a template, @@ -1568,7 +1570,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // applies to the call operator, which we already know is a member function, // AND defined. if (!Method->getDescribedFunctionTemplate() && !Method->isTemplated()) { - Diag(TRC->getBeginLoc(), diag::err_constrained_non_templated_function); + Diag(TRC.ConstraintExpr->getBeginLoc(), + diag::err_constrained_non_templated_function); } } @@ -1791,7 +1794,8 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, // A non-generic lambda may still be a templated entity. We need to preserve // constraints when converting the lambda to a function pointer. See GH63181. - if (Expr *Requires = CallOperator->getTrailingRequiresClause()) + if (const AssociatedConstraint &Requires = + CallOperator->getTrailingRequiresClause()) Conversion->setTrailingRequiresClause(Requires); if (Class->isGenericLambda()) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1802f8f4e1f91..d9a79bc802b56 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1551,12 +1551,16 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, if (!UseOverrideRules && New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { - Expr *NewRC = New->getTrailingRequiresClause(), - *OldRC = Old->getTrailingRequiresClause(); - if ((NewRC != nullptr) != (OldRC != nullptr)) + AssociatedConstraint NewRC = New->getTrailingRequiresClause(), + OldRC = Old->getTrailingRequiresClause(); + if (!NewRC != !OldRC) + return true; + if (NewRC.ArgumentPackSubstitutionIndex != + OldRC.ArgumentPackSubstitutionIndex) return true; if (NewRC && - !SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC)) + !SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC.ConstraintExpr, + NewDecl, NewRC.ConstraintExpr)) return true; } diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 3b2129e0df815..99bd9d0fb79af 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -200,7 +200,7 @@ buildDeductionGuide(Sema &SemaRef, TemplateDecl *OriginalTemplate, TypeSourceInfo *TInfo, SourceLocation LocStart, SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit, llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}, - Expr *FunctionTrailingRC = nullptr) { + const AssociatedConstraint &FunctionTrailingRC = {}) { DeclContext *DC = OriginalTemplate->getDeclContext(); auto DeductionGuideName = SemaRef.Context.DeclarationNames.getCXXDeductionGuideName( @@ -356,7 +356,8 @@ struct ConvertConstructorToDeductionGuideTransform { TemplateParameterList *TemplateParams = SemaRef.GetTemplateParameterList(Template); SmallVector<TemplateArgument, 16> Depth1Args; - Expr *OuterRC = TemplateParams->getRequiresClause(); + AssociatedConstraint OuterRC(TemplateParams->getRequiresClause(), + /*ArgumentPackSubstitutionIndex=*/-1); if (FTD) { TemplateParameterList *InnerParams = FTD->getTemplateParameters(); SmallVector<NamedDecl *, 16> AllParams; @@ -456,18 +457,20 @@ struct ConvertConstructorToDeductionGuideTransform { // At this point, the function parameters are already 'instantiated' in the // current scope. Substitute into the constructor's trailing // requires-clause, if any. - Expr *FunctionTrailingRC = nullptr; - if (Expr *RC = CD->getTrailingRequiresClause()) { + AssociatedConstraint FunctionTrailingRC; + if (const AssociatedConstraint &RC = CD->getTrailingRequiresClause()) { MultiLevelTemplateArgumentList Args; Args.setKind(TemplateSubstitutionKind::Rewrite); Args.addOuterTemplateArguments(Depth1Args); Args.addOuterRetainedLevel(); if (NestedPattern) Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); - ExprResult E = SemaRef.SubstConstraintExprWithoutSatisfaction(RC, Args); + ExprResult E = SemaRef.SubstConstraintExprWithoutSatisfaction( + const_cast<Expr *>(RC.ConstraintExpr), Args); if (!E.isUsable()) return nullptr; - FunctionTrailingRC = E.get(); + FunctionTrailingRC = + AssociatedConstraint(E.get(), RC.ArgumentPackSubstitutionIndex); } // C++ [over.match.class.deduct]p1: @@ -480,13 +483,19 @@ struct ConvertConstructorToDeductionGuideTransform { if (OuterRC) { // The outer template parameters are not transformed, so their // associated constraints don't need substitution. + // FIXME: Should simply add another field for the OuterRC, instead of + // combining them like this. if (!FunctionTrailingRC) FunctionTrailingRC = OuterRC; else - FunctionTrailingRC = BinaryOperator::Create( - SemaRef.Context, /*lhs=*/OuterRC, /*rhs=*/FunctionTrailingRC, - BO_LAnd, SemaRef.Context.BoolTy, VK_PRValue, OK_Ordinary, - TemplateParams->getTemplateLoc(), FPOptionsOverride()); + FunctionTrailingRC = AssociatedConstraint( + BinaryOperator::Create( + SemaRef.Context, + /*lhs=*/const_cast<Expr *>(OuterRC.ConstraintExpr), + /*rhs=*/const_cast<Expr *>(FunctionTrailingRC.ConstraintExpr), + BO_LAnd, SemaRef.Context.BoolTy, VK_PRValue, OK_Ordinary, + TemplateParams->getTemplateLoc(), FPOptionsOverride()), + FunctionTrailingRC.ArgumentPackSubstitutionIndex); } return buildDeductionGuide( @@ -1238,14 +1247,20 @@ void DeclareImplicitDeductionGuidesForTypeAlias( // FIXME: Here the synthesized deduction guide is not a templated // function. Per [dcl.decl]p4, the requires-clause shall be present only // if the declarator declares a templated function, a bug in standard? - auto *Constraint = buildIsDeducibleConstraint( - SemaRef, AliasTemplate, Transformed->getReturnType(), {}); - if (auto *RC = DG->getTrailingRequiresClause()) { - auto Conjunction = - SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{}, - BinaryOperatorKind::BO_LAnd, RC, Constraint); - if (!Conjunction.isInvalid()) - Constraint = Conjunction.getAs<Expr>(); + AssociatedConstraint Constraint( + buildIsDeducibleConstraint(SemaRef, AliasTemplate, + Transformed->getReturnType(), {}), + /*ArgumentPackSubstitutionIndex=*/-1); + if (const AssociatedConstraint &RC = DG->getTrailingRequiresClause()) { + auto Conjunction = SemaRef.BuildBinOp( + SemaRef.getCurScope(), SourceLocation{}, + BinaryOperatorKind::BO_LAnd, const_cast<Expr *>(RC.ConstraintExpr), + const_cast<Expr *>(Constraint.ConstraintExpr)); + if (!Conjunction.isInvalid()) { + Constraint.ConstraintExpr = Conjunction.getAs<Expr>(); + Constraint.ArgumentPackSubstitutionIndex = + RC.ArgumentPackSubstitutionIndex; + } } Transformed->setTrailingRequiresClause(Constraint); continue; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8aaaea0bcdd66..4e208b993cabd 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2669,7 +2669,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( return nullptr; } - Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); + AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause(); // If we're instantiating a local function declaration, put the result // in the enclosing namespace; otherwise we need to find the instantiated @@ -3100,7 +3100,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); - Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); + AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause(); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index e455b225d7f49..024d6b4225984 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -15653,10 +15653,13 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { auto FPTL = NewCallOpTSI->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>(); assert(FPTL && "Not a FunctionProtoType?"); + AssociatedConstraint TRC = E->getCallOperator()->getTrailingRequiresClause(); + if (TRC.ArgumentPackSubstitutionIndex == -1) + TRC.ArgumentPackSubstitutionIndex = SemaRef.ArgumentPackSubstitutionIndex; + getSema().CompleteLambdaCallOperator( NewCallOperator, E->getCallOperator()->getLocation(), - E->getCallOperator()->getInnerLocStart(), - E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI, + E->getCallOperator()->getInnerLocStart(), TRC, NewCallOpTSI, E->getCallOperator()->getConstexprKind(), E->getCallOperator()->getStorageClass(), FPTL.getParams(), E->hasExplicitResultType()); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 77daeaee5dd1f..989a107fc3488 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -901,7 +901,8 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { if (Record.readInt()) { // hasExtInfo auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); Record.readQualifierInfo(*Info); - Info->TrailingRequiresClause = Record.readExpr(); + Info->TrailingRequiresClause = + AssociatedConstraint(Record.readExpr(), int(Record.readInt())); DD->DeclInfo = Info; } QualType TSIType = Record.readType(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index b896a04a0b14b..a4b89d0d9ed5e 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -728,7 +728,10 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { if (D->hasExtInfo()) { DeclaratorDecl::ExtInfo *Info = D->getExtInfo(); Record.AddQualifierInfo(*Info); - Record.AddStmt(Info->TrailingRequiresClause); + Record.AddStmt( + const_cast<Expr *>(Info->TrailingRequiresClause.ConstraintExpr)); + Record.push_back( + Info->TrailingRequiresClause.ArgumentPackSubstitutionIndex); } // The location information is deferred until the end of the record. Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() diff --git a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp index 106da7d0e2663..980d71b2142a2 100644 --- a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp +++ b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp @@ -267,6 +267,15 @@ static_assert(bazz<1, 2>()(1)); // expected-error@-1 {{is ambiguous}} // expected-note@#bazz 2{{candidate function [with value:auto = int]}} +template <class T> concept C2 = sizeof(T) >= sizeof(int); +template <class... Ts> static constexpr auto trailing() { + return Overloaded{[](auto) requires (C2<Ts> && C2<int>) { return 0; }...}; // #trailing +} +static_assert(trailing<int, long>()(0)); +// expected-error@-1 {{is ambiguous}} +// expected-note@#trailing 2{{candidate function [with auto:1 = int]}} + + } // namespace GH101754 namespace GH131798 { diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 197ba2cd6856e..9e8cc2f6eb96c 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -872,7 +872,7 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { // FIXME: Attributes? } - if (auto *E = ND->getTrailingRequiresClause()) { + if (auto *E = ND->getTrailingRequiresClause().ConstraintExpr) { if (Visit(E)) return true; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits