Skip to content

Commit ff960ea

Browse files
cor3ntinmahesh-attarde
authored andcommitted
1 parent ab95f8e commit ff960ea

Some content is hidden

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

50 files changed

+1197
-2638
lines changed

clang/docs/InternalsManual.rst

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2859,67 +2859,6 @@ This library is called by the :ref:`Parser library <Parser>` during parsing to
28592859
do semantic analysis of the input. For valid programs, Sema builds an AST for
28602860
parsed constructs.
28612861

2862-
2863-
Concept Satisfaction Checking and Subsumption
2864-
---------------------------------------------
2865-
2866-
As per the C++ standard, constraints are `normalized <https://eel.is/c++draft/temp.constr.normal>`_
2867-
and the normal form is used both for subsumption, and constraint checking.
2868-
Both depend on a parameter mapping that substitutes lazily. In particular,
2869-
we should not substitute in unused arguments.
2870-
2871-
Clang follows the order of operations prescribed by the standard.
2872-
2873-
Normalization happens prior to satisfaction and subsumption
2874-
and is handled by ``NormalizedConstraint``.
2875-
2876-
Clang preserves in the normalized form intermediate concept-ids
2877-
(``ConceptIdConstraint``) This is used for diagnostics only and no substitution
2878-
happens in a ConceptIdConstraint if its expression is satisfied.
2879-
2880-
The normal form of the associated constraints of a declaration is cached in
2881-
Sema::NormalizationCache such that it is only computed once.
2882-
2883-
A ``NormalizedConstraint`` is a recursive data structure, where each node
2884-
contains a parameter mapping, represented by the indexes of all parameter
2885-
being used.
2886-
2887-
Checking satisfaction is done by ``ConstraintSatisfactionChecker``, recursively
2888-
walking ``NormalizedConstraint``. At each level, we substitute the outermost
2889-
level of the template arguments referenced in the parameter mapping of a
2890-
normalized expression (``MultiLevelTemplateArgumentList``).
2891-
2892-
For the following example,
2893-
2894-
.. code-block:: c++
2895-
2896-
template <typename T>
2897-
concept A = __is_same(T, int);
2898-
2899-
template <typename U>
2900-
concept B = A<U> && __is_same(U, int);
2901-
2902-
The normal form of B is
2903-
2904-
.. code-block:: c++
2905-
2906-
__is_same(T, int) /*T->U, innermost level*/
2907-
&& __is_same(U, int) {U->U} /*T->U, outermost level*/
2908-
2909-
After substitution in the mapping, we substitute in the constraint expression
2910-
using that copy of the ``MultiLevelTemplateArgumentList``, and then evaluate it.
2911-
2912-
Because this is expensive, it is cached in
2913-
``UnsubstitutedConstraintSatisfactionCache``.
2914-
2915-
Any error during satisfaction is recorded in ``ConstraintSatisfaction``.
2916-
for nested requirements, ``ConstraintSatisfaction`` is stored (including
2917-
diagnostics) in the AST, which is something we might want to improve.
2918-
2919-
When an atomic constraint is not satified, we try to substitute into any
2920-
enclosing concept-id using the same mechanism described above, for
2921-
diagnostics purpose, and inject that in the ``ConstraintSatisfaction``.
2922-
29232862
.. _CodeGen:
29242863

29252864
The CodeGen Library

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,6 @@ C++23 Feature Support
160160
C++20 Feature Support
161161
^^^^^^^^^^^^^^^^^^^^^
162162

