[clang] support pack expansions for trailing requires clauses (#133190)
This commit is contained in:
parent
c1ada72b09
commit
49fd0bf35d
@ -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())
|
||||
|
@ -385,6 +385,8 @@ Bug Fixes to C++ Support
|
||||
- Improved fix for an issue with pack expansions of type constraints, where this
|
||||
now also works if the constraint has non-type or template template parameters.
|
||||
(#GH131798)
|
||||
- Fix crash when evaluating the trailing requires clause of generic lambdas which are part of
|
||||
a pack expansion.
|
||||
- Fixes matching of nested template template parameters. (#GH130362)
|
||||
- Correctly diagnoses template template paramters which have a pack parameter
|
||||
not in the last position.
|
||||
|
@ -2907,6 +2907,14 @@ public:
|
||||
/// that they may be used in declarations of the same template.
|
||||
bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const;
|
||||
|
||||
/// Determine whether two 'requires' expressions are similar enough that they
|
||||
/// may be used in re-declarations.
|
||||
///
|
||||
/// Use of 'requires' isn't mandatory, works with constraints expressed in
|
||||
/// other ways too.
|
||||
bool isSameAssociatedConstraint(const AssociatedConstraint &ACX,
|
||||
const AssociatedConstraint &ACY) const;
|
||||
|
||||
/// Determine whether two 'requires' expressions are similar enough that they
|
||||
/// may be used in re-declarations.
|
||||
///
|
||||
|
@ -538,8 +538,8 @@ public:
|
||||
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;
|
||||
|
@ -81,13 +81,19 @@ enum class ImplicitParamKind;
|
||||
// Holds a constraint expression along with a pack expansion index, if
|
||||
// expanded.
|
||||
struct AssociatedConstraint {
|
||||
const Expr *ConstraintExpr;
|
||||
int ArgumentPackSubstitutionIndex;
|
||||
const Expr *ConstraintExpr = nullptr;
|
||||
int ArgumentPackSubstitutionIndex = -1;
|
||||
|
||||
constexpr AssociatedConstraint() = default;
|
||||
|
||||
explicit AssociatedConstraint(const Expr *ConstraintExpr,
|
||||
int ArgumentPackSubstitutionIndex = -1)
|
||||
: ConstraintExpr(ConstraintExpr),
|
||||
ArgumentPackSubstitutionIndex(ArgumentPackSubstitutionIndex) {}
|
||||
|
||||
explicit operator bool() const { return ConstraintExpr != nullptr; }
|
||||
|
||||
bool isNull() const { return !operator bool(); }
|
||||
};
|
||||
|
||||
/// The top declaration context.
|
||||
@ -754,7 +760,7 @@ class DeclaratorDecl : public ValueDecl {
|
||||
// and constrained function decls.
|
||||
struct ExtInfo : public QualifierInfo {
|
||||
TypeSourceInfo *TInfo = nullptr;
|
||||
Expr *TrailingRequiresClause = nullptr;
|
||||
AssociatedConstraint TrailingRequiresClause;
|
||||
};
|
||||
|
||||
llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
|
||||
@ -823,17 +829,12 @@ public:
|
||||
/// \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 AssociatedConstraint &getTrailingRequiresClause() const {
|
||||
static constexpr AssociatedConstraint Null;
|
||||
return hasExtInfo() ? getExtInfo()->TrailingRequiresClause : Null;
|
||||
}
|
||||
|
||||
const Expr *getTrailingRequiresClause() const {
|
||||
return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void setTrailingRequiresClause(Expr *TrailingRequiresClause);
|
||||
void setTrailingRequiresClause(const AssociatedConstraint &AC);
|
||||
|
||||
unsigned getNumTemplateParameterLists() const {
|
||||
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
|
||||
@ -2102,7 +2103,7 @@ protected:
|
||||
const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin,
|
||||
bool isInlineSpecified, ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause = nullptr);
|
||||
const AssociatedConstraint &TrailingRequiresClause);
|
||||
|
||||
using redeclarable_base = Redeclarable<FunctionDecl>;
|
||||
|
||||
@ -2138,7 +2139,7 @@ public:
|
||||
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin = false,
|
||||
bool isInlineSpecified = false, bool hasWrittenPrototype = true,
|
||||
ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified,
|
||||
Expr *TrailingRequiresClause = nullptr) {
|
||||
const AssociatedConstraint &TrailingRequiresClause = {}) {
|
||||
DeclarationNameInfo NameInfo(N, NLoc);
|
||||
return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC,
|
||||
UsesFPIntrin, isInlineSpecified,
|
||||
@ -2151,7 +2152,7 @@ public:
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified,
|
||||
bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause);
|
||||
const AssociatedConstraint &TrailingRequiresClause);
|
||||
|
||||
static FunctionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
|
||||
|
||||
@ -2644,9 +2645,9 @@ public:
|
||||
/// Use this instead of getTrailingRequiresClause for concepts APIs that
|
||||
/// accept an ArrayRef of constraint expressions.
|
||||
void
|
||||
getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &AC) const {
|
||||
if (auto *TRC = getTrailingRequiresClause())
|
||||
AC.emplace_back(TRC);
|
||||
getAssociatedConstraints(SmallVectorImpl<AssociatedConstraint> &ACs) const {
|
||||
if (const AssociatedConstraint &AC = getTrailingRequiresClause())
|
||||
ACs.emplace_back(AC);
|
||||
}
|
||||
|
||||
/// Get the message that indicates why this function was deleted.
|
||||
|
@ -1974,7 +1974,7 @@ private:
|
||||
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 @@ public:
|
||||
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 @@ protected:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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() ||
|
||||
@ -2859,7 +2859,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) {
|
||||
@ -2874,7 +2874,7 @@ public:
|
||||
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);
|
||||
@ -2925,7 +2925,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),
|
||||
@ -2943,7 +2943,7 @@ public:
|
||||
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() {
|
||||
|
@ -2129,7 +2129,7 @@ public:
|
||||
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(); }
|
||||
|
@ -2253,8 +2253,10 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
|
||||
}
|
||||
|
||||
// Visit the trailing requires clause, if any.
|
||||
if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
|
||||
TRY_TO(TraverseStmt(TrailingRequiresClause));
|
||||
if (const AssociatedConstraint &TrailingRequiresClause =
|
||||
D->getTrailingRequiresClause()) {
|
||||
TRY_TO(TraverseStmt(
|
||||
const_cast<Expr *>(TrailingRequiresClause.ConstraintExpr)));
|
||||
}
|
||||
|
||||
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
@ -2768,7 +2770,8 @@ DEF_TRAVERSE_STMT(LambdaExpr, {
|
||||
|
||||
if (S->hasExplicitResultType())
|
||||
TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getTrailingRequiresClause());
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(
|
||||
const_cast<Expr *>(S->getTrailingRequiresClause().ConstraintExpr));
|
||||
|
||||
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
|
||||
}
|
||||
|
@ -8867,11 +8867,13 @@ public:
|
||||
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,
|
||||
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.
|
||||
|
@ -7070,6 +7070,15 @@ bool ASTContext::hasSameTemplateName(const TemplateName &X,
|
||||
getCanonicalTemplateName(Y, IgnoreDeduced);
|
||||
}
|
||||
|
||||
bool ASTContext::isSameAssociatedConstraint(
|
||||
const AssociatedConstraint &ACX, const AssociatedConstraint &ACY) const {
|
||||
if (ACX.ArgumentPackSubstitutionIndex != ACY.ArgumentPackSubstitutionIndex)
|
||||
return false;
|
||||
if (!isSameConstraintExpr(ACX.ConstraintExpr, ACY.ConstraintExpr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTContext::isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const {
|
||||
if (!XCE != !YCE)
|
||||
return false;
|
||||
@ -7386,7 +7395,7 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isSameConstraintExpr(FuncX->getTrailingRequiresClause(),
|
||||
if (!isSameAssociatedConstraint(FuncX->getTrailingRequiresClause(),
|
||||
FuncY->getTrailingRequiresClause()))
|
||||
return false;
|
||||
|
||||
|
@ -3915,8 +3915,9 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
auto ToEndLoc = importChecked(Err, D->getEndLoc());
|
||||
auto ToDefaultLoc = importChecked(Err, D->getDefaultLoc());
|
||||
auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
|
||||
auto TrailingRequiresClause =
|
||||
importChecked(Err, D->getTrailingRequiresClause());
|
||||
AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause();
|
||||
TrailingRequiresClause.ConstraintExpr =
|
||||
importChecked(Err, TrailingRequiresClause.ConstraintExpr);
|
||||
if (Err)
|
||||
return std::move(Err);
|
||||
|
||||
|
@ -2009,8 +2009,8 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
|
||||
}
|
||||
}
|
||||
|
||||
void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
|
||||
assert(TrailingRequiresClause);
|
||||
void DeclaratorDecl::setTrailingRequiresClause(const AssociatedConstraint &AC) {
|
||||
assert(AC);
|
||||
// Make sure the extended decl info is allocated.
|
||||
if (!hasExtInfo()) {
|
||||
// Save (non-extended) type source info pointer.
|
||||
@ -2021,7 +2021,7 @@ void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
|
||||
getExtInfo()->TInfo = savedTInfo;
|
||||
}
|
||||
// Set requires clause info.
|
||||
getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
|
||||
getExtInfo()->TrailingRequiresClause = AC;
|
||||
}
|
||||
|
||||
void DeclaratorDecl::setTemplateParameterListsInfo(
|
||||
@ -3047,7 +3047,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||
TypeSourceInfo *TInfo, StorageClass S,
|
||||
bool UsesFPIntrin, bool isInlineSpecified,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause)
|
||||
const AssociatedConstraint &TrailingRequiresClause)
|
||||
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
|
||||
StartLoc),
|
||||
DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
|
||||
@ -3571,7 +3571,7 @@ bool FunctionDecl::isMemberLikeConstrainedFriend() const {
|
||||
// If these friends don't have constraints, they aren't constrained, and
|
||||
// thus don't fall under temp.friend p9. Else the simple presence of a
|
||||
// constraint makes them unique.
|
||||
return getTrailingRequiresClause();
|
||||
return !getTrailingRequiresClause().isNull();
|
||||
}
|
||||
|
||||
return FriendConstraintRefersToEnclosingTemplate();
|
||||
@ -5453,7 +5453,7 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
|
||||
bool isInlineSpecified, bool hasWrittenPrototype,
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
Expr *TrailingRequiresClause) {
|
||||
const AssociatedConstraint &TrailingRequiresClause) {
|
||||
FunctionDecl *New = new (C, DC) FunctionDecl(
|
||||
Function, C, DC, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
|
||||
isInlineSpecified, ConstexprKind, TrailingRequiresClause);
|
||||
@ -5464,7 +5464,8 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
||||
return new (C, ID) FunctionDecl(
|
||||
Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(),
|
||||
nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr);
|
||||
nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified,
|
||||
/*TrailingRequiresClause=*/{});
|
||||
}
|
||||
|
||||
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
||||
|
@ -2304,7 +2304,7 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
|
||||
ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
|
||||
TypeSourceInfo *TInfo, SourceLocation EndLocation, CXXConstructorDecl *Ctor,
|
||||
DeductionCandidate Kind, Expr *TrailingRequiresClause,
|
||||
DeductionCandidate Kind, const AssociatedConstraint &TrailingRequiresClause,
|
||||
const CXXDeductionGuideDecl *GeneratedFrom,
|
||||
SourceDeductionGuideKind SourceKind) {
|
||||
return new (C, DC) CXXDeductionGuideDecl(
|
||||
@ -2318,7 +2318,7 @@ CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
||||
C, /*DC=*/nullptr, SourceLocation(), ExplicitSpecifier(),
|
||||
DeclarationNameInfo(), QualType(), /*TInfo=*/nullptr, SourceLocation(),
|
||||
/*Ctor=*/nullptr, DeductionCandidate::Normal,
|
||||
/*TrailingRequiresClause=*/nullptr,
|
||||
/*TrailingRequiresClause=*/{},
|
||||
/*GeneratedFrom=*/nullptr, SourceDeductionGuideKind::None);
|
||||
}
|
||||
|
||||
@ -2427,7 +2427,7 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin,
|
||||
bool isInline, ConstexprSpecKind ConstexprKind,
|
||||
SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause) {
|
||||
const AssociatedConstraint &TrailingRequiresClause) {
|
||||
return new (C, RD) CXXMethodDecl(
|
||||
CXXMethod, C, RD, StartLoc, NameInfo, T, TInfo, SC, UsesFPIntrin,
|
||||
isInline, ConstexprKind, EndLocation, TrailingRequiresClause);
|
||||
@ -2435,10 +2435,11 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
|
||||
CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID) {
|
||||
return new (C, ID) CXXMethodDecl(
|
||||
CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
|
||||
QualType(), nullptr, SC_None, false, false,
|
||||
ConstexprSpecKind::Unspecified, SourceLocation(), nullptr);
|
||||
return new (C, ID)
|
||||
CXXMethodDecl(CXXMethod, C, nullptr, SourceLocation(),
|
||||
DeclarationNameInfo(), QualType(), nullptr, SC_None, false,
|
||||
false, ConstexprSpecKind::Unspecified, SourceLocation(),
|
||||
/*TrailingRequiresClause=*/{});
|
||||
}
|
||||
|
||||
CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
|
||||
@ -2834,7 +2835,8 @@ CXXConstructorDecl::CXXConstructorDecl(
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
|
||||
InheritedConstructor Inherited, Expr *TrailingRequiresClause)
|
||||
InheritedConstructor Inherited,
|
||||
const AssociatedConstraint &TrailingRequiresClause)
|
||||
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
|
||||
SC_None, UsesFPIntrin, isInline, ConstexprKind,
|
||||
SourceLocation(), TrailingRequiresClause) {
|
||||
@ -2861,7 +2863,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
|
||||
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
|
||||
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
|
||||
ExplicitSpecifier(), false, false, false, ConstexprSpecKind::Unspecified,
|
||||
InheritedConstructor(), nullptr);
|
||||
InheritedConstructor(), /*TrailingRequiresClause=*/{});
|
||||
Result->setInheritingConstructor(isInheritingConstructor);
|
||||
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
|
||||
hasTrailingExplicit;
|
||||
@ -2874,7 +2876,8 @@ CXXConstructorDecl *CXXConstructorDecl::Create(
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline,
|
||||
bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind,
|
||||
InheritedConstructor Inherited, Expr *TrailingRequiresClause) {
|
||||
InheritedConstructor Inherited,
|
||||
const AssociatedConstraint &TrailingRequiresClause) {
|
||||
assert(NameInfo.getName().getNameKind()
|
||||
== DeclarationName::CXXConstructorName &&
|
||||
"Name must refer to a constructor");
|
||||
@ -3000,14 +3003,16 @@ CXXDestructorDecl *CXXDestructorDecl::CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID) {
|
||||
return new (C, ID) CXXDestructorDecl(
|
||||
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
|
||||
false, false, false, ConstexprSpecKind::Unspecified, nullptr);
|
||||
false, false, false, ConstexprSpecKind::Unspecified,
|
||||
/*TrailingRequiresClause=*/{});
|
||||
}
|
||||
|
||||
CXXDestructorDecl *CXXDestructorDecl::Create(
|
||||
ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
|
||||
ConstexprSpecKind ConstexprKind, Expr *TrailingRequiresClause) {
|
||||
ConstexprSpecKind ConstexprKind,
|
||||
const AssociatedConstraint &TrailingRequiresClause) {
|
||||
assert(NameInfo.getName().getNameKind()
|
||||
== DeclarationName::CXXDestructorName &&
|
||||
"Name must refer to a destructor");
|
||||
@ -3062,7 +3067,7 @@ CXXConversionDecl *CXXConversionDecl::CreateDeserialized(ASTContext &C,
|
||||
return new (C, ID) CXXConversionDecl(
|
||||
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
|
||||
false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified,
|
||||
SourceLocation(), nullptr);
|
||||
SourceLocation(), /*TrailingRequiresClause=*/{});
|
||||
}
|
||||
|
||||
CXXConversionDecl *CXXConversionDecl::Create(
|
||||
@ -3070,7 +3075,7 @@ CXXConversionDecl *CXXConversionDecl::Create(
|
||||
const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
|
||||
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
|
||||
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
|
||||
Expr *TrailingRequiresClause) {
|
||||
const AssociatedConstraint &TrailingRequiresClause) {
|
||||
assert(NameInfo.getName().getNameKind()
|
||||
== DeclarationName::CXXConversionFunctionName &&
|
||||
"Name must refer to a conversion function");
|
||||
|
@ -842,10 +842,14 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
}
|
||||
Out << Proto;
|
||||
|
||||
if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
|
||||
if (const AssociatedConstraint &TrailingRequiresClause =
|
||||
D->getTrailingRequiresClause()) {
|
||||
Out << " requires ";
|
||||
TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation,
|
||||
"\n", &Context);
|
||||
// FIXME: The printer could support printing expressions and types as if
|
||||
// expanded by an index. Pass in the ArgumentPackSubstitutionIndex when
|
||||
// that's supported.
|
||||
TrailingRequiresClause.ConstraintExpr->printPretty(
|
||||
Out, nullptr, SubPolicy, Indentation, "\n", &Context);
|
||||
}
|
||||
} else {
|
||||
Ty.print(Out, Policy, Proto);
|
||||
|
@ -291,7 +291,7 @@ void TemplateDecl::getAssociatedConstraints(
|
||||
llvm::SmallVectorImpl<AssociatedConstraint> &ACs) const {
|
||||
TemplateParams->getAssociatedConstraints(ACs);
|
||||
if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl()))
|
||||
if (const Expr *TRC = FD->getTrailingRequiresClause())
|
||||
if (const AssociatedConstraint &TRC = FD->getTrailingRequiresClause())
|
||||
ACs.emplace_back(TRC);
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ bool TemplateDecl::hasAssociatedConstraints() const {
|
||||
if (TemplateParams->hasAssociatedConstraints())
|
||||
return true;
|
||||
if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl()))
|
||||
return FD->getTrailingRequiresClause();
|
||||
return static_cast<bool>(FD->getTrailingRequiresClause());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1402,7 +1402,7 @@ ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const {
|
||||
return Record->getLambdaExplicitTemplateParameters();
|
||||
}
|
||||
|
||||
Expr *LambdaExpr::getTrailingRequiresClause() const {
|
||||
const AssociatedConstraint &LambdaExpr::getTrailingRequiresClause() const {
|
||||
return getCallOperator()->getTrailingRequiresClause();
|
||||
}
|
||||
|
||||
|
@ -3781,7 +3781,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
|
||||
|
||||
if (FD) {
|
||||
FunctionTypeDepth.enterResultType();
|
||||
mangleRequiresClause(FD->getTrailingRequiresClause());
|
||||
mangleRequiresClause(FD->getTrailingRequiresClause().ConstraintExpr);
|
||||
}
|
||||
|
||||
FunctionTypeDepth.pop(saved);
|
||||
|
@ -584,7 +584,8 @@ public:
|
||||
|
||||
if (LE->hasExplicitResultType())
|
||||
TraverseTypeLoc(Proto.getReturnLoc());
|
||||
TraverseStmt(LE->getTrailingRequiresClause());
|
||||
TraverseStmt(
|
||||
const_cast<Expr *>(LE->getTrailingRequiresClause().ConstraintExpr));
|
||||
}
|
||||
|
||||
TraverseStmt(LE->getBody());
|
||||
|
@ -132,8 +132,8 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
if (auto *C = D->getTrailingRequiresClause())
|
||||
IndexCtx.indexBody(C, Parent);
|
||||
if (const AssociatedConstraint &C = D->getTrailingRequiresClause())
|
||||
IndexCtx.indexBody(C.ConstraintExpr, Parent);
|
||||
}
|
||||
|
||||
bool handleObjCMethod(const ObjCMethodDecl *D,
|
||||
|
@ -848,10 +848,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
|
||||
ForOverloadResolution);
|
||||
|
||||
return CheckConstraintSatisfaction(
|
||||
FD,
|
||||
AssociatedConstraint(FD->getTrailingRequiresClause(),
|
||||
ArgumentPackSubstitutionIndex),
|
||||
*MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
|
||||
FD, FD->getTrailingRequiresClause(), *MLTAL,
|
||||
SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
|
||||
Satisfaction);
|
||||
}
|
||||
|
||||
|
@ -9353,7 +9353,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
||||
SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC,
|
||||
SemaRef.getCurFPFeatures().isFPConstrained(), isInline, HasPrototype,
|
||||
ConstexprSpecKind::Unspecified,
|
||||
/*TrailingRequiresClause=*/nullptr);
|
||||
/*TrailingRequiresClause=*/{});
|
||||
if (D.isInvalidType())
|
||||
NewFD->setInvalidDecl();
|
||||
|
||||
@ -9361,7 +9361,7 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
||||
}
|
||||
|
||||
ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
|
||||
Expr *TrailingRequiresClause = D.getTrailingRequiresClause();
|
||||
AssociatedConstraint TrailingRequiresClause(D.getTrailingRequiresClause());
|
||||
|
||||
SemaRef.CheckExplicitObjectMemberFunction(DC, D, Name, R);
|
||||
|
||||
@ -10531,7 +10531,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
diag::ext_operator_new_delete_declared_inline)
|
||||
<< NewFD->getDeclName();
|
||||
|
||||
if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
|
||||
if (const Expr *TRC = NewFD->getTrailingRequiresClause().ConstraintExpr) {
|
||||
// C++20 [dcl.decl.general]p4:
|
||||
// The optional requires-clause in an init-declarator or
|
||||
// member-declarator shall be present only if the declarator declares a
|
||||
@ -12261,7 +12261,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||
if (Method->isVirtual() && NewFD->getTrailingRequiresClause())
|
||||
// C++2a [class.virtual]p6
|
||||
// A virtual method shall not have a requires-clause.
|
||||
Diag(NewFD->getTrailingRequiresClause()->getBeginLoc(),
|
||||
Diag(NewFD->getTrailingRequiresClause().ConstraintExpr->getBeginLoc(),
|
||||
diag::err_constrained_virtual_method);
|
||||
|
||||
if (Method->isStatic())
|
||||
@ -19085,8 +19085,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
|
||||
SmallVector<bool, 4> SatisfactionStatus;
|
||||
|
||||
for (CXXMethodDecl *Method : Methods) {
|
||||
const Expr *Constraints = Method->getTrailingRequiresClause();
|
||||
if (!Constraints)
|
||||
if (!Method->getTrailingRequiresClause())
|
||||
SatisfactionStatus.push_back(true);
|
||||
else {
|
||||
ConstraintSatisfaction Satisfaction;
|
||||
@ -19105,7 +19104,7 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
|
||||
if (FunctionDecl *MF = OrigMethod->getInstantiatedFromMemberFunction())
|
||||
OrigMethod = cast<CXXMethodDecl>(MF);
|
||||
|
||||
const Expr *Constraints = OrigMethod->getTrailingRequiresClause();
|
||||
AssociatedConstraint Orig = OrigMethod->getTrailingRequiresClause();
|
||||
bool AnotherMethodIsMoreConstrained = false;
|
||||
for (size_t j = 0; j < Methods.size(); j++) {
|
||||
if (i == j || !SatisfactionStatus[j])
|
||||
@ -19118,15 +19117,13 @@ static void SetEligibleMethods(Sema &S, CXXRecordDecl *Record,
|
||||
CSM))
|
||||
continue;
|
||||
|
||||
const Expr *OtherConstraints = OtherMethod->getTrailingRequiresClause();
|
||||
if (!OtherConstraints)
|
||||
AssociatedConstraint Other = OtherMethod->getTrailingRequiresClause();
|
||||
if (!Other)
|
||||
continue;
|
||||
if (!Constraints) {
|
||||
if (!Orig) {
|
||||
AnotherMethodIsMoreConstrained = true;
|
||||
break;
|
||||
}
|
||||
AssociatedConstraint Other(OtherConstraints);
|
||||
AssociatedConstraint Orig(Constraints);
|
||||
if (S.IsAtLeastAsConstrained(OtherMethod, {Other}, OrigMethod, {Orig},
|
||||
AnotherMethodIsMoreConstrained)) {
|
||||
// There was an error with the constraints comparison. Exit the loop
|
||||
|
@ -18995,8 +18995,8 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
|
||||
return true;
|
||||
|
||||
// Check the trailing requires clause
|
||||
if (Expr *E = Method->getTrailingRequiresClause())
|
||||
if (!Finder.TraverseStmt(E))
|
||||
if (const AssociatedConstraint &TRC = Method->getTrailingRequiresClause())
|
||||
if (!Finder.TraverseStmt(const_cast<Expr *>(TRC.ConstraintExpr)))
|
||||
return true;
|
||||
|
||||
return checkThisInStaticMemberFunctionAttributes(Method);
|
||||
|
@ -990,7 +990,7 @@ private:
|
||||
followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);
|
||||
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) {
|
||||
TrailingRequiresClause = FD->getTrailingRequiresClause();
|
||||
TrailingRequiresClause = FD->getTrailingRequiresClause().ConstraintExpr;
|
||||
|
||||
// Note that FD->getType->getAs<FunctionProtoType>() can yield a
|
||||
// noexcept Expr which has been boiled down to a constant expression.
|
||||
|
@ -1015,7 +1015,7 @@ CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
|
||||
QualType(), /*Tinfo=*/nullptr, SC_None,
|
||||
getCurFPFeatures().isFPConstrained(),
|
||||
/*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(),
|
||||
/*TrailingRequiresClause=*/nullptr);
|
||||
/*TrailingRequiresClause=*/{});
|
||||
Method->setAccess(AS_public);
|
||||
return Method;
|
||||
}
|
||||
@ -1033,7 +1033,8 @@ void Sema::AddTemplateParametersToLambdaCallOperator(
|
||||
|
||||
void Sema::CompleteLambdaCallOperator(
|
||||
CXXMethodDecl *Method, SourceLocation LambdaLoc,
|
||||
SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
|
||||
SourceLocation CallOperatorLoc,
|
||||
const AssociatedConstraint &TrailingRequiresClause,
|
||||
TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
|
||||
StorageClass SC, ArrayRef<ParmVarDecl *> Params,
|
||||
bool HasExplicitResultType) {
|
||||
@ -1461,8 +1462,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
||||
|
||||
CompleteLambdaCallOperator(
|
||||
Method, Intro.Range.getBegin(), CallOperatorLoc,
|
||||
ParamInfo.getTrailingRequiresClause(), MethodTyInfo,
|
||||
ParamInfo.getDeclSpec().getConstexprSpecifier(),
|
||||
AssociatedConstraint(ParamInfo.getTrailingRequiresClause(),
|
||||
/*ArgumentPackSubstitutionIndex=*/-1),
|
||||
MethodTyInfo, ParamInfo.getDeclSpec().getConstexprSpecifier(),
|
||||
IsLambdaStatic ? SC_Static : SC_None, Params, ExplicitResultType);
|
||||
|
||||
CheckCXXDefaultArguments(Method);
|
||||
@ -1545,7 +1547,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
||||
// The optional requires-clause ([temp.pre]) in an init-declarator or
|
||||
// member-declarator shall be present only if the declarator declares a
|
||||
// templated function ([dcl.fct]).
|
||||
if (Expr *TRC = Method->getTrailingRequiresClause()) {
|
||||
if (const AssociatedConstraint &TRC = Method->getTrailingRequiresClause()) {
|
||||
// [temp.pre]/8:
|
||||
// An entity is templated if it is
|
||||
// - a template,
|
||||
@ -1568,7 +1570,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
|
||||
// applies to the call operator, which we already know is a member function,
|
||||
// AND defined.
|
||||
if (!Method->getDescribedFunctionTemplate() && !Method->isTemplated()) {
|
||||
Diag(TRC->getBeginLoc(), diag::err_constrained_non_templated_function);
|
||||
Diag(TRC.ConstraintExpr->getBeginLoc(),
|
||||
diag::err_constrained_non_templated_function);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1791,7 +1794,8 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange,
|
||||
|
||||
// A non-generic lambda may still be a templated entity. We need to preserve
|
||||
// constraints when converting the lambda to a function pointer. See GH63181.
|
||||
if (Expr *Requires = CallOperator->getTrailingRequiresClause())
|
||||
if (const AssociatedConstraint &Requires =
|
||||
CallOperator->getTrailingRequiresClause())
|
||||
Conversion->setTrailingRequiresClause(Requires);
|
||||
|
||||
if (Class->isGenericLambda()) {
|
||||
|
@ -1551,12 +1551,16 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
|
||||
|
||||
if (!UseOverrideRules &&
|
||||
New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
|
||||
Expr *NewRC = New->getTrailingRequiresClause(),
|
||||
*OldRC = Old->getTrailingRequiresClause();
|
||||
if ((NewRC != nullptr) != (OldRC != nullptr))
|
||||
AssociatedConstraint NewRC = New->getTrailingRequiresClause(),
|
||||
OldRC = Old->getTrailingRequiresClause();
|
||||
if (!NewRC != !OldRC)
|
||||
return true;
|
||||
if (NewRC.ArgumentPackSubstitutionIndex !=
|
||||
OldRC.ArgumentPackSubstitutionIndex)
|
||||
return true;
|
||||
if (NewRC &&
|
||||
!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC, NewDecl, NewRC))
|
||||
!SemaRef.AreConstraintExpressionsEqual(OldDecl, OldRC.ConstraintExpr,
|
||||
NewDecl, NewRC.ConstraintExpr))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ buildDeductionGuide(Sema &SemaRef, TemplateDecl *OriginalTemplate,
|
||||
TypeSourceInfo *TInfo, SourceLocation LocStart,
|
||||
SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
|
||||
llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {},
|
||||
Expr *FunctionTrailingRC = nullptr) {
|
||||
const AssociatedConstraint &FunctionTrailingRC = {}) {
|
||||
DeclContext *DC = OriginalTemplate->getDeclContext();
|
||||
auto DeductionGuideName =
|
||||
SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
|
||||
@ -356,7 +356,8 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
TemplateParameterList *TemplateParams =
|
||||
SemaRef.GetTemplateParameterList(Template);
|
||||
SmallVector<TemplateArgument, 16> Depth1Args;
|
||||
Expr *OuterRC = TemplateParams->getRequiresClause();
|
||||
AssociatedConstraint OuterRC(TemplateParams->getRequiresClause(),
|
||||
/*ArgumentPackSubstitutionIndex=*/-1);
|
||||
if (FTD) {
|
||||
TemplateParameterList *InnerParams = FTD->getTemplateParameters();
|
||||
SmallVector<NamedDecl *, 16> AllParams;
|
||||
@ -456,18 +457,20 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
// At this point, the function parameters are already 'instantiated' in the
|
||||
// current scope. Substitute into the constructor's trailing
|
||||
// requires-clause, if any.
|
||||
Expr *FunctionTrailingRC = nullptr;
|
||||
if (Expr *RC = CD->getTrailingRequiresClause()) {
|
||||
AssociatedConstraint FunctionTrailingRC;
|
||||
if (const AssociatedConstraint &RC = CD->getTrailingRequiresClause()) {
|
||||
MultiLevelTemplateArgumentList Args;
|
||||
Args.setKind(TemplateSubstitutionKind::Rewrite);
|
||||
Args.addOuterTemplateArguments(Depth1Args);
|
||||
Args.addOuterRetainedLevel();
|
||||
if (NestedPattern)
|
||||
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
|
||||
ExprResult E = SemaRef.SubstConstraintExprWithoutSatisfaction(RC, Args);
|
||||
ExprResult E = SemaRef.SubstConstraintExprWithoutSatisfaction(
|
||||
const_cast<Expr *>(RC.ConstraintExpr), Args);
|
||||
if (!E.isUsable())
|
||||
return nullptr;
|
||||
FunctionTrailingRC = E.get();
|
||||
FunctionTrailingRC =
|
||||
AssociatedConstraint(E.get(), RC.ArgumentPackSubstitutionIndex);
|
||||
}
|
||||
|
||||
// C++ [over.match.class.deduct]p1:
|
||||
@ -480,13 +483,19 @@ struct ConvertConstructorToDeductionGuideTransform {
|
||||
if (OuterRC) {
|
||||
// The outer template parameters are not transformed, so their
|
||||
// associated constraints don't need substitution.
|
||||
// FIXME: Should simply add another field for the OuterRC, instead of
|
||||
// combining them like this.
|
||||
if (!FunctionTrailingRC)
|
||||
FunctionTrailingRC = OuterRC;
|
||||
else
|
||||
FunctionTrailingRC = BinaryOperator::Create(
|
||||
SemaRef.Context, /*lhs=*/OuterRC, /*rhs=*/FunctionTrailingRC,
|
||||
FunctionTrailingRC = AssociatedConstraint(
|
||||
BinaryOperator::Create(
|
||||
SemaRef.Context,
|
||||
/*lhs=*/const_cast<Expr *>(OuterRC.ConstraintExpr),
|
||||
/*rhs=*/const_cast<Expr *>(FunctionTrailingRC.ConstraintExpr),
|
||||
BO_LAnd, SemaRef.Context.BoolTy, VK_PRValue, OK_Ordinary,
|
||||
TemplateParams->getTemplateLoc(), FPOptionsOverride());
|
||||
TemplateParams->getTemplateLoc(), FPOptionsOverride()),
|
||||
FunctionTrailingRC.ArgumentPackSubstitutionIndex);
|
||||
}
|
||||
|
||||
return buildDeductionGuide(
|
||||
@ -1238,14 +1247,20 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
|
||||
// FIXME: Here the synthesized deduction guide is not a templated
|
||||
// function. Per [dcl.decl]p4, the requires-clause shall be present only
|
||||
// if the declarator declares a templated function, a bug in standard?
|
||||
auto *Constraint = buildIsDeducibleConstraint(
|
||||
SemaRef, AliasTemplate, Transformed->getReturnType(), {});
|
||||
if (auto *RC = DG->getTrailingRequiresClause()) {
|
||||
auto Conjunction =
|
||||
SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{},
|
||||
BinaryOperatorKind::BO_LAnd, RC, Constraint);
|
||||
if (!Conjunction.isInvalid())
|
||||
Constraint = Conjunction.getAs<Expr>();
|
||||
AssociatedConstraint Constraint(
|
||||
buildIsDeducibleConstraint(SemaRef, AliasTemplate,
|
||||
Transformed->getReturnType(), {}),
|
||||
/*ArgumentPackSubstitutionIndex=*/-1);
|
||||
if (const AssociatedConstraint &RC = DG->getTrailingRequiresClause()) {
|
||||
auto Conjunction = SemaRef.BuildBinOp(
|
||||
SemaRef.getCurScope(), SourceLocation{},
|
||||
BinaryOperatorKind::BO_LAnd, const_cast<Expr *>(RC.ConstraintExpr),
|
||||
const_cast<Expr *>(Constraint.ConstraintExpr));
|
||||
if (!Conjunction.isInvalid()) {
|
||||
Constraint.ConstraintExpr = Conjunction.getAs<Expr>();
|
||||
Constraint.ArgumentPackSubstitutionIndex =
|
||||
RC.ArgumentPackSubstitutionIndex;
|
||||
}
|
||||
}
|
||||
Transformed->setTrailingRequiresClause(Constraint);
|
||||
continue;
|
||||
|
@ -2671,7 +2671,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
|
||||
AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause();
|
||||
|
||||
// If we're instantiating a local function declaration, put the result
|
||||
// in the enclosing namespace; otherwise we need to find the instantiated
|
||||
@ -3102,7 +3102,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
||||
}
|
||||
|
||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
|
||||
Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
|
||||
AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause();
|
||||
|
||||
DeclarationNameInfo NameInfo
|
||||
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
|
||||
|
@ -15659,10 +15659,13 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
|
||||
auto FPTL = NewCallOpTSI->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>();
|
||||
assert(FPTL && "Not a FunctionProtoType?");
|
||||
|
||||
AssociatedConstraint TRC = E->getCallOperator()->getTrailingRequiresClause();
|
||||
if (TRC.ArgumentPackSubstitutionIndex == -1)
|
||||
TRC.ArgumentPackSubstitutionIndex = SemaRef.ArgumentPackSubstitutionIndex;
|
||||
|
||||
getSema().CompleteLambdaCallOperator(
|
||||
NewCallOperator, E->getCallOperator()->getLocation(),
|
||||
E->getCallOperator()->getInnerLocStart(),
|
||||
E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
|
||||
E->getCallOperator()->getInnerLocStart(), TRC, NewCallOpTSI,
|
||||
E->getCallOperator()->getConstexprKind(),
|
||||
E->getCallOperator()->getStorageClass(), FPTL.getParams(),
|
||||
E->hasExplicitResultType());
|
||||
|
@ -904,7 +904,8 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
||||
if (Record.readInt()) { // hasExtInfo
|
||||
auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo();
|
||||
Record.readQualifierInfo(*Info);
|
||||
Info->TrailingRequiresClause = Record.readExpr();
|
||||
Info->TrailingRequiresClause =
|
||||
AssociatedConstraint(Record.readExpr(), int(Record.readInt()));
|
||||
DD->DeclInfo = Info;
|
||||
}
|
||||
QualType TSIType = Record.readType();
|
||||
|
@ -728,7 +728,10 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
|
||||
if (D->hasExtInfo()) {
|
||||
DeclaratorDecl::ExtInfo *Info = D->getExtInfo();
|
||||
Record.AddQualifierInfo(*Info);
|
||||
Record.AddStmt(Info->TrailingRequiresClause);
|
||||
Record.AddStmt(
|
||||
const_cast<Expr *>(Info->TrailingRequiresClause.ConstraintExpr));
|
||||
Record.push_back(
|
||||
Info->TrailingRequiresClause.ArgumentPackSubstitutionIndex);
|
||||
}
|
||||
// The location information is deferred until the end of the record.
|
||||
Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType()
|
||||
|
@ -267,6 +267,15 @@ static_assert(bazz<1, 2>()(1));
|
||||
// expected-error@-1 {{is ambiguous}}
|
||||
// expected-note@#bazz 2{{candidate function [with value:auto = int]}}
|
||||
|
||||
template <class T> concept C2 = sizeof(T) >= sizeof(int);
|
||||
template <class... Ts> static constexpr auto trailing() {
|
||||
return Overloaded{[](auto) requires (C2<Ts> && C2<int>) { return 0; }...}; // #trailing
|
||||
}
|
||||
static_assert(trailing<int, long>()(0));
|
||||
// expected-error@-1 {{is ambiguous}}
|
||||
// expected-note@#trailing 2{{candidate function [with auto:1 = int]}}
|
||||
|
||||
|
||||
} // namespace GH101754
|
||||
|
||||
namespace GH131798 {
|
||||
|
@ -872,7 +872,7 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
|
||||
// FIXME: Attributes?
|
||||
}
|
||||
|
||||
if (auto *E = ND->getTrailingRequiresClause()) {
|
||||
if (auto *E = ND->getTrailingRequiresClause().ConstraintExpr) {
|
||||
if (Visit(E))
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user