Skip to content

Commit e04b68f

Browse files
committed
Use normalization for concept satisfaction
1 parent 27af6bc commit e04b68f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2454
-1220
lines changed

clang/include/clang/AST/ASTConcept.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,23 @@ namespace clang {
2828

2929
class ConceptDecl;
3030
class TemplateDecl;
31+
class ConceptReference;
3132
class Expr;
3233
class NamedDecl;
3334
struct PrintingPolicy;
3435

36+
/// Pairs of unsatisfied atomic constraint expressions along with the
37+
/// substituted constraint expr, if the template arguments could be
38+
/// substituted into them, or a diagnostic if substitution resulted in
39+
/// an invalid expression.
40+
using UnsatisfiedConstraintRecord =
41+
llvm::PointerUnion<const Expr *, const ConceptReference *,
42+
std::pair<SourceLocation, StringRef> *>;
43+
3544
/// The result of a constraint satisfaction check, containing the necessary
3645
/// information to diagnose an unsatisfied constraint.
3746
class ConstraintSatisfaction : public llvm::FoldingSetNode {
47+
private:
3848
// The template-like entity that 'owns' the constraint checked here (can be a
3949
// constrained entity or a concept).
4050
const NamedDecl *ConstraintOwner = nullptr;
@@ -49,15 +59,14 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
4959
: ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {}
5060

5161
using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
52-
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
5362

5463
bool IsSatisfied = false;
5564
bool ContainsErrors = false;
5665

5766
/// \brief The substituted constraint expr, if the template arguments could be
5867
/// substituted into them, or a diagnostic if substitution resulted in an
5968
/// invalid expression.
60-
llvm::SmallVector<Detail, 4> Details;
69+
llvm::SmallVector<UnsatisfiedConstraintRecord, 4> Details;
6170

6271
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
6372
Profile(ID, C, ConstraintOwner, TemplateArgs);
@@ -75,13 +84,6 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
7584
}
7685
};
7786

78-
/// Pairs of unsatisfied atomic constraint expressions along with the
79-
/// substituted constraint expr, if the template arguments could be
80-
/// substituted into them, or a diagnostic if substitution resulted in
81-
/// an invalid expression.
82-
using UnsatisfiedConstraintRecord =
83-
llvm::PointerUnion<Expr *, std::pair<SourceLocation, StringRef> *>;
84-
8587
/// \brief The result of a constraint satisfaction check, containing the
8688
/// necessary information to diagnose an unsatisfied constraint.
8789
///
@@ -101,6 +103,10 @@ struct ASTConstraintSatisfaction final :
101103
return getTrailingObjects() + NumRecords;
102104
}
103105

106+
ArrayRef<UnsatisfiedConstraintRecord> records() const {
107+
return {begin(), end()};
108+
}
109+
104110
ASTConstraintSatisfaction(const ASTContext &C,
105111
const ConstraintSatisfaction &Satisfaction);
106112
ASTConstraintSatisfaction(const ASTContext &C,
@@ -282,6 +288,11 @@ class TypeConstraint {
282288
}
283289
};
284290

291+
/// Insertion operator for diagnostics. This allows sending TemplateName's
292+
/// into a diagnostic with <<.
293+
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
294+
const ConceptReference *C);
295+
285296
} // clang
286297

287298
#endif // LLVM_CLANG_AST_ASTCONCEPT_H

clang/include/clang/AST/ASTContext.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@ class FixedPointSemantics;
5151
struct fltSemantics;
5252
template <typename T, unsigned N> class SmallPtrSet;
5353

54+
template <> struct DenseMapInfo<llvm::FoldingSetNodeID> {
55+
static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; }
56+
57+
static FoldingSetNodeID getTombstoneKey() {
58+
FoldingSetNodeID id;
59+
for (size_t i = 0; i < sizeof(id) / sizeof(unsigned); ++i) {
60+
id.AddInteger(std::numeric_limits<unsigned>::max());
61+
}
62+
return id;
63+
}
64+
65+
static unsigned getHashValue(const FoldingSetNodeID &Val) {
66+
return Val.ComputeHash();
67+
}
68+
69+
static bool isEqual(const FoldingSetNodeID &LHS,
70+
const FoldingSetNodeID &RHS) {
71+
return LHS == RHS;
72+
}
73+
};
74+
5475
} // namespace llvm
5576

5677
namespace clang {
@@ -3852,4 +3873,26 @@ typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
38523873
return Value;
38533874
}
38543875

