[clang] support pack expansions for trailing requires clauses#133190
[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]
|
zyn0217
left a comment
There was a problem hiding this comment.
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
erichkeane
left a comment
There was a problem hiding this comment.
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
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. |
This fixes a crash when evaluating constraints from trailing requires clauses, when these are part of a generic lambda which is expanded.