Skip to content

Commit fa3d14a

Browse files
author
git apple-llvm automerger
committed
Merge commit 'ffa214ef2289' from llvm.org/master into apple/master
2 parents b428916 + ffa214e commit fa3d14a

23 files changed

+1059
-133
lines changed

clang/include/clang/AST/ASTConcept.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// \brief This file provides AST data structures related to concepts.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_CLANG_AST_ASTCONCEPT_H
16+
#define LLVM_CLANG_AST_ASTCONCEPT_H
17+
#include "clang/AST/Expr.h"
18+
#include "clang/Basic/SourceLocation.h"
19+
#include "llvm/ADT/PointerUnion.h"
20+
#include "llvm/ADT/SmallVector.h"
21+
#include <string>
22+
#include <utility>
23+
namespace clang {
24+
25+
/// \brief The result of a constraint satisfaction check, containing the
26+
/// necessary information to diagnose an unsatisfied constraint.
27+
struct ConstraintSatisfaction {
28+
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
29+
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
30+
31+
bool IsSatisfied = false;
32+
33+
/// \brief Pairs of unsatisfied atomic constraint expressions along with the
34+
/// substituted constraint expr, if the template arguments could be
35+
/// substituted into them, or a diagnostic if substitution resulted in an
36+
/// invalid expression.
37+
llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
38+
39+
// This can leak if used in an AST node, use ASTConstraintSatisfaction
40+
// instead.
41+
void *operator new(size_t bytes, ASTContext &C) = delete;
42+
};
43+
44+
/// Pairs of unsatisfied atomic constraint expressions along with the
45+
/// substituted constraint expr, if the template arguments could be
46+
/// substituted into them, or a diagnostic if substitution resulted in
47+
/// an invalid expression.
48+
using UnsatisfiedConstraintRecord =
49+
std::pair<const Expr *,
50+
llvm::PointerUnion<Expr *,
51+
std::pair<SourceLocation, StringRef> *>>;
52+
53+
/// \brief The result of a constraint satisfaction check, containing the
54+
/// necessary information to diagnose an unsatisfied constraint.
55+
///
56+
/// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
57+
struct ASTConstraintSatisfaction final :
58+
llvm::TrailingObjects<ASTConstraintSatisfaction,
59+
UnsatisfiedConstraintRecord> {
60+
std::size_t NumRecords;
61+
bool IsSatisfied : 1;
62+
63+
const UnsatisfiedConstraintRecord *begin() const {
64+
return getTrailingObjects<UnsatisfiedConstraintRecord>();
65+
}
66+
67+
const UnsatisfiedConstraintRecord *end() const {
68+
return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
69+
}
70+
71+
ASTConstraintSatisfaction(const ASTContext &C,
72+
const ConstraintSatisfaction &Satisfaction);
73+
74+
static ASTConstraintSatisfaction *
75+
Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
76+
};
77+
78+
} // clang
79+
80+
#endif // LLVM_CLANG_AST_ASTCONCEPT_H

clang/include/clang/AST/ExprCXX.h

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_AST_EXPRCXX_H
1515
#define LLVM_CLANG_AST_EXPRCXX_H
1616

17+
#include "clang/AST/ASTConcept.h"
1718
#include "clang/AST/Decl.h"
1819
#include "clang/AST/DeclBase.h"
1920
#include "clang/AST/DeclCXX.h"
@@ -4851,6 +4852,10 @@ class ConceptSpecializationExpr final : public Expr,
48514852
TemplateArgument> {
48524853
friend class ASTStmtReader;
48534854
friend TrailingObjects;
4855+
public:
4856+
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
4857+
4858+
protected:
48544859

48554860
// \brief The optional nested name specifier used when naming the concept.
48564861
NestedNameSpecifierLoc NestedNameSpec;
@@ -4868,11 +4873,8 @@ class ConceptSpecializationExpr final : public Expr,
48684873
/// through a UsingShadowDecl.
48694874
NamedDecl *FoundDecl;
48704875

4871-
/// \brief The concept named, and whether or not the concept with the given
4872-
/// arguments was satisfied when the expression was created.
4873-
/// If any of the template arguments are dependent (this expr would then be
4874-
/// isValueDependent()), this bit is to be ignored.
4875-
llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept;
4876+
/// \brief The concept named.
4877+
ConceptDecl *NamedConcept;
48764878

48774879
/// \brief The template argument list source info used to specialize the
48784880
/// concept.
@@ -4882,13 +4884,18 @@ class ConceptSpecializationExpr final : public Expr,
48824884
/// converted template arguments.
48834885
unsigned NumTemplateArgs;
48844886

4887+
/// \brief Information about the satisfaction of the named concept with the
4888+
/// given arguments. If this expression is value dependent, this is to be
4889+
/// ignored.
4890+
ASTConstraintSatisfaction *Satisfaction;
4891+
48854892
ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
48864893
SourceLocation TemplateKWLoc,
48874894
SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
48884895
ConceptDecl *NamedConcept,
48894896
const ASTTemplateArgumentListInfo *ArgsAsWritten,
48904897
ArrayRef<TemplateArgument> ConvertedArgs,
4891-
Optional<bool> IsSatisfied);
4898+
const ConstraintSatisfaction *Satisfaction);
48924899

