diff options
author | Matheus Izvekov <mizvekov@gmail.com> | 2025-04-03 12:36:15 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-03 12:36:15 -0300 |
commit | 49fd0bf35d2e04a0d76ac7fd13b3e3439a91f76f (patch) | |
tree | bdc0a283e4d7cedd073db304ad6c6e3e4bcff2d9 /clang/lib | |
parent | c1ada72b0995844299ef40433314124266015428 (diff) | |
download | llvm-49fd0bf35d2e04a0d76ac7fd13b3e3439a91f76f.zip llvm-49fd0bf35d2e04a0d76ac7fd13b3e3439a91f76f.tar.gz llvm-49fd0bf35d2e04a0d76ac7fd13b3e3439a91f76f.tar.bz2 |
[clang] support pack expansions for trailing requires clauses (#133190)
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 13 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 15 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 33 | ||||
-rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 10 | ||||
-rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 2 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/ASTMatchFinder.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Index/IndexDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaFunctionEffects.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 7 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 5 |
21 files changed, 135 insertions, 89 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0270a8e..a73c15a 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 893160e..73dc355 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 5f55685..568d74c 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 3c447a9..7aa710a 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"); @@ -3062,7 +3067,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( @@ -3070,7 +3075,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 6368531..28098b2 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 8f6916a..b0bba84 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 a0bc50c..77add7b 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 b819816..eb9c9c3 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 e9ec7ef..6d0ba0b 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -584,7 +584,8 @@ public: 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 6c971bf..df875e0 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -132,8 +132,8 @@ public: } } } - 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 16f9e3d..e10c492 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -848,10 +848,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 9b7b3f8..a675fea 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9353,7 +9353,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(); @@ -9361,7 +9361,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); @@ -10531,7 +10531,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 @@ -12261,7 +12261,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()) @@ -19085,8 +19085,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; @@ -19105,7 +19104,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]) @@ -19118,15 +19117,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 96c0470..47c472b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -18995,8 +18995,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 31980ab..1592862 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -990,7 +990,7 @@ private: 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 6f114b7..f38198e 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 1802f8f..d9a79bc 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 3b2129e..99bd9d0 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 9ea5eca..fcb4ee5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2671,7 +2671,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 @@ -3102,7 +3102,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 3689d32..12ec97c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -15659,10 +15659,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 b838f84..1a2b8be 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -904,7 +904,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 b896a04a0..a4b89d0 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() |