[clang] [clang-tools-extra] [clang] support pack expansions for trailing requires clauses (PR #133190)
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 1 18:45:46 PDT 2025
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/133190
>From 4c3fe79695f8082f56f8403fbf1f9eb299bb4af2 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at 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/ASTNodeTraverser.h | 4 +-
clang/include/clang/AST/Decl.h | 35 +++++++------
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 | 7 ++-
clang/lib/AST/ASTImporter.cpp | 5 +-
clang/lib/AST/Decl.cpp | 14 ++---
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 +-
31 files changed, 187 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..f1066139c8514 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 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/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..adf3634d205bc 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -81,13 +81,17 @@ 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; }
};
/// The top declaration context.
@@ -754,7 +758,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 +827,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 +2101,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 +2137,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 +2150,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 +2643,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..3d561f493522b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7386,8 +7386,11 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
return false;
}
- if (!isSameConstraintExpr(FuncX->getTrailingRequiresClause(),
- FuncY->getTrailingRequiresClause()))
+ AssociatedConstraint ACX = FuncX->getTrailingRequiresClause(),
+ ACY = FuncY->getTrailingRequiresClause();
+ if (ACX.ArgumentPackSubstitutionIndex != ACY.ArgumentPackSubstitutionIndex)
+ return false;
+ if (!isSameConstraintExpr(ACX.ConstraintExpr, ACY.ConstraintExpr))
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..3852feaef1e44 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 static_cast<bool>(getTrailingRequiresClause());
}
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,7 @@ 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, {});
}
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 at -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 at -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;
}
More information about the cfe-commits
mailing list