48934900
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
48944901

@@ -4899,7 +4906,8 @@ class ConceptSpecializationExpr final : public Expr,
48994906
SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
49004907
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
49014908
const ASTTemplateArgumentListInfo *ArgsAsWritten,
4902-
ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
4909+
ArrayRef<TemplateArgument> ConvertedArgs,
4910+
const ConstraintSatisfaction *Satisfaction);
49034911

49044912
static ConceptSpecializationExpr *
49054913
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
@@ -4913,7 +4921,7 @@ class ConceptSpecializationExpr final : public Expr,
49134921
}
49144922

49154923
ConceptDecl *getNamedConcept() const {
4916-
return NamedConcept.getPointer();
4924+
return NamedConcept;
49174925
}
49184926

49194927
ArrayRef<TemplateArgument> getTemplateArguments() const {
@@ -4930,12 +4938,21 @@ class ConceptSpecializationExpr final : public Expr,
49304938
ArrayRef<TemplateArgument> Converted);
49314939

49324940
/// \brief Whether or not the concept with the given arguments was satisfied
4933-
/// when the expression was created. This method assumes that the expression
4934-
/// is not dependent!
4941+
/// when the expression was created.
4942+
/// The expression must not be dependent.
49354943
bool isSatisfied() const {
49364944
assert(!isValueDependent()
49374945
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
4938-
return NamedConcept.getInt();
4946+
return Satisfaction->IsSatisfied;
4947+
}
4948+
4949+
/// \brief Get elaborated satisfaction info about the template arguments'
4950+
/// satisfaction of the named concept.
4951+
/// The expression must not be dependent.
4952+
const ASTConstraintSatisfaction &getSatisfaction() const {
4953+
assert(!isValueDependent()
4954+
&& "getSatisfaction called on dependent ConceptSpecializationExpr");
4955+
return *Satisfaction;
49394956
}
49404957

49414958
SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,26 @@ def err_non_constant_constraint_expression : Error<
25482548
"expression">;
25492549
def err_non_bool_atomic_constraint : Error<
25502550
"atomic constraint must be of type 'bool' (found %0)">;
2551+
def err_template_arg_list_constraints_not_satisfied : Error<
2552+
"constraints not satisfied for %select{class template|function template|variable template|alias template|"
2553+
"template template parameter|template}0 %1%2">;
2554+
def note_constraints_not_satisfied : Note<
2555+
"constraints not satisfied">;
2556+
def note_substituted_constraint_expr_is_ill_formed : Note<
2557+
"because substituted constraint expression is ill-formed%0">;
2558+
def note_atomic_constraint_evaluated_to_false : Note<
2559+
"%select{and |because }0'%1' evaluated to false">;
2560+
def note_concept_specialization_constraint_evaluated_to_false : Note<
2561+
"%select{and |because }0'%1' evaluated to false">;
2562+
def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note<
2563+
"%select{and |because }0%1 does not satisfy %2">;
2564+
def note_atomic_constraint_evaluated_to_false_elaborated : Note<
2565+
"%select{and |because }0'%1' (%2 %3 %4) evaluated to false">;
2566+
def err_could_not_normalize_ill_formed_constraint : Error<
2567+
"required expansion of concept specialization %0 failed, substituted "
2568+
"expression would be illegal">;
2569+
def note_could_not_normalize_ill_formed_constraint_reason : Note<
2570+
"because: %0">;
25512571

25522572
def err_template_different_requires_clause : Error<
25532573
"requires clause differs in template redeclaration">;
@@ -3890,6 +3910,8 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
38903910
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
38913911
"candidate template ignored: invalid explicitly-specified argument "
38923912
"for template parameter %0">;
3913+
def note_ovl_candidate_unsatisfied_constraints : Note<
3914+
"candidate template ignored: constraints not satisfied%0">;
38933915
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
38943916
"candidate template ignored: invalid explicitly-specified argument "
38953917
"for %ordinal0 template parameter">;
@@ -4582,6 +4604,14 @@ def note_template_default_arg_checking : Note<
45824604
"while checking a default template argument used here">;
45834605
def note_concept_specialization_here : Note<
45844606
"while checking the satisfaction of concept '%0' requested here">;
4607+
def note_checking_constraints_for_template_id_here : Note<
4608+
"while checking constraint satisfaction for template '%0' required here">;
4609+
def note_checking_constraints_for_var_spec_id_here : Note<
4610+
"while checking constraint satisfaction for variable template "
4611+
"partial specialization '%0' required here">;
4612+
def note_checking_constraints_for_class_spec_id_here : Note<
4613+
"while checking constraint satisfaction for class template partial "
4614+
"specialization '%0' required here">;
45854615
def note_constraint_substitution_here : Note<
45864616
"while substituting template arguments into constraint expression here">;
45874617
def note_instantiation_contexts_suppressed : Note<

clang/include/clang/Sema/Sema.h

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_SEMA_SEMA_H
1515
#define LLVM_CLANG_SEMA_SEMA_H
1616

17+
#include "clang/AST/ASTConcept.h"
1718
#include "clang/AST/Attr.h"
1819
#include "clang/AST/Availability.h"
1920
#include "clang/AST/ComparisonCategories.h"
@@ -6190,17 +6191,84 @@ class Sema {
61906191
/// A diagnostic is emitted if it is not, and false is returned.
61916192
bool CheckConstraintExpression(Expr *CE);
61926193

6193-
bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
6194-
MultiLevelTemplateArgumentList &MLTAL,
6195-
Expr *ConstraintExpr,
6196-
bool &IsSatisfied);
6194+
/// \brief Check whether the given list of constraint expressions are
6195+
/// satisfied (as if in a 'conjunction') given template arguments.
6196+
/// \param ConstraintExprs a list of constraint expressions, treated as if
6197+
/// they were 'AND'ed together.
6198+
/// \param TemplateArgs the list of template arguments to substitute into the
6199+
/// constraint expression.
6200+
/// \param TemplateIDRange The source range of the template id that
6201+
/// caused the constraints check.
6202+
/// \param Satisfaction if true is returned, will contain details of the
6203+
/// satisfaction, with enough information to diagnose an unsatisfied
6204+
/// expression.
6205+
/// \returns true if an error occurred and satisfaction could not be checked,
6206+
/// false otherwise.
6207+
bool CheckConstraintSatisfaction(TemplateDecl *Template,
6208+
ArrayRef<const Expr *> ConstraintExprs,
6209+
ArrayRef<TemplateArgument> TemplateArgs,
6210+
SourceRange TemplateIDRange,
6211+
ConstraintSatisfaction &Satisfaction);
6212+
6213+
bool CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl *TD,
6214+
ArrayRef<const Expr *> ConstraintExprs,
6215+
ArrayRef<TemplateArgument> TemplateArgs,
6216+
SourceRange TemplateIDRange,
6217+
ConstraintSatisfaction &Satisfaction);
6218+
6219+
bool CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl *TD,
6220+
ArrayRef<const Expr *> ConstraintExprs,
6221+
ArrayRef<TemplateArgument> TemplateArgs,
6222+
SourceRange TemplateIDRange,
6223+
ConstraintSatisfaction &Satisfaction);
6224+
6225+
/// \brief Check whether the given non-dependent constraint expression is
6226+
/// satisfied. Returns false and updates Satisfaction with the satisfaction
6227+
/// verdict if successful, emits a diagnostic and returns true if an error
6228+
/// occured and satisfaction could not be determined.
6229+
///
6230+
/// \returns true if an error occurred, false otherwise.
6231+
bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
6232+
ConstraintSatisfaction &Satisfaction);
61976233