163-
- Clang now normalizes constraints before checking whether they are satisfied, as mandated by the standard.
164-
As a result, Clang no longer incorrectly diagnoses substitution failures in template arguments only
165-
used in concept-ids, and produces better diagnostics for satisfaction failure. (#GH61811) (#GH135190)
166-
167163
C++17 Feature Support
168164
^^^^^^^^^^^^^^^^^^^^^
169165

clang/include/clang/AST/ASTConcept.h

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,10 @@ namespace clang {
2828

2929
class ConceptDecl;
3030
class TemplateDecl;
31-
class ConceptReference;
3231
class Expr;
3332
class NamedDecl;
3433
struct PrintingPolicy;
3534

36-
/// Unsatisfied constraint expressions if the template arguments could be
37-
/// substituted into them, or a diagnostic if substitution resulted in
38-
/// an invalid expression.
39-
///
40-
using ConstraintSubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
41-
using UnsatisfiedConstraintRecord =
42-
llvm::PointerUnion<const Expr *, const ConceptReference *,
43-
const ConstraintSubstitutionDiagnostic *>;
44-
4535
/// The result of a constraint satisfaction check, containing the necessary
4636
/// information to diagnose an unsatisfied constraint.
4737
class ConstraintSatisfaction : public llvm::FoldingSetNode {
@@ -58,13 +48,16 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
5848
ArrayRef<TemplateArgument> TemplateArgs)
5949
: ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {}
6050

51+
using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
52+
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
53+
6154
bool IsSatisfied = false;
6255
bool ContainsErrors = false;
6356

6457
/// \brief The substituted constraint expr, if the template arguments could be
6558
/// substituted into them, or a diagnostic if substitution resulted in an
6659
/// invalid expression.
67-
llvm::SmallVector<UnsatisfiedConstraintRecord, 4> Details;
60+
llvm::SmallVector<Detail, 4> Details;
6861

6962
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
7063
Profile(ID, C, ConstraintOwner, TemplateArgs);
@@ -76,12 +69,19 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
7669

7770
bool HasSubstitutionFailure() {
7871
for (const auto &Detail : Details)
79-
if (Detail.dyn_cast<const ConstraintSubstitutionDiagnostic *>())
72+
if (Detail.dyn_cast<SubstitutionDiagnostic *>())
8073
return true;
8174
return false;
8275
}
8376
};
8477

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+
8585
/// \brief The result of a constraint satisfaction check, containing the
8686
/// necessary information to diagnose an unsatisfied constraint.
8787
///
@@ -101,10 +101,6 @@ struct ASTConstraintSatisfaction final :
101101
return getTrailingObjects() + NumRecords;
102102
}
103103

104-
ArrayRef<UnsatisfiedConstraintRecord> records() const {
105-
return {begin(), end()};
106-
}
107-
108104
ASTConstraintSatisfaction(const ASTContext &C,
109105
const ConstraintSatisfaction &Satisfaction);
110106
ASTConstraintSatisfaction(const ASTContext &C,
@@ -286,11 +282,6 @@ class TypeConstraint {
286282
}
287283
};
288284

289-
/// Insertion operator for diagnostics. This allows sending ConceptReferences's
290-
/// into a diagnostic with <<.
291-
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
292-
const ConceptReference *C);
293-
294285
} // clang
295286

296287
#endif // LLVM_CLANG_AST_ASTCONCEPT_H

clang/include/clang/AST/ASTContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3877,6 +3877,7 @@ typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
38773877
return new (Ctx) LazyData(Source, Value);
38783878
return Value;
38793879
}
3880+
38803881
template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
38813882
static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; }
38823883

clang/include/clang/Sema/Sema.h

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
#include "clang/Sema/Redeclaration.h"
6666
#include "clang/Sema/Scope.h"
6767
#include "clang/Sema/SemaBase.h"
68-
#include "clang/Sema/SemaConcept.h"
6968
#include "clang/Sema/TypoCorrection.h"
7069
#include "clang/Sema/Weak.h"
7170
#include "llvm/ADT/APInt.h"
@@ -11695,9 +11694,8 @@ class Sema final : public SemaBase {
1169511694
ExprResult
1169611695
CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
1169711696
const DeclarationNameInfo &ConceptNameInfo,
11698-
NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
11699-
const TemplateArgumentListInfo *TemplateArgs,
11700-
bool DoCheckConstraintSatisfaction = true);
11697+
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
11698+
const TemplateArgumentListInfo *TemplateArgs);
1170111699

1170211700
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
1170311701
void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
@@ -12027,13 +12025,6 @@ class Sema final : public SemaBase {
1202712025
bool UpdateArgsWithConversions = true,
1202812026
bool *ConstraintsNotSatisfied = nullptr);
1202912027

