[clang] 38839d0 - Revert "[Concepts] Constraint Enforcement & Diagnostics"
Vlad Tsyrklevich via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 28 15:00:49 PDT 2019
Author: Vlad Tsyrklevich
Date: 2019-10-28T15:00:40-07:00
New Revision: 38839d08b8e165dfaab0fa6acc77e620d6df294c
URL: https://github.com/llvm/llvm-project/commit/38839d08b8e165dfaab0fa6acc77e620d6df294c
DIFF: https://github.com/llvm/llvm-project/commit/38839d08b8e165dfaab0fa6acc77e620d6df294c.diff
LOG: Revert "[Concepts] Constraint Enforcement & Diagnostics"
This reverts commit ffa214ef22892d75340dc6720271863901dc2c90, it was
causing ASAN test failures on sanitizer-x86_64-linux-bootstrap.
Added:
Modified:
clang/include/clang/AST/ExprCXX.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/include/clang/Sema/TemplateDeduction.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/CMakeLists.txt
clang/lib/AST/Decl.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/Sema/SemaConcept.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
Removed:
clang/include/clang/AST/ASTConcept.h
clang/lib/AST/ASTConcept.cpp
clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp
clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp
################################################################################
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
deleted file mode 100644
index f5e99a8bfa1e..000000000000
--- a/clang/include/clang/AST/ASTConcept.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===--- 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, std::string>;
- 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 3719f8229a36..2152e108c7cb 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -14,7 +14,6 @@
#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"
@@ -4852,10 +4851,6 @@ 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;
@@ -4873,8 +4868,11 @@ class ConceptSpecializationExpr final : public Expr,
/// through a UsingShadowDecl.
NamedDecl *FoundDecl;
- /// \brief The concept named.
- ConceptDecl *NamedConcept;
+ /// \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 template argument list source info used to specialize the
/// concept.
@@ -4884,18 +4882,13 @@ 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,
- const ConstraintSatisfaction *Satisfaction);
+ Optional<bool> IsSatisfied);
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
@@ -4906,8 +4899,7 @@ class ConceptSpecializationExpr final : public Expr,
SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ArrayRef<TemplateArgument> ConvertedArgs,
- const ConstraintSatisfaction *Satisfaction);
+ ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
static ConceptSpecializationExpr *
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
@@ -4921,7 +4913,7 @@ class ConceptSpecializationExpr final : public Expr,
}
ConceptDecl *getNamedConcept() const {
- return NamedConcept;
+ return NamedConcept.getPointer();
}
ArrayRef<TemplateArgument> getTemplateArguments() const {
@@ -4938,21 +4930,12 @@ class ConceptSpecializationExpr final : public Expr,
ArrayRef<TemplateArgument> Converted);
/// \brief Whether or not the concept with the given arguments was satisfied
- /// when the expression was created.
- /// The expression must not be dependent.
+ /// when the expression was created. This method assumes that the expression
+ /// is not dependent!
bool isSatisfied() const {
assert(!isValueDependent()
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
- 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;
+ return NamedConcept.getInt();
}
SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 20670a98fe03..2313c60f006f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2542,26 +2542,6 @@ 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_
diff erent_requires_clause : Error<
"requires clause
diff ers in template redeclaration">;
@@ -3849,8 +3829,6 @@ 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">;
@@ -4543,14 +4521,6 @@ 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 694b923160aa..88d21367006f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14,7 +14,6 @@
#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"
@@ -6132,45 +6131,10 @@ class Sema {
/// A diagnostic is emitted if it is not, and false is returned.
bool CheckConstraintExpression(Expr *CE);
- /// \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);
+ bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
+ MultiLevelTemplateArgumentList &MLTAL,
+ Expr *ConstraintExpr,
+ bool &IsSatisfied);
/// Check that the associated constraints of a template declaration match the
/// associated constraints of an older declaration of which it is a
@@ -6178,38 +6142,6 @@ class Sema {
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);
@@ -7025,18 +6957,13 @@ class Sema {
/// 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 *ConstraintsNotSatisfied = nullptr);
+ bool UpdateArgsWithConversions = true);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
TemplateArgumentLoc &Arg,
@@ -7578,9 +7505,6 @@ class Sema {
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.
@@ -8093,7 +8017,7 @@ class Sema {
/// constrained entity (a concept declaration or a template with associated
/// constraints).
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintsCheck, NamedDecl *Template,
+ ConstraintsCheck, TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
@@ -8102,7 +8026,7 @@ class Sema {
/// with a template declaration or as part of the satisfaction check of a
/// concept.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintSubstitution, NamedDecl *Template,
+ ConstraintSubstitution, TemplateDecl *Template,
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange);
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index b60939c97872..662c4072c978 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -14,8 +14,6 @@
#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"
@@ -220,10 +218,6 @@ class TemplateDeductionInfo {
///
/// 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
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
deleted file mode 100644
index 3446a6a6da14..000000000000
--- a/clang/lib/AST/ASTConcept.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//===--- ASTConcept.cpp - 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 defines AST data structures related to concepts.
-///
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/ASTConcept.h"
-#include "clang/AST/ASTContext.h"
-using namespace clang;
-
-ASTConstraintSatisfaction::ASTConstraintSatisfaction(const ASTContext &C,
- const ConstraintSatisfaction &Satisfaction):
- NumRecords{Satisfaction.Details.size()},
- IsSatisfied{Satisfaction.IsSatisfied} {
- for (unsigned I = 0; I < NumRecords; ++I) {
- auto &Detail = Satisfaction.Details[I];
- if (Detail.second.is<Expr *>())
- new (getTrailingObjects<UnsatisfiedConstraintRecord>() + I)
- UnsatisfiedConstraintRecord{Detail.first,
- UnsatisfiedConstraintRecord::second_type(
- Detail.second.get<Expr *>())};
- else {
- auto &SubstitutionDiagnostic =
- *Detail.second.get<std::pair<SourceLocation, std::string> *>();
- unsigned MessageSize = SubstitutionDiagnostic.second.size();
- char *Mem = new (C) char[MessageSize + 1];
- memcpy(Mem, SubstitutionDiagnostic.second.c_str(), MessageSize);
- Mem[MessageSize + 1] = '\0';
- auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>(
- SubstitutionDiagnostic.first, StringRef(Mem));
- new (getTrailingObjects<UnsatisfiedConstraintRecord>() + I)
- UnsatisfiedConstraintRecord{Detail.first,
- UnsatisfiedConstraintRecord::second_type(
- NewSubstDiag)};
- }
- }
-}
-
-
-ASTConstraintSatisfaction *
-ASTConstraintSatisfaction::Create(const ASTContext &C,
- const ConstraintSatisfaction &Satisfaction) {
- std::size_t size =
- totalSizeToAlloc<UnsatisfiedConstraintRecord>(
- Satisfaction.Details.size());
- void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));
- return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
-}
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index cdd05c02ef36..cda51ec755a8 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -14,7 +14,6 @@
#include "CXXABI.h"
#include "Interp/Context.h"
#include "clang/AST/APValue.h"
-#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Attr.h"
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 1ede58cc9ed6..5bae40c86539 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -14,7 +14,6 @@ clang_tablegen(Opcodes.inc
add_clang_library(clangAST
APValue.cpp
- ASTConcept.cpp
ASTConsumer.cpp
ASTContext.cpp
ASTDiagnostic.cpp
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 03fb55db14ef..66446626c2eb 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4585,7 +4585,7 @@ LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
}
void LabelDecl::setMSAsmLabel(StringRef Name) {
-char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
+ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
memcpy(Buffer, Name.data(), Name.size());
Buffer[Name.size()] = '\0';
MSAsmName = Buffer;
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index a6252d45b267..904928bdf286 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1755,19 +1755,18 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(ASTContext &C,
NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ArrayRef<TemplateArgument> ConvertedArgs,
- const ConstraintSatisfaction *Satisfaction)
+ ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied)
: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
/*TypeDependent=*/false,
// All the flags below are set in setTemplateArguments.
- /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false,
+ /*ValueDependent=*/!IsSatisfied.hasValue(),
+ /*InstantiationDependent=*/false,
/*ContainsUnexpandedParameterPacks=*/false),
NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
ConceptNameLoc(ConceptNameLoc), FoundDecl(FoundDecl),
- NamedConcept(NamedConcept), NumTemplateArgs(ConvertedArgs.size()),
- Satisfaction(Satisfaction ?
- ASTConstraintSatisfaction::Create(C, *Satisfaction) :
- nullptr) {
+ NamedConcept(NamedConcept, IsSatisfied ? *IsSatisfied : true),
+ NumTemplateArgs(ConvertedArgs.size()) {
+
setTemplateArguments(ArgsAsWritten, ConvertedArgs);
}
@@ -1814,13 +1813,13 @@ ConceptSpecializationExpr::Create(ASTContext &C, NestedNameSpecifierLoc NNS,
ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
- const ConstraintSatisfaction *Satisfaction) {
+ Optional<bool> IsSatisfied) {
void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
ConvertedArgs.size()));
return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
ConceptNameLoc, FoundDecl,
NamedConcept, ArgsAsWritten,
- ConvertedArgs, Satisfaction);
+ ConvertedArgs, IsSatisfied);
}
ConceptSpecializationExpr *
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index cbe265971df6..848ccf543445 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -12,13 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/Template.h"
#include "clang/AST/ExprCXX.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/PointerUnion.h"
using namespace clang;
using namespace sema;
@@ -49,367 +46,80 @@ bool Sema::CheckConstraintExpression(Expr *ConstraintExpression) {
return true;
}
-template <typename AtomicEvaluator>
-static bool
-calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
- ConstraintSatisfaction &Satisfaction,
- AtomicEvaluator &&Evaluator) {
+bool
+Sema::CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
+ MultiLevelTemplateArgumentList &MLTAL,
+ Expr *ConstraintExpr,
+ bool &IsSatisfied) {
ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
- if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
- if (calculateConstraintSatisfaction(S, BO->getLHS(), Satisfaction,
- Evaluator))
+ if (BO->getOpcode() == BO_LAnd) {
+ if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
+ IsSatisfied))
return true;
-
- bool IsLHSSatisfied = Satisfaction.IsSatisfied;
-
- if (BO->getOpcode() == BO_LOr && IsLHSSatisfied)
- // [temp.constr.op] p3
- // A disjunction is a constraint taking two operands. To determine if
- // a disjunction is satisfied, the satisfaction of the first operand
- // is checked. If that is satisfied, the disjunction is satisfied.
- // Otherwise, the disjunction is satisfied if and only if the second
- // operand is satisfied.
+ if (!IsSatisfied)
return false;
-
- if (BO->getOpcode() == BO_LAnd && !IsLHSSatisfied)
- // [temp.constr.op] p2
- // A conjunction is a constraint taking two operands. To determine if
- // a conjunction is satisfied, the satisfaction of the first operand
- // is checked. If that is not satisfied, the conjunction is not
- // satisfied. Otherwise, the conjunction is satisfied if and only if
- // the second operand is satisfied.
+ return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),
+ IsSatisfied);
+ } else if (BO->getOpcode() == BO_LOr) {
+ if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
+ IsSatisfied))
+ return true;
+ if (IsSatisfied)
return false;
-
- return calculateConstraintSatisfaction(S, BO->getRHS(), Satisfaction,
- std::forward<AtomicEvaluator>(Evaluator));
+ return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),
+ IsSatisfied);
}
}
else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
- return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
- std::forward<AtomicEvaluator>(Evaluator));
-
- // An atomic constraint expression
- ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
-
- if (SubstitutedAtomicExpr.isInvalid())
- return true;
-
- if (!SubstitutedAtomicExpr.isUsable())
- // Evaluator has decided satisfaction without yielding an expression.
- return false;
+ return CalculateConstraintSatisfaction(NamedConcept, MLTAL, C->getSubExpr(),
+ IsSatisfied);
EnterExpressionEvaluationContext ConstantEvaluated(
- S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
- Expr::EvalResult EvalResult;
- EvalResult.Diag = &EvaluationDiags;
- if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
- // C++2a [temp.constr.atomic]p1
- // ...E shall be a constant expression of type bool.
- S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
- diag::err_non_constant_constraint_expression)
- << SubstitutedAtomicExpr.get()->getSourceRange();
- for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
- S.Diag(PDiag.first, PDiag.second);
- return true;
- }
-
- Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
- if (!Satisfaction.IsSatisfied)
- Satisfaction.Details.emplace_back(ConstraintExpr,
- SubstitutedAtomicExpr.get());
-
- return false;
-}
-
-template <typename TemplateDeclT>
-static bool calculateConstraintSatisfaction(
- Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs,
- SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
- const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
- return calculateConstraintSatisfaction(
- S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
- EnterExpressionEvaluationContext ConstantEvaluated(
- S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
-
- // Atomic constraint - substitute arguments and check satisfaction.
- ExprResult SubstitutedExpression;
- {
- TemplateDeductionInfo Info(TemplateNameLoc);
- Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
- Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template,
- Info, AtomicExpr->getSourceRange());
- if (Inst.isInvalid())
- return ExprError();
- // We do not want error diagnostics escaping here.
- Sema::SFINAETrap Trap(S);
- SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
- MLTAL);
- if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
- // C++2a [temp.constr.atomic]p1
- // ...If substitution results in an invalid type or expression, the
- // constraint is not satisfied.
- if (!Trap.hasErrorOccurred())
- // A non-SFINAE error has occured as a result of this
- // substitution.
- return ExprError();
-
- PartialDiagnosticAt SubstDiag{SourceLocation(),
- PartialDiagnostic::NullDiagnostic()};
- Info.takeSFINAEDiagnostic(SubstDiag);
- // FIXME: Concepts: This is an unfortunate consequence of there
- // being no serialization code for PartialDiagnostics and the fact
- // that serializing them would likely take a lot more storage than
- // just storing them as strings. We would still like, in the
- // future, to serialize the proper PartialDiagnostic as serializing
- // it as a string defeats the purpose of the diagnostic mechanism.
- SmallString<128> DiagString;
- DiagString = ": ";
- SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
- Satisfaction.Details.emplace_back(
- AtomicExpr,
- new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
- SubstDiag.first,
- std::string(DiagString.begin(), DiagString.end())});
- Satisfaction.IsSatisfied = false;
- return ExprEmpty();
- }
- }
-
- if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
- return ExprError();
-
- return SubstitutedExpression;
- });
-}
-
-template<typename TemplateDeclT>
-static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction) {
- if (ConstraintExprs.empty()) {
- Satisfaction.IsSatisfied = true;
- return false;
- }
+ *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+
+ // Atomic constraint - substitute arguments and check satisfaction.
+ ExprResult E;
+ {
+ TemplateDeductionInfo Info(ConstraintExpr->getBeginLoc());
+ InstantiatingTemplate Inst(*this, ConstraintExpr->getBeginLoc(),
+ InstantiatingTemplate::ConstraintSubstitution{},
+ NamedConcept, Info,
+ ConstraintExpr->getSourceRange());
+ if (Inst.isInvalid())
+ return true;
+ // We do not want error diagnostics escaping here.
+ Sema::SFINAETrap Trap(*this);
- for (auto& Arg : TemplateArgs)
- if (Arg.isInstantiationDependent()) {
- // No need to check satisfaction for dependent constraint expressions.
- Satisfaction.IsSatisfied = true;
+ E = SubstExpr(ConstraintExpr, MLTAL);
+ if (E.isInvalid() || Trap.hasErrorOccurred()) {
+ // C++2a [temp.constr.atomic]p1
+ // ...If substitution results in an invalid type or expression, the
+ // constraint is not satisfied.
+ IsSatisfied = false;
return false;
}
-
- Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
- Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
- TemplateIDRange);
- if (Inst.isInvalid())
- return true;
-
- MultiLevelTemplateArgumentList MLTAL;
- MLTAL.addOuterTemplateArguments(TemplateArgs);
-
- for (const Expr *ConstraintExpr : ConstraintExprs) {
- if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
- TemplateIDRange.getBegin(), MLTAL,
- ConstraintExpr, Satisfaction))
- return true;
- if (!Satisfaction.IsSatisfied)
- // [temp.constr.op] p2
- // [...] To determine if a conjunction is satisfied, the satisfaction
- // of the first operand is checked. If that is not satisfied, the
- // conjunction is not satisfied. [...]
- return false;
}
- return false;
-}
-
-bool Sema::CheckConstraintSatisfaction(TemplateDecl *Template,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction) {
- return ::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
- TemplateArgs, TemplateIDRange,
- Satisfaction);
-}
-bool
-Sema::CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl* Part,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction) {
- return ::CheckConstraintSatisfaction(*this, Part, ConstraintExprs,
- TemplateArgs, TemplateIDRange,
- Satisfaction);
-}
-
-bool
-Sema::CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl* Partial,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction) {
- return ::CheckConstraintSatisfaction(*this, Partial, ConstraintExprs,
- TemplateArgs, TemplateIDRange,
- Satisfaction);
-}
-
-bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
- ConstraintSatisfaction &Satisfaction) {
- return calculateConstraintSatisfaction(
- *this, ConstraintExpr, Satisfaction,
- [](const Expr *AtomicExpr) -> ExprResult {
- return ExprResult(const_cast<Expr *>(AtomicExpr));
- });
-}
-
-bool Sema::EnsureTemplateArgumentListConstraints(
- TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange) {
- ConstraintSatisfaction Satisfaction;
- llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
- TD->getAssociatedConstraints(AssociatedConstraints);
- if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
- TemplateIDRange, Satisfaction))
+ if (!CheckConstraintExpression(E.get()))
return true;
- if (!Satisfaction.IsSatisfied) {
- SmallString<128> TemplateArgString;
- TemplateArgString = " ";
- TemplateArgString += getTemplateArgumentBindingsText(
- TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
-
- Diag(TemplateIDRange.getBegin(),
- diag::err_template_arg_list_constraints_not_satisfied)
- << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
- << TemplateArgString << TemplateIDRange;
- DiagnoseUnsatisfiedConstraint(Satisfaction);
+ SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
+ Expr::EvalResult EvalResult;
+ EvalResult.Diag = &EvaluationDiags;
+ if (!E.get()->EvaluateAsRValue(EvalResult, Context)) {
+ // C++2a [temp.constr.atomic]p1
+ // ...E shall be a constant expression of type bool.
+ Diag(E.get()->getBeginLoc(),
+ diag::err_non_constant_constraint_expression)
+ << E.get()->getSourceRange();
+ for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
+ Diag(PDiag.first, PDiag.second);
return true;
}
- return false;
-}
-
-static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
- Expr *SubstExpr,
- bool First = true) {
- SubstExpr = SubstExpr->IgnoreParenImpCasts();
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
- switch (BO->getOpcode()) {
- // These two cases will in practice only be reached when using fold
- // expressions with || and &&, since otherwise the || and && will have been
- // broken down into atomic constraints during satisfaction checking.
- case BO_LOr:
- // Or evaluated to false - meaning both RHS and LHS evaluated to false.
- diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
- diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
- /*First=*/false);
- return;
- case BO_LAnd:
- bool LHSSatisfied;
- BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
- if (LHSSatisfied) {
- // LHS is true, so RHS must be false.
- diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
- return;
- }
- // LHS is false
- diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
-
- // RHS might also be false
- bool RHSSatisfied;
- BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
- if (!RHSSatisfied)
- diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
- /*First=*/false);
- return;
- case BO_GE:
- case BO_LE:
- case BO_GT:
- case BO_LT:
- case BO_EQ:
- case BO_NE:
- if (BO->getLHS()->getType()->isIntegerType() &&
- BO->getRHS()->getType()->isIntegerType()) {
- Expr::EvalResult SimplifiedLHS;
- Expr::EvalResult SimplifiedRHS;
- BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
- BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
- if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
- S.Diag(SubstExpr->getBeginLoc(),
- diag::note_atomic_constraint_evaluated_to_false_elaborated)
- << (int)First << SubstExpr
- << SimplifiedLHS.Val.getInt().toString(10)
- << BinaryOperator::getOpcodeStr(BO->getOpcode())
- << SimplifiedRHS.Val.getInt().toString(10);
- return;
- }
- }
- break;
-
- default:
- break;
- }
- } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
- if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
- S.Diag(
- CSE->getSourceRange().getBegin(),
- diag::
- note_single_arg_concept_specialization_constraint_evaluated_to_false)
- << (int)First
- << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
- << CSE->getNamedConcept();
- } else {
- S.Diag(SubstExpr->getSourceRange().getBegin(),
- diag::note_concept_specialization_constraint_evaluated_to_false)
- << (int)First << CSE;
- }
- S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
- return;
- }
-
- S.Diag(SubstExpr->getSourceRange().getBegin(),
- diag::note_atomic_constraint_evaluated_to_false)
- << (int)First << SubstExpr;
-}
-template<typename SubstitutionDiagnostic>
-static void diagnoseUnsatisfiedConstraintExpr(
- Sema &S, const Expr *E,
- const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
- bool First = true) {
- if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
- S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
- << Diag->second;
- return;
- }
+ IsSatisfied = EvalResult.Val.getInt().getBoolValue();
- diagnoseWellFormedUnsatisfiedConstraintExpr(S,
- Record.template get<Expr *>(), First);
-}
-
-void Sema::DiagnoseUnsatisfiedConstraint(
- const ConstraintSatisfaction& Satisfaction) {
- assert(!Satisfaction.IsSatisfied &&
- "Attempted to diagnose a satisfied constraint");
- bool First = true;
- for (auto &Pair : Satisfaction.Details) {
- diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
- First = false;
- }
-}
-
-void Sema::DiagnoseUnsatisfiedConstraint(
- const ASTConstraintSatisfaction &Satisfaction) {
- assert(!Satisfaction.IsSatisfied &&
- "Attempted to diagnose a satisfied constraint");
- bool First = true;
- for (auto &Pair : Satisfaction) {
- diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
- First = false;
- }
+ return false;
}
\ No newline at end of file
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6a718db6c553..e3f57e347268 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -14486,16 +14486,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
std::string InnerCondDescription;
std::tie(InnerCond, InnerCondDescription) =
findFailedBooleanCondition(Converted.get());
- if (InnerCond && isa<ConceptSpecializationExpr>(InnerCond)) {
- // Drill down into concept specialization expressions to see why they
- // weren't satisfied.
- Diag(StaticAssertLoc, diag::err_static_assert_failed)
- << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
- ConstraintSatisfaction Satisfaction;
- if (!CheckConstraintSatisfaction(InnerCond, Satisfaction))
- DiagnoseUnsatisfiedConstraint(Satisfaction);
- } else if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
- && !isa<IntegerLiteral>(InnerCond)) {
+ if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
+ && !isa<IntegerLiteral>(InnerCond)) {
Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
<< InnerCondDescription << !AssertMessage
<< Msg.str() << InnerCond->getSourceRange();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4417d22d133e..1547108b4af6 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -591,12 +591,6 @@ namespace {
TemplateArgumentList *TemplateArgs;
unsigned CallArgIndex;
};
- // Structure used by DeductionFailureInfo to store information about
- // unsatisfied constraints.
- struct CNSInfo {
- TemplateArgumentList *TemplateArgs;
- ConstraintSatisfaction Satisfaction;
- };
}
/// Convert from Sema's representation of template deduction information
@@ -667,14 +661,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
}
break;
- case Sema::TDK_ConstraintsNotSatisfied: {
- CNSInfo *Saved = new (Context) CNSInfo;
- Saved->TemplateArgs = Info.take();
- Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction;
- Result.Data = Saved;
- break;
- }
-
case Sema::TDK_Success:
case Sema::TDK_NonDependentConversionFailure:
llvm_unreachable("not a deduction failure");
@@ -715,15 +701,6 @@ void DeductionFailureInfo::Destroy() {
}
break;
- case Sema::TDK_ConstraintsNotSatisfied:
- // FIXME: Destroy the template argument list?
- Data = nullptr;
- if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
- Diag->~PartialDiagnosticAt();
- HasDiagnostic = false;
- }
- break;
-
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
break;
@@ -749,7 +726,6 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
- case Sema::TDK_ConstraintsNotSatisfied:
return TemplateParameter();
case Sema::TDK_Incomplete:
@@ -793,9 +769,6 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
- case Sema::TDK_ConstraintsNotSatisfied:
- return static_cast<CNSInfo*>(Data)->TemplateArgs;
-
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
break;
@@ -816,7 +789,6 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
- case Sema::TDK_ConstraintsNotSatisfied:
return nullptr;
case Sema::TDK_IncompletePack:
@@ -848,7 +820,6 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
- case Sema::TDK_ConstraintsNotSatisfied:
return nullptr;
case Sema::TDK_Inconsistent:
@@ -1284,8 +1255,6 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return NewTarget != OldTarget;
}
- // TODO: Concepts: Check function trailing requires clauses here.
-
// The signatures match; this is not an overload.
return false;
}
@@ -10380,21 +10349,6 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
MaybeEmitInheritedConstructorNote(S, Found);
return;
- case Sema::TDK_ConstraintsNotSatisfied: {
- // Format the template argument list into the argument string.
- SmallString<128> TemplateArgString;
- TemplateArgumentList *Args = DeductionFailure.getTemplateArgumentList();
- TemplateArgString = " ";
- TemplateArgString += S.getTemplateArgumentBindingsText(
- getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
- S.Diag(Templated->getLocation(),
- diag::note_ovl_candidate_unsatisfied_constraints)
- << TemplateArgString;
-
- S.DiagnoseUnsatisfiedConstraint(
- static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
- return;
- }
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Found, Templated, NumArgs);
@@ -10847,7 +10801,6 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_DeducedMismatch:
- case Sema::TDK_ConstraintsNotSatisfied:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 3003a9a889df..3f2d38630c36 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3210,7 +3210,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template || isa<FunctionTemplateDecl>(Template) ||
- isa<VarTemplateDecl>(Template) || isa<ConceptDecl>(Template)) {
+ isa<VarTemplateDecl>(Template) ||
+ isa<ConceptDecl>(Template)) {
// We might have a substituted template template parameter pack. If so,
// build a template specialization type for it.
if (Name.getAsSubstTemplateTemplateParmPack())
@@ -3226,8 +3227,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
- false, Converted,
- /*UpdateArgsWithConversion=*/true))
+ false, Converted))
return QualType();
QualType CanonType;
@@ -3235,7 +3235,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
bool InstantiationDependent = false;
if (TypeAliasTemplateDecl *AliasTemplate =
dyn_cast<TypeAliasTemplateDecl>(Template)) {
-
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
if (Pattern->isInvalidDecl())
@@ -3873,8 +3872,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
- false, Converted,
- /*UpdateArgsWithConversion=*/true))
+ false, Converted))
return true;
// Find the variable template (partial) specialization declaration that
@@ -4045,7 +4043,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
if (CheckTemplateArgumentList(
Template, TemplateNameLoc,
const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
- Converted, /*UpdateArgsWithConversion=*/true))
+ Converted))
return true;
// Find the variable template specialization declaration that
@@ -4236,7 +4234,7 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
/*UpdateArgsWithConversion=*/false))
return ExprError();
- ConstraintSatisfaction Satisfaction;
+ Optional<bool> IsSatisfied;
bool AreArgsDependent = false;
for (TemplateArgument &Arg : Converted) {
if (Arg.isDependent()) {
@@ -4244,21 +4242,25 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
break;
}
}
- if (!AreArgsDependent &&
- CheckConstraintSatisfaction(NamedConcept,
- {NamedConcept->getConstraintExpr()},
- Converted,
- SourceRange(SS.isSet() ? SS.getBeginLoc() :
- ConceptNameLoc,
- TemplateArgs->getRAngleLoc()),
- Satisfaction))
+ if (!AreArgsDependent) {
+ InstantiatingTemplate Inst(*this, ConceptNameLoc,
+ InstantiatingTemplate::ConstraintsCheck{}, NamedConcept, Converted,
+ SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameLoc,
+ TemplateArgs->getRAngleLoc()));
+ MultiLevelTemplateArgumentList MLTAL;
+ MLTAL.addOuterTemplateArguments(Converted);
+ bool Satisfied;
+ if (CalculateConstraintSatisfaction(NamedConcept, MLTAL,
+ NamedConcept->getConstraintExpr(),
+ Satisfied))
return ExprError();
-
+ IsSatisfied = Satisfied;
+ }
return ConceptSpecializationExpr::Create(Context,
SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept,
ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), Converted,
- AreArgsDependent ? nullptr : &Satisfaction);
+ IsSatisfied);
}
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -5204,11 +5206,7 @@ bool Sema::CheckTemplateArgumentList(
TemplateDecl *Template, SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
SmallVectorImpl<TemplateArgument> &Converted,
- bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
-
- if (ConstraintsNotSatisfied)
- *ConstraintsNotSatisfied = false;
-
+ bool UpdateArgsWithConversions) {
// Make a copy of the template arguments for processing. Only make the
// changes at the end when successful in matching the arguments to the
// template.
@@ -5323,6 +5321,7 @@ bool Sema::CheckTemplateArgumentList(
if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
Converted.push_back(
TemplateArgument::CreatePackCopy(Context, ArgumentPack));
+
return false;
}
@@ -5461,15 +5460,6 @@ bool Sema::CheckTemplateArgumentList(
if (UpdateArgsWithConversions)
TemplateArgs = std::move(NewArgs);
- if (!PartialTemplateArgs &&
- EnsureTemplateArgumentListConstraints(
- Template, Converted, SourceRange(TemplateLoc,
- TemplateArgs.getRAngleLoc()))) {
- if (ConstraintsNotSatisfied)
- *ConstraintsNotSatisfied = true;
- return true;
- }
-
return false;
}
@@ -7804,8 +7794,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
- TemplateArgs, false, Converted,
- /*UpdateArgsWithConversion=*/true))
+ TemplateArgs, false, Converted))
return true;
// Find the class template (partial) specialization declaration that
@@ -9051,8 +9040,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
- TemplateArgs, false, Converted,
- /*UpdateArgsWithConversion=*/true))
+ TemplateArgs, false, Converted))
return true;
// Find the class template specialization declaration that
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 327447746c39..64ef819e30d4 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2591,23 +2591,6 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return ConvertArg(Arg, 0);
}
-template<typename TemplateDeclT>
-static Sema::TemplateDeductionResult
-CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
- ArrayRef<TemplateArgument> DeducedArgs,
- TemplateDeductionInfo &Info) {
- llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
- Template->getAssociatedConstraints(AssociatedConstraints);
- if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints,
- DeducedArgs, Info.getLocation(),
- Info.AssociatedConstraintsSatisfaction) ||
- !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
- return Sema::TDK_ConstraintsNotSatisfied;
- }
- return Sema::TDK_Success;
-}
-
// FIXME: This should not be a template, but
// ClassTemplatePartialSpecializationDecl sadly does not derive from
// TemplateDecl.
@@ -2705,10 +2688,6 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
// If we get here, we successfully used the default template argument.
}
- if (Sema::TemplateDeductionResult Result
- = CheckDeducedArgumentConstraints(S, Template, Builder, Info))
- return Result;
-
return Sema::TDK_Success;
}
@@ -2788,14 +2767,10 @@ FinishTemplateArgumentDeduction(
return Sema::TDK_SubstitutionFailure;
}
- bool ConstraintsNotSatisfied;
SmallVector<TemplateArgument, 4> ConvertedInstArgs;
if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
- false, ConvertedInstArgs,
- /*UpdateArgsWithConversions=*/true,
- &ConstraintsNotSatisfied))
- return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied :
- Sema::TDK_SubstitutionFailure;
+ false, ConvertedInstArgs))
+ return Sema::TDK_SubstitutionFailure;
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
@@ -2856,6 +2831,7 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
return Sema::TDK_Success;
}
+
/// Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
@@ -5073,7 +5049,6 @@ template<typename TemplateLikeDecl>
static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
TemplateLikeDecl *P2,
TemplateDeductionInfo &Info) {
- // TODO: Concepts: Regard constraints
// C++ [temp.class.order]p1:
// For two class template partial specializations, the first is at least as
// specialized as the second if, given the following rewrite to two
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e6c3ab422067..0daa33cfbef5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -363,7 +363,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintsCheck, NamedDecl *Template,
+ ConstraintsCheck, TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintsCheck,
@@ -372,7 +372,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintSubstitution, NamedDecl *Template,
+ ConstraintSubstitution, TemplateDecl *Template,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintSubstitution,
@@ -691,27 +691,24 @@ void Sema::PrintInstantiationStack() {
case CodeSynthesisContext::Memoization:
break;
- case CodeSynthesisContext::ConstraintsCheck: {
- unsigned DiagID = 0;
- if (isa<ConceptDecl>(Active->Entity))
- DiagID = diag::note_concept_specialization_here;
- else if (isa<TemplateDecl>(Active->Entity))
- DiagID = diag::note_checking_constraints_for_template_id_here;
- else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
- DiagID = diag::note_checking_constraints_for_var_spec_id_here;
- else {
- assert(isa<ClassTemplatePartialSpecializationDecl>(Active->Entity));
- DiagID = diag::note_checking_constraints_for_class_spec_id_here;
+ case CodeSynthesisContext::ConstraintsCheck:
+ if (auto *CD = dyn_cast<ConceptDecl>(Active->Entity)) {
+ SmallVector<char, 128> TemplateArgsStr;
+ llvm::raw_svector_ostream OS(TemplateArgsStr);
+ CD->printName(OS);
+ printTemplateArgumentList(OS, Active->template_arguments(),
+ getPrintingPolicy());
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_concept_specialization_here)
+ << OS.str()
+ << Active->InstantiationRange;
+ break;
}
- SmallVector<char, 128> TemplateArgsStr;
- llvm::raw_svector_ostream OS(TemplateArgsStr);
- cast<NamedDecl>(Active->Entity)->printName(OS);
- printTemplateArgumentList(OS, Active->template_arguments(),
- getPrintingPolicy());
- Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
- << Active->InstantiationRange;
+ // TODO: Concepts - implement this for constrained templates and partial
+ // specializations.
+ llvm_unreachable("only concept constraints are supported right now");
break;
- }
+
case CodeSynthesisContext::ConstraintSubstitution:
Diags.Report(Active->PointOfInstantiation,
diag::note_constraint_substitution_here)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c1d7b7f84f30..31a4302ba826 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3279,8 +3279,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
D->getLocation(),
InstTemplateArgs,
false,
- Converted,
- /*UpdateArgsWithConversion=*/true))
+ Converted))
return nullptr;
// Figure out where to insert this class template explicit specialization
@@ -3401,8 +3400,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
// Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted;
if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(),
- VarTemplateArgsInfo, false, Converted,
- /*UpdateArgsWithConversion=*/true))
+ VarTemplateArgsInfo, false, Converted))
return nullptr;
// Check whether we've already seen a declaration of this specialization.
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index f5d659affac7..a275e0c30579 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ASTReader.h"
-#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
@@ -743,33 +742,14 @@ void ASTStmtReader::VisitConceptSpecializationExpr(
E->TemplateKWLoc = Record.readSourceLocation();
E->ConceptNameLoc = Record.readSourceLocation();
E->FoundDecl = ReadDeclAs<NamedDecl>();
- E->NamedConcept = ReadDeclAs<ConceptDecl>();
+ E->NamedConcept.setPointer(ReadDeclAs<ConceptDecl>());
const ASTTemplateArgumentListInfo *ArgsAsWritten =
Record.readASTTemplateArgumentListInfo();
llvm::SmallVector<TemplateArgument, 4> Args;
for (unsigned I = 0; I < NumTemplateArgs; ++I)
Args.push_back(Record.readTemplateArgument());
E->setTemplateArguments(ArgsAsWritten, Args);
- ConstraintSatisfaction Satisfaction;
- Satisfaction.IsSatisfied = Record.readInt();
- if (!Satisfaction.IsSatisfied) {
- unsigned NumDetailRecords = Record.readInt();
- for (unsigned i = 0; i != NumDetailRecords; ++i) {
- Expr *ConstraintExpr = Record.readExpr();
- bool IsDiagnostic = Record.readInt();
- if (IsDiagnostic) {
- SourceLocation DiagLocation = Record.readSourceLocation();
- std::string DiagMessage = Record.readString();
- Satisfaction.Details.emplace_back(
- ConstraintExpr, new (Record.getContext())
- ConstraintSatisfaction::SubstitutionDiagnostic{
- DiagLocation, DiagMessage});
- } else
- Satisfaction.Details.emplace_back(ConstraintExpr, Record.readExpr());
- }
- }
- E->Satisfaction = ASTConstraintSatisfaction::Create(Record.getContext(),
- Satisfaction);
+ E->NamedConcept.setInt(Record.readInt() == 1);
}
void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 671e55e14521..c39d4d39bcdf 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -401,25 +401,7 @@ void ASTStmtWriter::VisitConceptSpecializationExpr(
Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten());
for (const TemplateArgument &Arg : TemplateArgs)
Record.AddTemplateArgument(Arg);
- const ASTConstraintSatisfaction &Satisfaction = E->getSatisfaction();
- Record.push_back(Satisfaction.IsSatisfied);
- if (!Satisfaction.IsSatisfied) {
- Record.push_back(Satisfaction.NumRecords);
- for (const auto &DetailRecord : Satisfaction) {
- Record.AddStmt(const_cast<Expr *>(DetailRecord.first));
- auto *E = DetailRecord.second.dyn_cast<Expr *>();
- Record.push_back(E == nullptr);
- if (E)
- Record.AddStmt(E);
- else {
- auto *Diag = DetailRecord.second.get<std::pair<SourceLocation,
- StringRef> *>();
- Record.AddSourceLocation(Diag->first);
- Record.AddString(Diag->second);
- }
- }
- }
-
+ Record.push_back(E->isSatisfied());
Code = serialization::EXPR_CONCEPT_SPECIALIZATION;
}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
index 1e10d4550ce0..dd3f0c0e3d6c 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
@@ -72,15 +72,6 @@ template<typename T> struct T2 { static constexpr bool value = sizeof(T) == 2; }
static_assert(IsTypePredicate<T2>);
static_assert(!IsTypePredicate<T1>);
-template<typename T, typename U, typename... Ts>
-concept OneOf = (Same<T, Ts> || ...);
-
-template<typename... X>
-constexpr bool S = OneOf<X..., int, int>;
-
-static_assert(S<int, long, int>);
-static_assert(!S<long, int, char, char>);
-
namespace piecewise_substitution {
template <typename T>
concept True = true;
@@ -156,25 +147,3 @@ template<typename T>
struct X { static constexpr bool a = SameSize<T>; };
static_assert(X<unsigned>::a);
-
-// static_assert concept diagnostics
-template<typename T>
-concept Large = sizeof(T) > 100;
-// expected-note at -1 2{{because 'sizeof(small) > 100' (1 > 100) evaluated to false}}
-
-struct small { };
-static_assert(Large<small>);
-// expected-error at -1 {{static_assert failed}}
-// expected-note at -2 {{because 'small' does not satisfy 'Large'}}
-static_assert(Large<small>, "small isn't large");
-// expected-error at -1 {{static_assert failed "small isn't large"}}
-// expected-note at -2 {{because 'small' does not satisfy 'Large'}}
-
-// Make sure access-checking can fail a concept specialization
-
-class T4 { static constexpr bool f = true; };
-template<typename T> concept AccessPrivate = T{}.f;
-// expected-note at -1{{because substituted constraint expression is ill-formed: 'f' is a private member of 'T4'}}
-static_assert(AccessPrivate<T4>);
-// expected-error at -1{{static_assert failed}}
-// expected-note at -2{{because 'T4' does not satisfy 'AccessPrivate'}}
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp
deleted file mode 100644
index c1a3a27fbeac..000000000000
--- a/clang/test/CXX/temp/temp.constr/temp.constr.constr/function-templates.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
-
-template<typename T>
-constexpr bool is_ptr_v = false;
-
-template<typename T>
-constexpr bool is_ptr_v<T*> = true;
-
-template<typename T, typename U>
-constexpr bool is_same_v = false;
-
-template<typename T>
-constexpr bool is_same_v<T, T> = true;
-
-template<typename T> requires is_ptr_v<T> // expected-note {{because 'is_ptr_v<int>' evaluated to false}}
- // expected-note at -1{{because 'is_ptr_v<char>' evaluated to false}}
-auto dereference(T t) { // expected-note {{candidate template ignored: constraints not satisfied [with T = int]}}
- // expected-note at -1{{candidate template ignored: constraints not satisfied [with T = char]}}
- return *t;
-}
-
-static_assert(is_same_v<decltype(dereference<int*>(nullptr)), int>);
-static_assert(is_same_v<decltype(dereference(2)), int>); // expected-error {{no matching function for call to 'dereference'}}
-static_assert(is_same_v<decltype(dereference<char>('a')), char>); // expected-error {{no matching function for call to 'dereference'}}
-
-
-template<typename T> requires T{} + T{} // expected-note {{because substituted constraint expression is ill-formed: invalid operands to binary expression ('A' and 'A')}}
-auto foo(T t) { // expected-note {{candidate template ignored: constraints not satisfied [with T = A]}}
- return t + t;
-}
-
-
-template<typename T> requires !((T{} - T{}) && (T{} + T{})) || false
-// expected-note at -1{{because substituted constraint expression is ill-formed: invalid operands to binary expression ('A' and 'A')}}
-// expected-note at -2{{and 'false' evaluated to false}}
-auto bar(T t) { // expected-note {{candidate template ignored: constraints not satisfied [with T = A]}}
- return t + t;
-}
-
-struct A { };
-
-static_assert(foo(A{})); // expected-error {{no matching function for call to 'foo'}}
-static_assert(bar(A{})); // expected-error {{no matching function for call to 'bar'}}
\ No newline at end of file
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
deleted file mode 100644
index 24caa5063a1b..000000000000
--- a/clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
-
-template<typename T> requires sizeof(T) >= 2 // expected-note{{because 'sizeof(char) >= 2' (1 >= 2) evaluated to false}}
-struct A {
- static constexpr int value = sizeof(T);
-};
-
-static_assert(A<int>::value == 4);
-static_assert(A<char>::value == 1); // expected-error{{constraints not satisfied for class template 'A' [with T = char]}}
-
-template<typename T, typename U>
- requires sizeof(T) != sizeof(U) // expected-note{{because 'sizeof(int) != sizeof(char [4])' (4 != 4) evaluated to false}}
- && sizeof(T) >= 4 // expected-note{{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}}
-constexpr int SizeDiff = sizeof(T) > sizeof(U) ? sizeof(T) - sizeof(U) : sizeof(U) - sizeof(T);
-
-static_assert(SizeDiff<int, char> == 3);
-static_assert(SizeDiff<int, char[4]> == 0); // expected-error{{constraints not satisfied for variable template 'SizeDiff' [with T = int, U = char [4]]}}
-static_assert(SizeDiff<char, int> == 3); // expected-error{{constraints not satisfied for variable template 'SizeDiff' [with T = char, U = int]}}
-
-template<typename... Ts>
- requires ((sizeof(Ts) == 4) || ...) // expected-note{{because 'sizeof(char) == 4' (1 == 4) evaluated to false}} expected-note{{'sizeof(long long) == 4' (8 == 4) evaluated to false}} expected-note{{'sizeof(int [20]) == 4' (80 == 4) evaluated to false}}
-constexpr auto SumSizes = (sizeof(Ts) + ...);
-
-static_assert(SumSizes<char, long long, int> == 13);
-static_assert(SumSizes<char, long long, int[20]> == 89); // expected-error{{constraints not satisfied for variable template 'SumSizes' [with Ts = <char, long long, int [20]>]}}
-
-template<typename T>
-concept IsBig = sizeof(T) > 100; // expected-note{{because 'sizeof(int) > 100' (4 > 100) evaluated to false}}
-
-template<typename T>
- requires IsBig<T> // expected-note{{'int' does not satisfy 'IsBig'}}
-using BigPtr = T*;
-
-static_assert(sizeof(BigPtr<int>)); // expected-error{{constraints not satisfied for alias template 'BigPtr' [with T = int]}}}}
-
-template<typename T> requires T::value // expected-note{{because substituted constraint expression is ill-formed: type 'int' cannot be used prior to '::' because it has no members}}
-struct S { static constexpr bool value = true; };
-
-struct S2 { static constexpr bool value = true; };
-
-static_assert(S<int>::value); // expected-error{{constraints not satisfied for class template 'S' [with T = int]}}
-static_assert(S<S2>::value);
-
-template<typename T>
-struct AA
-{
- template<typename U> requires sizeof(U) == sizeof(T) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}}
- struct B
- {
- static constexpr int a = 0;
- };
-
- template<typename U> requires sizeof(U) == sizeof(T) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}}
- static constexpr int b = 1;
-
- template<typename U> requires sizeof(U) == sizeof(T) // expected-note{{because 'sizeof(int [2]) == sizeof(int)' (8 == 4) evaluated to false}}
- static constexpr int getB() { // expected-note{{candidate template ignored: constraints not satisfied [with U = int [2]]}}
- return 2;
- }
-
- static auto foo()
- {
- return B<T[2]>::a; // expected-error{{constraints not satisfied for class template 'B' [with U = int [2]]}}
- }
-
- static auto foo1()
- {
- return b<T[2]>; // expected-error{{constraints not satisfied for variable template 'b' [with U = int [2]]}}
- }
-
- static auto foo2()
- {
- return AA<T>::getB<T[2]>(); // expected-error{{no matching function for call to 'getB'}}
- }
-};
-
-constexpr auto x = AA<int>::foo(); // expected-note{{in instantiation of member function 'AA<int>::foo' requested here}}
-constexpr auto x1 = AA<int>::foo1(); // expected-note{{in instantiation of member function 'AA<int>::foo1' requested here}}
-constexpr auto x2 = AA<int>::foo2(); // expected-note{{in instantiation of member function 'AA<int>::foo2' requested here}}
-
-template<typename T>
-struct B { using type = typename T::type; }; // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
-
-template<typename T> requires B<T>::type // expected-note{{in instantiation of template class 'B<int>' requested here}}
- // expected-note at -1{{while substituting template arguments into constraint expression here}}
-struct C { };
-
-template<typename T> requires T{} // expected-error{{atomic constraint must be of type 'bool' (found 'int')}}
-struct D { };
-
-static_assert(C<int>{}); // expected-note{{while checking constraint satisfaction for template 'C<int>' required here}}
-static_assert(D<int>{}); // expected-note{{while checking constraint satisfaction for template 'D<int>' required here}}
\ No newline at end of file
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp
deleted file mode 100644
index 47bd2a550769..000000000000
--- a/clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
-
-namespace class_templates
-{
- template<typename T, typename U> requires sizeof(T) >= 4 // expected-note {{because 'sizeof(char) >= 4' (1 >= 4) evaluated to false}}
- struct is_same { static constexpr bool value = false; };
-
- template<typename T> requires sizeof(T*) >= 4 && sizeof(T) >= 4
- struct is_same<T*, T*> { static constexpr bool value = true; };
-
- static_assert(!is_same<char*, char*>::value);
- static_assert(!is_same<short*, short*>::value);
- static_assert(is_same<int*, int*>::value);
- static_assert(is_same<char, char>::value); // expected-error {{constraints not satisfied for class template 'is_same' [with T = char, U = char]}}
-
- template<typename T>
- struct A { using type = typename T::type; }; // expected-error{{type 'int *' cannot be used prior to '::' because it has no members}}
-
- template<typename T>
- struct B {};
-
- template<typename T> requires A<T>::type // expected-note{{in instantiation of template class 'class_templates::A<int *>' requested here}}
- // expected-note at -1{{while substituting template arguments into constraint expression here}}
- struct B<T*> {};
-
- template<typename T> requires T{} // expected-error{{atomic constraint must be of type 'bool' (found 'int')}}
- struct B<T**> {};
-
- static_assert((B<int**>{}, true)); // expected-note{{while checking constraint satisfaction for class template partial specialization 'B<int *>' required here}}
- // expected-note at -1{{while checking constraint satisfaction for class template partial specialization 'B<int>' required here}}
- // expected-note at -2{{during template argument deduction for class template partial specialization 'B<T *>' [with T = int *]}}
- // expected-note at -3{{during template argument deduction for class template partial specialization 'B<T **>' [with T = int]}}
- // expected-note at -4 2{{in instantiation of template class 'class_templates::B<int **>' requested here}}
-}
-
-namespace variable_templates
-{
- template<typename T, typename U> requires sizeof(T) >= 4
- constexpr bool is_same_v = false;
-
- template<typename T> requires sizeof(T*) >= 4 && sizeof(T) >= 4
- constexpr bool is_same_v<T*, T*> = true;
-
- static_assert(!is_same_v<char*, char*>);
- static_assert(!is_same_v<short*, short*>);
- static_assert(is_same_v<int*, int*>);
-
- template<typename T>
- struct A { using type = typename T::type; }; // expected-error{{type 'int *' cannot be used prior to '::' because it has no members}}
-
- template<typename T>
- constexpr bool v1 = false;
-
- template<typename T> requires A<T>::type // expected-note{{in instantiation of template class 'variable_templates::A<int *>' requested here}}
- // expected-note at -1{{while substituting template arguments into constraint expression here}}
- constexpr bool v1<T*> = true;
-
- template<typename T> requires T{} // expected-error{{atomic constraint must be of type 'bool' (found 'int')}}
- constexpr bool v1<T**> = true;
-
- static_assert(v1<int**>); // expected-note{{while checking constraint satisfaction for variable template partial specialization 'v1<int *>' required here}}
- // expected-note at -1{{while checking constraint satisfaction for variable template partial specialization 'v1<int>' required here}}
- // expected-note at -2{{during template argument deduction for variable template partial specialization 'v1<T *>' [with T = int *]}}
- // expected-note at -3{{during template argument deduction for variable template partial specialization 'v1<T **>' [with T = int]}}
- // expected-error at -4{{static_assert failed due to requirement 'v1<int **>'}}
-
-}
\ No newline at end of file
More information about the cfe-commits
mailing list