61986234
/// Check that the associated constraints of a template declaration match the
61996235
/// associated constraints of an older declaration of which it is a
62006236
/// redeclaration.
62016237
bool CheckRedeclarationConstraintMatch(TemplateParameterList *Old,
62026238
TemplateParameterList *New);
62036239

6240+
/// \brief Ensure that the given template arguments satisfy the constraints
6241+
/// associated with the given template, emitting a diagnostic if they do not.
6242+
///
6243+
/// \param Template The template to which the template arguments are being
6244+
/// provided.
6245+
///
6246+
/// \param TemplateArgs The converted, canonicalized template arguments.
6247+
///
6248+
/// \param TemplateIDRange The source range of the template id that
6249+
/// caused the constraints check.
6250+
///
6251+
/// \returns true if the constrains are not satisfied or could not be checked
6252+
/// for satisfaction, false if the constraints are satisfied.
6253+
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template,
6254+
ArrayRef<TemplateArgument> TemplateArgs,
6255+
SourceRange TemplateIDRange);
6256+
6257+
/// \brief Emit diagnostics explaining why a constraint expression was deemed
6258+
/// unsatisfied.
6259+
void
6260+
DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction);
6261+
6262+
/// \brief Emit diagnostics explaining why a constraint expression was deemed
6263+
/// unsatisfied.
6264+
void
6265+
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction& Satisfaction);
6266+
6267+
/// \brief Emit diagnostics explaining why a constraint expression was deemed
6268+
/// unsatisfied because it was ill-formed.
6269+
void DiagnoseUnsatisfiedIllFormedConstraint(SourceLocation DiagnosticLocation,
6270+
StringRef Diagnostic);
6271+
62046272
// ParseObjCStringLiteral - Parse Objective-C string literals.
62056273
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
62066274
ArrayRef<Expr *> Strings);
@@ -7016,13 +7084,18 @@ class Sema {
70167084
/// contain the converted forms of the template arguments as written.
70177085
/// Otherwise, \p TemplateArgs will not be modified.
70187086
///
7087+
/// \param ConstraintsNotSatisfied If provided, and an error occured, will
7088+
/// receive true if the cause for the error is the associated constraints of
7089+
/// the template not being satisfied by the template arguments.
7090+
///
70197091
/// \returns true if an error occurred, false otherwise.
70207092
bool CheckTemplateArgumentList(TemplateDecl *Template,
70217093
SourceLocation TemplateLoc,
70227094
TemplateArgumentListInfo &TemplateArgs,
70237095
bool PartialTemplateArgs,
70247096
SmallVectorImpl<TemplateArgument> &Converted,
7025-
bool UpdateArgsWithConversions = true);
7097+
bool UpdateArgsWithConversions = true,
7098+
bool *ConstraintsNotSatisfied = nullptr);
70267099