12030-
bool CheckTemplateArgumentList(
12031-
TemplateDecl *Template, TemplateParameterList *Params,
12032-
SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
12033-
const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
12034-
CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true,
12035-
bool *ConstraintsNotSatisfied = nullptr);
12036-
1203712028
bool CheckTemplateTypeArgument(
1203812029
TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
1203912030
SmallVectorImpl<TemplateArgument> &SugaredConverted,
@@ -12792,18 +12783,6 @@ class Sema final : public SemaBase {
1279212783
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
1279312784
unsigned Depth, llvm::SmallBitVector &Used);
1279412785

12795-
/// Mark which template parameters are named in a given expression.
12796-
///
12797-
/// Unlike MarkUsedTemplateParameters, this excludes parameter that
12798-
/// are used but not directly named by an expression - i.e. it excludes
12799-
/// any template parameter that denotes the type of a referenced NTTP.
12800-
///
12801-
/// \param Used a bit vector whose elements will be set to \c true
12802-
/// to indicate when the corresponding template parameter will be
12803-
/// deduced.
12804-
void MarkUsedTemplateParametersForSubsumptionParameterMapping(
12805-
const Expr *E, unsigned Depth, llvm::SmallBitVector &Used);
12806-
1280712786
/// Mark which template parameters can be deduced from a given
1280812787
/// template argument list.
1280912788
///
@@ -12820,9 +12799,6 @@ class Sema final : public SemaBase {
1282012799
void MarkUsedTemplateParameters(ArrayRef<TemplateArgument> TemplateArgs,
1282112800
unsigned Depth, llvm::SmallBitVector &Used);
1282212801

12823-
void MarkUsedTemplateParameters(ArrayRef<TemplateArgumentLoc> TemplateArgs,
12824-
unsigned Depth, llvm::SmallBitVector &Used);
12825-
1282612802
void
1282712803
MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
1282812804
llvm::SmallBitVector &Deduced) {
@@ -13120,9 +13096,6 @@ class Sema final : public SemaBase {
1312013096
/// Whether we're substituting into constraints.
1312113097
bool InConstraintSubstitution;
1312213098

13123-
/// Whether we're substituting into the parameter mapping of a constraint.
13124-
bool InParameterMappingSubstitution;
13125-
1312613099
/// The point of instantiation or synthesis within the source code.
1312713100
SourceLocation PointOfInstantiation;
1312813101

@@ -13386,11 +13359,6 @@ class Sema final : public SemaBase {
1338613359
const MultiLevelTemplateArgumentList &TemplateArgs,
1338713360
TemplateArgumentListInfo &Outputs);
1338813361

13389-
bool SubstTemplateArgumentsInParameterMapping(
13390-
ArrayRef<TemplateArgumentLoc> Args, SourceLocation BaseLoc,
13391-
const MultiLevelTemplateArgumentList &TemplateArgs,
13392-
TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes);
13393-
1339413362
/// Retrieve the template argument list(s) that should be used to
1339513363
/// instantiate the definition of the given declaration.
1339613364
///
@@ -13852,12 +13820,6 @@ class Sema final : public SemaBase {
1385213820
CodeSynthesisContexts.back().InConstraintSubstitution;
1385313821
}
1385413822

13855-
bool inParameterMappingSubstitution() const {
13856-
return !CodeSynthesisContexts.empty() &&
13857-
CodeSynthesisContexts.back().InParameterMappingSubstitution &&
13858-
!inConstraintSubstitution();
13859-
}
13860-
1386113823
using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>;
1386213824

1386313825
/// \brief create a Requirement::SubstitutionDiagnostic with only a
@@ -14742,10 +14704,6 @@ class Sema final : public SemaBase {
1474214704
SatisfactionStack.swap(NewSS);
1474314705
}
1474414706

14745-
using ConstrainedDeclOrNestedRequirement =
14746-
llvm::PointerUnion<const NamedDecl *,
14747-
const concepts::NestedRequirement *>;
14748-
1474914707
/// Check whether the given expression is a valid constraint expression.
1475014708
/// A diagnostic is emitted if it is not, false is returned, and
1475114709
/// PossibleNonPrimary will be set to true if the failure might be due to a
@@ -14770,12 +14728,44 @@ class Sema final : public SemaBase {
1477014728
/// \returns true if an error occurred and satisfaction could not be checked,
1477114729
/// false otherwise.
1477214730
bool CheckConstraintSatisfaction(
14773-
ConstrainedDeclOrNestedRequirement Entity,
14731+
const NamedDecl *Template,
1477414732
ArrayRef<AssociatedConstraint> AssociatedConstraints,
1477514733
const MultiLevelTemplateArgumentList &TemplateArgLists,
14776-
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
14777-
const ConceptReference *TopLevelConceptId = nullptr,
14778-
Expr **ConvertedExpr = nullptr);
14734+
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
14735+
llvm::SmallVector<Expr *, 4> Converted;
14736+
return CheckConstraintSatisfaction(Template, AssociatedConstraints,
14737+
Converted, TemplateArgLists,
14738+
TemplateIDRange, Satisfaction);
14739+
}
14740+
14741+
/// \brief Check whether the given list of constraint expressions are
14742+
/// satisfied (as if in a 'conjunction') given template arguments.
14743+
/// Additionally, takes an empty list of Expressions which is populated with
14744+
/// the instantiated versions of the ConstraintExprs.
14745+
/// \param Template the template-like entity that triggered the constraints
14746+
/// check (either a concept or a constrained entity).
14747+
/// \param ConstraintExprs a list of constraint expressions, treated as if
14748+
/// they were 'AND'ed together.
14749+
/// \param ConvertedConstraints a out parameter that will get populated with
14750+
/// the instantiated version of the ConstraintExprs if we successfully checked
14751+
/// satisfaction.
14752+
/// \param TemplateArgList the multi-level list of template arguments to
14753+
/// substitute into the constraint expression. This should be relative to the
14754+
/// top-level (hence multi-level), since we need to instantiate fully at the
14755+
/// time of checking.
14756+
/// \param TemplateIDRange The source range of the template id that
14757+
/// caused the constraints check.
14758+
/// \param Satisfaction if true is returned, will contain details of the
14759+
/// satisfaction, with enough information to diagnose an unsatisfied
14760+
/// expression.
14761+
/// \returns true if an error occurred and satisfaction could not be checked,
14762+
/// false otherwise.
14763+
bool CheckConstraintSatisfaction(
14764+
const NamedDecl *Template,
14765+
ArrayRef<AssociatedConstraint> AssociatedConstraints,
14766+
llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
14767+
const MultiLevelTemplateArgumentList &TemplateArgList,
14768+
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
1477914769

1478014770
/// \brief Check whether the given non-dependent constraint expression is
1478114771
/// satisfied. Returns false and updates Satisfaction with the satisfaction
@@ -14841,17 +14831,16 @@ class Sema final : public SemaBase {
1484114831
/// \param First whether this is the first time an unsatisfied constraint is
1484214832
/// diagnosed for this error.
1484314833
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
14844-
SourceLocation Loc = {},
1484514834
bool First = true);
1484614835

1484714836
/// \brief Emit diagnostics explaining why a constraint expression was deemed
1484814837
/// unsatisfied.
1484914838
void
14850-
DiagnoseUnsatisfiedConstraint(const ConceptSpecializationExpr *ConstraintExpr,
14839+
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
1485114840
bool First = true);
1485214841

1485314842
const NormalizedConstraint *getNormalizedAssociatedConstraints(
14854-
ConstrainedDeclOrNestedRequirement Entity,
14843+
const NamedDecl *ConstrainedDecl,
1485514844
ArrayRef<AssociatedConstraint> AssociatedConstraints);
1485614845

1485714846
/// \brief Check whether the given declaration's associated constraints are
@@ -14876,15 +14865,6 @@ class Sema final : public SemaBase {
1487614865
const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1,
1487714866
const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2);
1487814867

14879-
/// Cache the satisfaction of an atomic constraint.
14880-
/// The key is based on the unsubstituted expression and the parameter
14881-
/// mapping. This lets us not substituting the mapping more than once,
14882-
/// which is (very!) expensive.
14883-
/// FIXME: this should be private.
14884-
llvm::DenseMap<llvm::FoldingSetNodeID,
14885-
UnsubstitutedConstraintSatisfactionCacheResult>
14886-
UnsubstitutedConstraintSatisfactionCache;
14887-
1488814868
private:
1488914869
/// Caches pairs of template-like decls whose associated constraints were
1489014870
/// checked for subsumption and whether or not the first's constraints did in
@@ -14895,11 +14875,8 @@ class Sema final : public SemaBase {
1489514875
/// constrained declarations). If an error occurred while normalizing the
1489614876
/// associated constraints of the template or concept, nullptr will be cached
1489714877
/// here.
14898-
llvm::DenseMap<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *>
14899-
NormalizationCache;
14878+
llvm::DenseMap<const NamedDecl *, NormalizedConstraint *> NormalizationCache;
1490014879

14901-
/// Cache whether the associated constraint of a declaration
14902-
/// is satisfied.
1490314880
llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
1490414881
SatisfactionCache;
1490514882

0 commit comments

Comments
 (0)