summaryrefslogtreecommitdiffstats
path: root/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/AST/ASTConcept.h80
-rw-r--r--clang/include/clang/AST/ExprCXX.h39
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td30
-rw-r--r--clang/include/clang/Sema/Sema.h90
-rw-r--r--clang/include/clang/Sema/TemplateDeduction.h6
5 files changed, 227 insertions, 18 deletions
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
new file mode 100644
index 00000000000..937a8a9b345
--- /dev/null
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -0,0 +1,80 @@
+//===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides AST data structures related to concepts.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONCEPT_H
+#define LLVM_CLANG_AST_ASTCONCEPT_H
+#include "clang/AST/Expr.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+#include <utility>
+namespace clang {
+
+/// \brief The result of a constraint satisfaction check, containing the
+/// necessary information to diagnose an unsatisfied constraint.
+struct ConstraintSatisfaction {
+ using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
+ using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
+
+ bool IsSatisfied = false;
+
+ /// \brief Pairs of unsatisfied atomic constraint expressions along with the
+ /// substituted constraint expr, if the template arguments could be
+ /// substituted into them, or a diagnostic if substitution resulted in an
+ /// invalid expression.
+ llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
+
+ // This can leak if used in an AST node, use ASTConstraintSatisfaction
+ // instead.
+ void *operator new(size_t bytes, ASTContext &C) = delete;
+};
+
+/// Pairs of unsatisfied atomic constraint expressions along with the
+/// substituted constraint expr, if the template arguments could be
+/// substituted into them, or a diagnostic if substitution resulted in
+/// an invalid expression.
+using UnsatisfiedConstraintRecord =
+ std::pair<const Expr *,
+ llvm::PointerUnion<Expr *,
+ std::pair<SourceLocation, StringRef> *>>;
+
+/// \brief The result of a constraint satisfaction check, containing the
+/// necessary information to diagnose an unsatisfied constraint.
+///
+/// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
+struct ASTConstraintSatisfaction final :
+ llvm::TrailingObjects<ASTConstraintSatisfaction,
+ UnsatisfiedConstraintRecord> {
+ std::size_t NumRecords;
+ bool IsSatisfied : 1;
+
+ const UnsatisfiedConstraintRecord *begin() const {
+ return getTrailingObjects<UnsatisfiedConstraintRecord>();
+ }
+
+ const UnsatisfiedConstraintRecord *end() const {
+ return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
+ }
+
+ ASTConstraintSatisfaction(const ASTContext &C,
+ const ConstraintSatisfaction &Satisfaction);
+
+ static ASTConstraintSatisfaction *
+ Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
+};
+
+} // clang
+
+#endif // LLVM_CLANG_AST_ASTCONCEPT_H \ No newline at end of file
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 1eac1ce842d..1a16aa7aace 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
@@ -4845,6 +4846,10 @@ class ConceptSpecializationExpr final : public Expr,
TemplateArgument> {
friend class ASTStmtReader;
friend TrailingObjects;
+public:
+ using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
+
+protected:
// \brief The optional nested name specifier used when naming the concept.
NestedNameSpecifierLoc NestedNameSpec;
@@ -4862,11 +4867,8 @@ class ConceptSpecializationExpr final : public Expr,
/// through a UsingShadowDecl.
NamedDecl *FoundDecl;
- /// \brief The concept named, and whether or not the concept with the given
- /// arguments was satisfied when the expression was created.
- /// If any of the template arguments are dependent (this expr would then be
- /// isValueDependent()), this bit is to be ignored.
- llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept;
+ /// \brief The concept named.
+ ConceptDecl *NamedConcept;
/// \brief The template argument list source info used to specialize the
/// concept.
@@ -4876,13 +4878,18 @@ class ConceptSpecializationExpr final : public Expr,
/// converted template arguments.
unsigned NumTemplateArgs;
+ /// \brief Information about the satisfaction of the named concept with the
+ /// given arguments. If this expression is value dependent, this is to be
+ /// ignored.
+ ASTConstraintSatisfaction *Satisfaction;
+
ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc,
SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
- Optional<bool> IsSatisfied);
+ const ConstraintSatisfaction *Satisfaction);
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
@@ -4893,7 +4900,8 @@ public:
SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction);
static ConceptSpecializationExpr *
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
@@ -4907,7 +4915,7 @@ public:
}
ConceptDecl *getNamedConcept() const {
- return NamedConcept.getPointer();
+ return NamedConcept;
}
ArrayRef<TemplateArgument> getTemplateArguments() const {
@@ -4924,12 +4932,21 @@ public:
ArrayRef<TemplateArgument> Converted);
/// \brief Whether or not the concept with the given arguments was satisfied
- /// when the expression was created. This method assumes that the expression
- /// is not dependent!
+ /// when the expression was created.
+ /// The expression must not be dependent.
bool isSatisfied() const {
assert(!isValueDependent()
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
- return NamedConcept.getInt();
+ return Satisfaction->IsSatisfied;
+ }
+
+ /// \brief Get elaborated satisfaction info about the template arguments'
+ /// satisfaction of the named concept.
+ /// The expression must not be dependent.
+ const ASTConstraintSatisfaction &getSatisfaction() const {
+ assert(!isValueDependent()
+ && "getSatisfaction called on dependent ConceptSpecializationExpr");
+ return *Satisfaction;
}
SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dee585bda79..5c01dea9b77 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2572,6 +2572,26 @@ def err_non_constant_constraint_expression : Error<
"expression">;
def err_non_bool_atomic_constraint : Error<
"atomic constraint must be of type 'bool' (found %0)">;
+def err_template_arg_list_constraints_not_satisfied : Error<
+ "constraints not satisfied for %select{class template|function template|variable template|alias template|"
+ "template template parameter|template}0 %1%2">;
+def note_constraints_not_satisfied : Note<
+ "constraints not satisfied">;
+def note_substituted_constraint_expr_is_ill_formed : Note<
+ "because substituted constraint expression is ill-formed%0">;
+def note_atomic_constraint_evaluated_to_false : Note<
+ "%select{and |because }0'%1' evaluated to false">;
+def note_concept_specialization_constraint_evaluated_to_false : Note<
+ "%select{and |because }0'%1' evaluated to false">;
+def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note<
+ "%select{and |because }0%1 does not satisfy %2">;
+def note_atomic_constraint_evaluated_to_false_elaborated : Note<
+ "%select{and |because }0'%1' (%2 %3 %4) evaluated to false">;
+def err_could_not_normalize_ill_formed_constraint : Error<
+ "required expansion of concept specialization %0 failed, substituted "
+ "expression would be illegal">;
+def note_could_not_normalize_ill_formed_constraint_reason : Note<
+ "because: %0">;
def err_template_different_requires_clause : Error<
"requires clause differs in template redeclaration">;
@@ -3861,6 +3881,8 @@ def note_ovl_candidate_inconsistent_deduction_types : Note<
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
"candidate template ignored: invalid explicitly-specified argument "
"for template parameter %0">;
+def note_ovl_candidate_unsatisfied_constraints : Note<
+ "candidate template ignored: constraints not satisfied%0">;
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
"candidate template ignored: invalid explicitly-specified argument "
"for %ordinal0 template parameter">;
@@ -4553,6 +4575,14 @@ def note_template_default_arg_checking : Note<
"while checking a default template argument used here">;
def note_concept_specialization_here : Note<
"while checking the satisfaction of concept '%0' requested here">;
+def note_checking_constraints_for_template_id_here : Note<
+ "while checking constraint satisfaction for template '%0' required here">;
+def note_checking_constraints_for_var_spec_id_here : Note<
+ "while checking constraint satisfaction for variable template "
+ "partial specialization '%0' required here">;
+def note_checking_constraints_for_class_spec_id_here : Note<
+ "while checking constraint satisfaction for class template partial "
+ "specialization '%0' required here">;
def note_constraint_substitution_here : Note<
"while substituting template arguments into constraint expression here">;
def note_instantiation_contexts_suppressed : Note<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e678ac5f82e..f117cca0a56 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SEMA_SEMA_H
#define LLVM_CLANG_SEMA_SEMA_H
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Availability.h"
#include "clang/AST/ComparisonCategories.h"
@@ -6140,10 +6141,45 @@ public:
/// A diagnostic is emitted if it is not, and false is returned.
bool CheckConstraintExpression(Expr *CE);
- bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
- MultiLevelTemplateArgumentList &MLTAL,
- Expr *ConstraintExpr,
- bool &IsSatisfied);
+ /// \brief Check whether the given list of constraint expressions are
+ /// satisfied (as if in a 'conjunction') given template arguments.
+ /// \param ConstraintExprs a list of constraint expressions, treated as if
+ /// they were 'AND'ed together.
+ /// \param TemplateArgs the list of template arguments to substitute into the
+ /// constraint expression.
+ /// \param TemplateIDRange The source range of the template id that
+ /// caused the constraints check.
+ /// \param Satisfaction if true is returned, will contain details of the
+ /// satisfaction, with enough information to diagnose an unsatisfied
+ /// expression.
+ /// \returns true if an error occurred and satisfaction could not be checked,
+ /// false otherwise.
+ bool CheckConstraintSatisfaction(TemplateDecl *Template,
+ ArrayRef<const Expr *> ConstraintExprs,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange TemplateIDRange,
+ ConstraintSatisfaction &Satisfaction);
+
+ bool CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl *TD,
+ ArrayRef<const Expr *> ConstraintExprs,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange TemplateIDRange,
+ ConstraintSatisfaction &Satisfaction);
+
+ bool CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl *TD,
+ ArrayRef<const Expr *> ConstraintExprs,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange TemplateIDRange,
+ ConstraintSatisfaction &Satisfaction);
+
+ /// \brief Check whether the given non-dependent constraint expression is
+ /// satisfied. Returns false and updates Satisfaction with the satisfaction
+ /// verdict if successful, emits a diagnostic and returns true if an error
+ /// occured and satisfaction could not be determined.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
+ ConstraintSatisfaction &Satisfaction);
/// Check that the associated constraints of a template declaration match the
/// associated constraints of an older declaration of which it is a
@@ -6151,6 +6187,38 @@ public:
bool CheckRedeclarationConstraintMatch(TemplateParameterList *Old,
TemplateParameterList *New);
+ /// \brief Ensure that the given template arguments satisfy the constraints
+ /// associated with the given template, emitting a diagnostic if they do not.
+ ///
+ /// \param Template The template to which the template arguments are being
+ /// provided.
+ ///
+ /// \param TemplateArgs The converted, canonicalized template arguments.
+ ///
+ /// \param TemplateIDRange The source range of the template id that
+ /// caused the constraints check.
+ ///
+ /// \returns true if the constrains are not satisfied or could not be checked
+ /// for satisfaction, false if the constraints are satisfied.
+ bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange TemplateIDRange);
+
+ /// \brief Emit diagnostics explaining why a constraint expression was deemed
+ /// unsatisfied.
+ void
+ DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction);
+
+ /// \brief Emit diagnostics explaining why a constraint expression was deemed
+ /// unsatisfied.
+ void
+ DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction& Satisfaction);
+
+ /// \brief Emit diagnostics explaining why a constraint expression was deemed
+ /// unsatisfied because it was ill-formed.
+ void DiagnoseUnsatisfiedIllFormedConstraint(SourceLocation DiagnosticLocation,
+ StringRef Diagnostic);
+
// ParseObjCStringLiteral - Parse Objective-C string literals.
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
ArrayRef<Expr *> Strings);
@@ -6966,13 +7034,18 @@ public:
/// contain the converted forms of the template arguments as written.
/// Otherwise, \p TemplateArgs will not be modified.
///
+ /// \param ConstraintsNotSatisfied If provided, and an error occured, will
+ /// receive true if the cause for the error is the associated constraints of
+ /// the template not being satisfied by the template arguments.
+ ///
/// \returns true if an error occurred, false otherwise.
bool CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
SmallVectorImpl<TemplateArgument> &Converted,
- bool UpdateArgsWithConversions = true);
+ bool UpdateArgsWithConversions = true,
+ bool *ConstraintsNotSatisfied = nullptr);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
TemplateArgumentLoc &Arg,
@@ -7514,6 +7587,9 @@ public:
TDK_InvalidExplicitArguments,
/// Checking non-dependent argument conversions failed.
TDK_NonDependentConversionFailure,
+ /// The deduced arguments did not satisfy the constraints associated
+ /// with the template.
+ TDK_ConstraintsNotSatisfied,
/// Deduction failed; that's all we know.
TDK_MiscellaneousDeductionFailure,
/// CUDA Target attributes do not match.
@@ -8026,7 +8102,7 @@ public:
/// constrained entity (a concept declaration or a template with associated
/// constraints).
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintsCheck, TemplateDecl *Template,
+ ConstraintsCheck, NamedDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
@@ -8035,7 +8111,7 @@ public:
/// with a template declaration or as part of the satisfaction check of a
/// concept.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintSubstitution, TemplateDecl *Template,
+ ConstraintSubstitution, NamedDecl *Template,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange);
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index 662c4072c97..b60939c9787 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
+#include "clang/Sema/Ownership.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/TemplateBase.h"
@@ -218,6 +220,10 @@ public:
///
/// FIXME: This should be kept internal to SemaTemplateDeduction.
SmallVector<DeducedPack *, 8> PendingDeducedPacks;
+
+ /// \brief The constraint satisfaction details resulting from the associated
+ /// constraints satisfaction tests.
+ ConstraintSatisfaction AssociatedConstraintsSatisfaction;
};
} // namespace sema
OpenPOWER on IntegriCloud