70277100
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
70287101
TemplateArgumentLoc &Arg,
@@ -7564,6 +7637,9 @@ class Sema {
75647637
TDK_InvalidExplicitArguments,
75657638
/// Checking non-dependent argument conversions failed.
75667639
TDK_NonDependentConversionFailure,
7640+
/// The deduced arguments did not satisfy the constraints associated
7641+
/// with the template.
7642+
TDK_ConstraintsNotSatisfied,
75677643
/// Deduction failed; that's all we know.
75687644
TDK_MiscellaneousDeductionFailure,
75697645
/// CUDA Target attributes do not match.
@@ -8076,7 +8152,7 @@ class Sema {
80768152
/// constrained entity (a concept declaration or a template with associated
80778153
/// constraints).
80788154
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
8079-
ConstraintsCheck, TemplateDecl *Template,
8155+
ConstraintsCheck, NamedDecl *Template,
80808156
ArrayRef<TemplateArgument> TemplateArgs,
80818157
SourceRange InstantiationRange);
80828158

@@ -8085,7 +8161,7 @@ class Sema {
80858161
/// with a template declaration or as part of the satisfaction check of a
80868162
/// concept.
80878163
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
8088-
ConstraintSubstitution, TemplateDecl *Template,
8164+
ConstraintSubstitution, NamedDecl *Template,
80898165
sema::TemplateDeductionInfo &DeductionInfo,
80908166
SourceRange InstantiationRange);
80918167

clang/include/clang/Sema/TemplateDeduction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
1515
#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
1616

17+
#include "clang/Sema/Ownership.h"
18+
#include "clang/AST/ASTConcept.h"
1719
#include "clang/AST/DeclAccessPair.h"
1820
#include "clang/AST/DeclTemplate.h"
1921
#include "clang/AST/TemplateBase.h"
@@ -218,6 +220,10 @@ class TemplateDeductionInfo {
218220
///
219221
/// FIXME: This should be kept internal to SemaTemplateDeduction.
220222
SmallVector<DeducedPack *, 8> PendingDeducedPacks;
223+
224+
/// \brief The constraint satisfaction details resulting from the associated
225+
/// constraints satisfaction tests.
226+
ConstraintSatisfaction AssociatedConstraintsSatisfaction;
221227
};
222228

223229
} // namespace sema

0 commit comments

Comments
 (0)