3876+
template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
3877+
static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; }
3878+
3879+
static FoldingSetNodeID getTombstoneKey() {
3880+
FoldingSetNodeID id;
3881+
for (size_t i = 0; i < sizeof(id) / sizeof(unsigned); ++i) {
3882+
id.AddInteger(std::numeric_limits<unsigned>::max());
3883+
}
3884+
return id;
3885+
}
3886+
3887+
static unsigned getHashValue(const FoldingSetNodeID &Val) {
3888+
return Val.ComputeHash();
3889+
}
3890+
3891+
static bool isEqual(const FoldingSetNodeID &LHS,
3892+
const FoldingSetNodeID &RHS) {
3893+
return LHS == RHS;
3894+
}
3895+
};
3896+
3897+
38553898
#endif // LLVM_CLANG_AST_ASTCONTEXT_H

clang/include/clang/AST/TemplateBase.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,6 @@ class TemplateArgument {
475475
/// Used to insert TemplateArguments into FoldingSets.
476476
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
477477
};
478-
479478
/// Location information for a TemplateArgument.
480479
struct TemplateArgumentLocInfo {
481480
struct TemplateTemplateArgLocInfo {

clang/include/clang/Sema/Sema.h

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "clang/Sema/Redeclaration.h"
6666
#include "clang/Sema/Scope.h"
6767
#include "clang/Sema/SemaBase.h"
68+
#include "clang/Sema/SemaConcept.h"
6869
#include "clang/Sema/TypoCorrection.h"
6970
#include "clang/Sema/Weak.h"
7071
#include "llvm/ADT/APInt.h"
@@ -11688,8 +11689,9 @@ class Sema final : public SemaBase {
1168811689
ExprResult
1168911690
CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
1169011691
const DeclarationNameInfo &ConceptNameInfo,
11691-
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
11692-
const TemplateArgumentListInfo *TemplateArgs);
11692+
NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
11693+
const TemplateArgumentListInfo *TemplateArgs,
11694+
bool DoCheckConstraintSatisfaction = true);
1169311695

1169411696
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
1169511697
void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
@@ -12002,6 +12004,13 @@ class Sema final : public SemaBase {
1200212004
bool UpdateArgsWithConversions = true,
1200312005
bool *ConstraintsNotSatisfied = nullptr);
1200412006

12007+
bool CheckTemplateArgumentList(
12008+
TemplateDecl *Template, TemplateParameterList *Params,
12009+
SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
12010+
const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
12011+
CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true,
12012+
bool *ConstraintsNotSatisfied = nullptr);
12013+
1200512014
bool CheckTemplateTypeArgument(
1200612015
TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
1200712016
SmallVectorImpl<TemplateArgument> &SugaredConverted,
@@ -12776,6 +12785,9 @@ class Sema final : public SemaBase {
1277612785
void MarkUsedTemplateParameters(ArrayRef<TemplateArgument> TemplateArgs,
1277712786
unsigned Depth, llvm::SmallBitVector &Used);
1277812787

12788+
void MarkUsedTemplateParameters(ArrayRef<TemplateArgumentLoc> TemplateArgs,
12789+
unsigned Depth, llvm::SmallBitVector &Used);
12790+
1277912791
void
1278012792
MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
1278112793
llvm::SmallBitVector &Deduced) {
@@ -13073,6 +13085,8 @@ class Sema final : public SemaBase {
1307313085
/// Whether we're substituting into constraints.
1307413086
bool InConstraintSubstitution;
1307513087

13088+
bool InParameterMappingSubstitution;
13089+
1307613090
/// The point of instantiation or synthesis within the source code.
1307713091
SourceLocation PointOfInstantiation;
1307813092

@@ -13338,6 +13352,11 @@ class Sema final : public SemaBase {
1333813352
const MultiLevelTemplateArgumentList &TemplateArgs,
1333913353
TemplateArgumentListInfo &Outputs);
1334013354

13355+
bool SubstTemplateArgumentsInParameterMapping(
13356+
ArrayRef<TemplateArgumentLoc> Args, SourceLocation BaseLoc,
13357+
const MultiLevelTemplateArgumentList &TemplateArgs,
13358+
TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes);
13359+
1334113360
/// Retrieve the template argument list(s) that should be used to
1334213361
/// instantiate the definition of the given declaration.
1334313362
///
@@ -13799,6 +13818,12 @@ class Sema final : public SemaBase {
1379913818
CodeSynthesisContexts.back().InConstraintSubstitution;
1380013819
}
1380113820

13821+
bool inParameterMappingSubstitution() const {
13822+
return !CodeSynthesisContexts.empty() &&
13823+
CodeSynthesisContexts.back().InParameterMappingSubstitution &&
13824+
!inConstraintSubstitution();
13825+
}
13826+
1380213827
using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>;
1380313828

1380413829
/// \brief create a Requirement::SubstitutionDiagnostic with only a
@@ -14683,6 +14708,10 @@ class Sema final : public SemaBase {
1468314708
SatisfactionStack.swap(NewSS);
1468414709
}
1468514710

14711+
using ConstrainedDeclOrNestedRequirement =
14712+
llvm::PointerUnion<const NamedDecl *,
14713+
const concepts::NestedRequirement *>;
14714+
1468614715
/// Check whether the given expression is a valid constraint expression.
1468714716
/// A diagnostic is emitted if it is not, false is returned, and
1468814717
/// PossibleNonPrimary will be set to true if the failure might be due to a
@@ -14707,44 +14736,12 @@ class Sema final : public SemaBase {
1470714736
/// \returns true if an error occurred and satisfaction could not be checked,
1470814737
/// false otherwise.
1470914738
bool CheckConstraintSatisfaction(
14710-
const NamedDecl *Template,
14739+
ConstrainedDeclOrNestedRequirement Entity,
1471114740
ArrayRef<AssociatedConstraint> AssociatedConstraints,
1471214741
const MultiLevelTemplateArgumentList &TemplateArgLists,
14713-
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
14714-
llvm::SmallVector<Expr *, 4> Converted;
14715-
return CheckConstraintSatisfaction(Template, AssociatedConstraints,
14716-
Converted, TemplateArgLists,
14717-
TemplateIDRange, Satisfaction);
14718-
}
14719-
14720-
/// \brief Check whether the given list of constraint expressions are
14721-
/// satisfied (as if in a 'conjunction') given template arguments.
14722-
/// Additionally, takes an empty list of Expressions which is populated with
14723-
/// the instantiated versions of the ConstraintExprs.
14724-
/// \param Template the template-like entity that triggered the constraints
14725-
/// check (either a concept or a constrained entity).
14726-
/// \param ConstraintExprs a list of constraint expressions, treated as if
14727-
/// they were 'AND'ed together.
14728-
/// \param ConvertedConstraints a out parameter that will get populated with
14729-
/// the instantiated version of the ConstraintExprs if we successfully checked
14730-
/// satisfaction.
14731-
/// \param TemplateArgList the multi-level list of template arguments to
14732-
/// substitute into the constraint expression. This should be relative to the
14733-
/// top-level (hence multi-level), since we need to instantiate fully at the
14734-
/// time of checking.
14735-
/// \param TemplateIDRange The source range of the template id that
14736-
/// caused the constraints check.
14737-
/// \param Satisfaction if true is returned, will contain details of the
14738-
/// satisfaction, with enough information to diagnose an unsatisfied
14739-
/// expression.
14740-
/// \returns true if an error occurred and satisfaction could not be checked,
14741-
/// false otherwise.
14742-
bool CheckConstraintSatisfaction(
14743-
const NamedDecl *Template,
14744-
ArrayRef<AssociatedConstraint> AssociatedConstraints,
14745-
llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
14746-
const MultiLevelTemplateArgumentList &TemplateArgList,
14747-
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
14742+
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
14743+
const ConceptReference *TopLevelConceptId = nullptr,
14744+
Expr **ConvertedExpr = nullptr);
1474814745

1474914746
/// \brief Check whether the given non-dependent constraint expression is
1475014747
/// satisfied. Returns false and updates Satisfaction with the satisfaction
@@ -14810,16 +14807,17 @@ class Sema final : public SemaBase {
1481014807
/// \param First whether this is the first time an unsatisfied constraint is
1481114808
/// diagnosed for this error.
1481214809
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
14810+
SourceLocation Loc = {},
1481314811
bool First = true);
1481414812

1481514813
/// \brief Emit diagnostics explaining why a constraint expression was deemed
1481614814
/// unsatisfied.
1481714815
void
14818-
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
14816+
DiagnoseUnsatisfiedConstraint(const ConceptSpecializationExpr *ConstraintExpr,
1481914817
bool First = true);
1482014818

1482114819
const NormalizedConstraint *getNormalizedAssociatedConstraints(
14822-
const NamedDecl *ConstrainedDecl,
14820+
ConstrainedDeclOrNestedRequirement Entity,
1482314821
ArrayRef<AssociatedConstraint> AssociatedConstraints);
1482414822

1482514823
/// \brief Check whether the given declaration's associated constraints are
@@ -14844,6 +14842,9 @@ class Sema final : public SemaBase {
1484414842
const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1,
1484514843
const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2);
1484614844

14845+
llvm::DenseMap<llvm::FoldingSetNodeID, CachedConceptIdConstraint>
14846+
ConceptIdSatisfactionCache;
14847+
1484714848
private:
1484814849
/// Caches pairs of template-like decls whose associated constraints were
1484914850
/// checked for subsumption and whether or not the first's constraints did in
@@ -14854,7 +14855,8 @@ class Sema final : public SemaBase {
1485414855
/// constrained declarations). If an error occurred while normalizing the
1485514856
/// associated constraints of the template or concept, nullptr will be cached
1485614857
/// here.
14857-
llvm::DenseMap<const NamedDecl *, NormalizedConstraint *> NormalizationCache;
14858+
llvm::DenseMap<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *>
14859+
NormalizationCache;
1485814860

1485914861
llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
1486014862
SatisfactionCache;

0 commit comments

Comments
 (0)