-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] support pack expansions for trailing requires clauses #133190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] support pack expansions for trailing requires clauses #133190
Conversation
@llvm/pr-subscribers-clang-modules @llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) ChangesThis fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded. Patch is 50.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133190.diff 31 Files Affected:
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 962016c62fc68..9415b29191ddd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -352,6 +352,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 f557555e96e59..b16595db07e18 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -534,8 +534,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 6557a4c4962ec..592512e885dc8 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;
AssociatedConstraint(const Expr *ConstraintExpr,
int ArgumentPackSubstitutionIndex)
: ConstraintExpr(ConstraintExpr),
ArgumentPackSubstitutionIndex(ArgumentPackSubstitutionIndex) {}
+
+ 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,10 @@ 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, /*ArgumentPackSubstitutionIndex=*/-1);
+ getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &ACs) const {
+ if (const AssociatedConstraint &AC = getTrailingRequiresClause();
+ AC.ConstraintExpr)
+ 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 0d5d515c0e6f7..e249a066ff1d8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2254,8 +2254,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)) {
@@ -2769,7 +2771,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 c98eea1c05060..2bb2328ffb978 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8865,12 +8865,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 dd4462a4356b2..dce4e322b5bce 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7378,8 +7378,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 d397c9285ed76..747f46fdc5fa1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3923,8 +3923,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 e8aeacf24374f..7e28907d94684 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2010,8 +2010,8 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
}
}
-void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
- assert(TrailingRequiresClause);
+void DeclaratorDecl::setTrailingRequiresClause(const AssociatedConstraint &AC) {
+ assert(AC.ConstraintExpr);
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
@@ -2022,7 +2022,7 @@ void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
getExtInfo()->TInfo = savedTInfo;
}
// Set requires clause info.
- getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
+ getExtInfo()->TrailingRequiresClause = AC;
}
void DeclaratorDecl::setTemplateParameterListsInfo(
@@ -3048,7 +3048,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),
@@ -3083,7 +3083,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
static_cast<unsigned char>(DeductionCandidate::Normal);
FunctionDeclBits.HasODRHash = false;
FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
- if (TrailingRequiresClause)
+ if (TrailingRequiresClause.ConstraintExpr)
setTrailingRequiresClause(TrailingRequiresClause);
}
@@ -5454,7 +5454,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);
@@ -5465,7 +5465,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,
...
[truncated]
|
@llvm/pr-subscribers-clangd Author: Matheus Izvekov (mizvekov) ChangesThis fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded. Patch is 50.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133190.diff 31 Files Affected:
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 962016c62fc68..9415b29191ddd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -352,6 +352,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 f557555e96e59..b16595db07e18 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -534,8 +534,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 6557a4c4962ec..592512e885dc8 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;
AssociatedConstraint(const Expr *ConstraintExpr,
int ArgumentPackSubstitutionIndex)
: ConstraintExpr(ConstraintExpr),
ArgumentPackSubstitutionIndex(ArgumentPackSubstitutionIndex) {}
+
+ 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,10 @@ 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, /*ArgumentPackSubstitutionIndex=*/-1);
+ getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &ACs) const {
+ if (const AssociatedConstraint &AC = getTrailingRequiresClause();
+ AC.ConstraintExpr)
+ 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 0d5d515c0e6f7..e249a066ff1d8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2254,8 +2254,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)) {
@@ -2769,7 +2771,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 c98eea1c05060..2bb2328ffb978 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8865,12 +8865,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 dd4462a4356b2..dce4e322b5bce 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7378,8 +7378,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 d397c9285ed76..747f46fdc5fa1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3923,8 +3923,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 e8aeacf24374f..7e28907d94684 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2010,8 +2010,8 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
}
}
-void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
- assert(TrailingRequiresClause);
+void DeclaratorDecl::setTrailingRequiresClause(const AssociatedConstraint &AC) {
+ assert(AC.ConstraintExpr);
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
@@ -2022,7 +2022,7 @@ void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
getExtInfo()->TInfo = savedTInfo;
}
// Set requires clause info.
- getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
+ getExtInfo()->TrailingRequiresClause = AC;
}
void DeclaratorDecl::setTemplateParameterListsInfo(
@@ -3048,7 +3048,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),
@@ -3083,7 +3083,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
static_cast<unsigned char>(DeductionCandidate::Normal);
FunctionDeclBits.HasODRHash = false;
FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
- if (TrailingRequiresClause)
+ if (TrailingRequiresClause.ConstraintExpr)
setTrailingRequiresClause(TrailingRequiresClause);
}
@@ -5454,7 +5454,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);
@@ -5465,7 +5465,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,
...
[truncated]
|
@llvm/pr-subscribers-clang-tools-extra Author: Matheus Izvekov (mizvekov) ChangesThis fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded. Patch is 50.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133190.diff 31 Files Affected:
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 962016c62fc68..9415b29191ddd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -352,6 +352,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 f557555e96e59..b16595db07e18 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -534,8 +534,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 6557a4c4962ec..592512e885dc8 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;
AssociatedConstraint(const Expr *ConstraintExpr,
int ArgumentPackSubstitutionIndex)
: ConstraintExpr(ConstraintExpr),
ArgumentPackSubstitutionIndex(ArgumentPackSubstitutionIndex) {}
+
+ 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,10 @@ 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, /*ArgumentPackSubstitutionIndex=*/-1);
+ getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &ACs) const {
+ if (const AssociatedConstraint &AC = getTrailingRequiresClause();
+ AC.ConstraintExpr)
+ 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 0d5d515c0e6f7..e249a066ff1d8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2254,8 +2254,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)) {
@@ -2769,7 +2771,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 c98eea1c05060..2bb2328ffb978 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8865,12 +8865,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 dd4462a4356b2..dce4e322b5bce 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7378,8 +7378,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 d397c9285ed76..747f46fdc5fa1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3923,8 +3923,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 e8aeacf24374f..7e28907d94684 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2010,8 +2010,8 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
}
}
-void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
- assert(TrailingRequiresClause);
+void DeclaratorDecl::setTrailingRequiresClause(const AssociatedConstraint &AC) {
+ assert(AC.ConstraintExpr);
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
@@ -2022,7 +2022,7 @@ void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
getExtInfo()->TInfo = savedTInfo;
}
// Set requires clause info.
- getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
+ getExtInfo()->TrailingRequiresClause = AC;
}
void DeclaratorDecl::setTemplateParameterListsInfo(
@@ -3048,7 +3048,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),
@@ -3083,7 +3083,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
static_cast<unsigned char>(DeductionCandidate::Normal);
FunctionDeclBits.HasODRHash = false;
FunctionDeclBits.FriendConstraintRefersToEnclosingTemplate = false;
- if (TrailingRequiresClause)
+ if (TrailingRequiresClause.ConstraintExpr)
setTrailingRequiresClause(TrailingRequiresClause);
}
@@ -5454,7 +5454,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);
@@ -5465,7 +5465,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,
...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The patch LGTM in general. Thanks for tackling with these issues!
630d3a2
to
426bec0
Compare
Looks like there are some dependencies on the implicit bool conversion. So feel free to drop the explicit specifier ;) |
Actually the current users of the implicit conversion are not good at all, will fix them instead. |
426bec0
to
bb164f3
Compare
1b3a8e3
to
a2a372d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the most part this is fine. I think we should do a couple of code-cleanliness changes as suggested in the comments, but overall this looks fine. It IS a giant review though, it would be appreciated in the future if we could find ways to break these up. In this case, I don't have a good suggestion on how we could have done it, but whew
this was a big time sink.
@erichkeane. Ops, looks like the PR is not rebased, that's why it looks so big. But on the flip side you already reviewed the base PR :) |
bb164f3
to
eb5b0ed
Compare
a2a372d
to
6ba9bbe
Compare
1ee94ea
to
d6c84d3
Compare
d6c84d3
to
4c3fe79
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense to me
4c3fe79
to
1405944
Compare
This fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded.
1405944
to
4a6c038
Compare
All done with the comments here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
This fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded.