Revert 374882 "[Concepts] Concept Specialization Expressions"

This reverts commit ec87b003823d63f3342cf648f55a134c1522e612.
The test fails on Windows, see e.g.
http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/11533/steps/stage%201%20check/logs/stdio

Also revert follow-up r374893.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374899 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 57ccba8..61e7a91 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -17,7 +17,6 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/NestedNameSpecifier.h"
@@ -57,7 +56,6 @@
 class LambdaCapture;
 class NonTypeTemplateParmDecl;
 class TemplateParameterList;
-class Sema;
 
 //===--------------------------------------------------------------------===//
 // C++ Expressions.
@@ -4752,125 +4750,6 @@
   }
 };
 
-/// \brief Represents the specialization of a concept - evaluates to a prvalue
-/// of type bool.
-///
-/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
-/// specialization of a concept results in a prvalue of type bool.
-class ConceptSpecializationExpr final : public Expr,
-      private llvm::TrailingObjects<ConceptSpecializationExpr,
-                                    TemplateArgument> {
-  friend class ASTStmtReader;
-  friend TrailingObjects;
-
-  // \brief The optional nested name specifier used when naming the concept.
-  NestedNameSpecifierLoc NestedNameSpec;
-
-  /// \brief The location of the template keyword, if specified when naming the
-  /// concept.
-  SourceLocation TemplateKWLoc;
-
-  /// \brief The location of the concept name in the expression.
-  SourceLocation ConceptNameLoc;
-
-  /// \brief The declaration found by name lookup when the expression was
-  /// created.
-  /// Can differ from NamedConcept when, for example, the concept was found
-  /// 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 template argument list source info used to specialize the
-  /// concept.
-  const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
-
-  /// \brief The number of template arguments in the tail-allocated list of
-  /// converted template arguments.
-  unsigned NumTemplateArgs;
-
-  ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
-                            SourceLocation TemplateKWLoc,
-                            SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
-                            ConceptDecl *NamedConcept,
-                            const ASTTemplateArgumentListInfo *ArgsAsWritten,
-                            ArrayRef<TemplateArgument> ConvertedArgs,
-                            Optional<bool> IsSatisfied);
-
-  ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
-
-public:
-
-  static ConceptSpecializationExpr *
-  Create(ASTContext &C, NestedNameSpecifierLoc NNS,
-         SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
-         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
-         const ASTTemplateArgumentListInfo *ArgsAsWritten,
-         ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);
-
-  static ConceptSpecializationExpr *
-  Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
-
-  const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
-    return NestedNameSpec;
-  }
-
-  NamedDecl *getFoundDecl() const {
-    return FoundDecl;
-  }
-
-  ConceptDecl *getNamedConcept() const {
-    return NamedConcept.getPointer();
-  }
-
-  ArrayRef<TemplateArgument> getTemplateArguments() const {
-    return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
-                                      NumTemplateArgs);
-  }
-
-  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
-    return ArgsAsWritten;
-  }
-
-  /// \brief Set new template arguments for this concept specialization.
-  void setTemplateArguments(const ASTTemplateArgumentListInfo *ArgsAsWritten,
-                            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!
-  bool isSatisfied() const {
-    assert(!isValueDependent()
-           && "isSatisfied called on a dependent ConceptSpecializationExpr");
-    return NamedConcept.getInt();
-  }
-
-  SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
-
-  SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
-
-  static bool classof(const Stmt *T) {
-    return T->getStmtClass() == ConceptSpecializationExprClass;
-  }
-
-  SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; }
-  SourceLocation getEndLoc() const LLVM_READONLY {
-    return ArgsAsWritten->RAngleLoc;
-  }
-
-  // Iterators
-  child_range children() {
-    return child_range(child_iterator(), child_iterator());
-  }
-  const_child_range children() const {
-    return const_child_range(const_child_iterator(), const_child_iterator());
-  }
-};
-
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_EXPRCXX_H
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 998cf92..09a6f78 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2659,12 +2659,6 @@
   }
 })
 
-DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
-  TRY_TO(TraverseTemplateArgumentLocsHelper(
-          S->getTemplateArgsAsWritten()->getTemplateArgs(),
-          S->getTemplateArgsAsWritten()->NumTemplateArgs));
-})
-
 // These literals (all of them) do not need any action.
 DEF_TRAVERSE_STMT(IntegerLiteral, {})
 DEF_TRAVERSE_STMT(FixedPointLiteral, {})
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 968c2db..47a1dee 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2526,6 +2526,8 @@
   "use __attribute__((visibility(\"hidden\"))) attribute instead">;
 
 // C++ Concepts
+def err_concept_initialized_with_non_bool_type : Error<
+  "constraint expression must be of type 'bool' but is of type %0">;
 def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<
   "concept declarations may only appear in global or namespace scope">;
 def err_concept_no_parameters : Error<
@@ -2537,11 +2539,6 @@
   "concept cannot have associated constraints">;
 def err_concept_not_implemented : Error<
   "sorry, unimplemented concepts feature %0 used">;
-def err_non_constant_constraint_expression : Error<
-  "substitution into constraint expression resulted in a non-constant "
-  "expression">;
-def err_non_bool_atomic_constraint : Error<
-  "atomic constraint must be of type 'bool' (found %0)">;
 
 def err_template_different_associated_constraints : Error<
   "associated constraints differ in template redeclaration">;
@@ -4499,10 +4496,6 @@
   " template parameter%1 %2">;
 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_constraint_substitution_here : Note<
-  "while substituting template arguments into constraint expression here">;
 def note_instantiation_contexts_suppressed : Note<
   "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
   "see all)">;
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 6231484..1cef89f 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -163,9 +163,6 @@
 def DependentCoawaitExpr : DStmt<Expr>;
 def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
 
-// C++2a Concepts expressions
-def ConceptSpecializationExpr : DStmt<Expr>;
-
 // Obj-C Expressions.
 def ObjCStringLiteral : DStmt<Expr>;
 def ObjCBoxedExpr : DStmt<Expr>;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 6b2d603..0403df4 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -6047,16 +6047,7 @@
                                            CXXConversionDecl *Conv,
                                            Expr *Src);
 
-  /// Check whether the given expression is a valid constraint expression.
-  /// 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);
-
-    // ParseObjCStringLiteral - Parse Objective-C string literals.
+  // ParseObjCStringLiteral - Parse Objective-C string literals.
   ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
                                     ArrayRef<Expr *> Strings);
 
@@ -6727,9 +6718,9 @@
 
   ExprResult
   CheckConceptTemplateId(const CXXScopeSpec &SS,
-                         SourceLocation TemplateKWLoc,
-                         SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
-                         ConceptDecl *NamedConcept,
+                         const DeclarationNameInfo &NameInfo,
+                         ConceptDecl *Template,
+                         SourceLocation TemplateLoc,
                          const TemplateArgumentListInfo *TemplateArgs);
 
   void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
@@ -7648,15 +7639,6 @@
       /// member).
       DefiningSynthesizedFunction,
 
-      // We are checking the constraints associated with a constrained entity or
-      // the constraint expression of a concept. This includes the checks that
-      // atomic constraints have the type 'bool' and that they can be constant
-      // evaluated.
-      ConstraintsCheck,
-
-      // We are substituting template arguments into a constraint expression.
-      ConstraintSubstitution,
-
       /// Added for Template instantiation observation.
       /// Memoization means we are _not_ instantiating a template because
       /// it is already instantiated (but we entered a context where we
@@ -7917,23 +7899,6 @@
                           ArrayRef<TemplateArgument> TemplateArgs,
                           SourceRange InstantiationRange);
 
-    struct ConstraintsCheck {};
-    /// \brief Note that we are checking the constraints associated with some
-    /// constrained entity (a concept declaration or a template with associated
-    /// constraints).
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ConstraintsCheck, TemplateDecl *Template,
-                          ArrayRef<TemplateArgument> TemplateArgs,
-                          SourceRange InstantiationRange);
-
-    struct ConstraintSubstitution {};
-    /// \brief Note that we are checking a constraint expression associated
-    /// with a template declaration or as part of the satisfaction check of a
-    /// concept.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ConstraintSubstitution, TemplateDecl *Template,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange);
 
     /// Note that we have finished instantiating this template.
     void Clear();
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 0d3971d..eab1ec8 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1915,7 +1915,6 @@
       EXPR_FUNCTION_PARM_PACK,    // FunctionParmPackExpr
       EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
       EXPR_CXX_FOLD,              // CXXFoldExpr
-      EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr
 
       // CUDA
       EXPR_CUDA_KERNEL_CALL,       // CUDAKernelCallExpr
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index f2e6251..339f471 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3403,7 +3403,6 @@
   case CXXUuidofExprClass:
   case OpaqueValueExprClass:
   case SourceLocExprClass:
-  case ConceptSpecializationExprClass:
     // These never have a side-effect.
     return false;
 
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a9b7c00..cb6b870 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -1680,82 +1680,3 @@
                            alignof(CUDAKernelCallExpr));
   return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
 }
-
-ConceptSpecializationExpr::ConceptSpecializationExpr(ASTContext &C,
-    NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
-    SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
-    ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,
-    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=*/!IsSatisfied.hasValue(),
-           /*InstantiationDependent=*/false,
-           /*ContainsUnexpandedParameterPacks=*/false),
-      NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
-      ConceptNameLoc(ConceptNameLoc), FoundDecl(FoundDecl),
-      NamedConcept(NamedConcept, IsSatisfied ? *IsSatisfied : true),
-      NumTemplateArgs(ConvertedArgs.size()) {
-
-  setTemplateArguments(ArgsAsWritten, ConvertedArgs);
-}
-
-ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
-    unsigned NumTemplateArgs)
-    : Expr(ConceptSpecializationExprClass, Empty),
-      NumTemplateArgs(NumTemplateArgs) { }
-
-void ConceptSpecializationExpr::setTemplateArguments(
-    const ASTTemplateArgumentListInfo *ArgsAsWritten,
-    ArrayRef<TemplateArgument> Converted) {
-  assert(Converted.size() == NumTemplateArgs);
-  assert(!this->ArgsAsWritten && "setTemplateArguments can only be used once");
-  this->ArgsAsWritten = ArgsAsWritten;
-  std::uninitialized_copy(Converted.begin(), Converted.end(),
-                          getTrailingObjects<TemplateArgument>());
-  bool IsInstantiationDependent = false;
-  bool ContainsUnexpandedParameterPack = false;
-  for (const TemplateArgumentLoc& LocInfo : ArgsAsWritten->arguments()) {
-    if (LocInfo.getArgument().isInstantiationDependent())
-      IsInstantiationDependent = true;
-    if (LocInfo.getArgument().containsUnexpandedParameterPack())
-      ContainsUnexpandedParameterPack = true;
-    if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
-      break;
-  }
-
-  // Currently guaranteed by the fact concepts can only be at namespace-scope.
-  assert(!NestedNameSpec ||
-         (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
-          !NestedNameSpec.getNestedNameSpecifier()
-              ->containsUnexpandedParameterPack()));
-  setInstantiationDependent(IsInstantiationDependent);
-  setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
-  assert((!isValueDependent() || isInstantiationDependent()) &&
-         "should not be value-dependent");
-}
-
-ConceptSpecializationExpr *
-ConceptSpecializationExpr::Create(ASTContext &C, NestedNameSpecifierLoc NNS,
-                                  SourceLocation TemplateKWLoc,
-                                  SourceLocation ConceptNameLoc,
-                                  NamedDecl *FoundDecl,
-                                  ConceptDecl *NamedConcept,
-                               const ASTTemplateArgumentListInfo *ArgsAsWritten,
-                                  ArrayRef<TemplateArgument> ConvertedArgs,
-                                  Optional<bool> IsSatisfied) {
-  void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
-                                ConvertedArgs.size()));
-  return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
-                                                ConceptNameLoc, FoundDecl,
-                                                NamedConcept, ArgsAsWritten,
-                                                ConvertedArgs, IsSatisfied);
-}
-
-ConceptSpecializationExpr *
-ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
-                                  unsigned NumTemplateArgs) {
-  void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
-                                NumTemplateArgs));
-  return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
-}
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index d109cd3..c61ee70 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -192,7 +192,6 @@
   case Expr::NoInitExprClass:
   case Expr::DesignatedInitUpdateExprClass:
   case Expr::SourceLocExprClass:
-  case Expr::ConceptSpecializationExprClass:
     return Cl::CL_PRValue;
 
   case Expr::ConstantExprClass:
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 4459335..ceee50d 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -9768,7 +9768,6 @@
   bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
   bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
   bool VisitSourceLocExpr(const SourceLocExpr *E);
-  bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
   // FIXME: Missing: array subscript of vector, member of vector
 };
 
@@ -12251,12 +12250,6 @@
   return Success(E->getValue(), E);
 }
 
-bool IntExprEvaluator::VisitConceptSpecializationExpr(
-       const ConceptSpecializationExpr *E) {
-  return Success(E->isSatisfied(), E);
-}
-
-
 bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
   switch (E->getOpcode()) {
     default:
@@ -13930,7 +13923,6 @@
   case Expr::CXXBoolLiteralExprClass:
   case Expr::CXXScalarValueInitExprClass:
   case Expr::TypeTraitExprClass:
-  case Expr::ConceptSpecializationExprClass:
   case Expr::ArrayTypeTraitExprClass:
   case Expr::ExpressionTraitExprClass:
   case Expr::CXXNoexceptExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 8e3ad4c..c6f7143 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -3658,7 +3658,6 @@
   case Expr::ConvertVectorExprClass:
   case Expr::StmtExprClass:
   case Expr::TypeTraitExprClass:
-  case Expr::ConceptSpecializationExprClass:
   case Expr::ArrayTypeTraitExprClass:
   case Expr::ExpressionTraitExprClass:
   case Expr::VAArgExprClass:
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 70fe484..e392682 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -2231,17 +2231,6 @@
   OS << ")";
 }
 
-void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
-  NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
-  if (NNS)
-    NNS.getNestedNameSpecifier()->print(OS, Policy);
-  if (E->getTemplateKWLoc().isValid())
-    OS << "template ";
-  OS << E->getFoundDecl()->getName();
-  printTemplateArgumentList(OS, E->getTemplateArgsAsWritten()->arguments(),
-                            Policy);
-}
-
 // C++ Coroutines TS
 
 void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 82bb4b8..9c19305 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -1309,14 +1309,6 @@
   ID.AddInteger(S->getOp());
 }
 
-void StmtProfiler::VisitConceptSpecializationExpr(
-                                           const ConceptSpecializationExpr *S) {
-  VisitExpr(S);
-  VisitDecl(S->getFoundDecl());
-  VisitTemplateArguments(S->getTemplateArgsAsWritten()->getTemplateArgs(),
-                         S->getTemplateArgsAsWritten()->NumTemplateArgs);
-}
-
 static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
                                           UnaryOperatorKind &UnaryOp,
                                           BinaryOperatorKind &BinaryOp) {
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index f139613..a10b18c 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -673,10 +673,6 @@
     return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
   }
 
-  Value *VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {
-    return Builder.getInt1(E->isSatisfied());
-  }
-
   Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
     return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue());
   }
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index fea5826..dc830cb 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -417,10 +417,6 @@
       return "DefiningSynthesizedFunction";
     case CodeSynthesisContext::Memoization:
       return "Memoization";
-    case CodeSynthesisContext::ConstraintsCheck:
-      return "ConstraintsCheck";
-    case CodeSynthesisContext::ConstraintSubstitution:
-      return "ConstraintSubstitution";
     }
     return "";
   }
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b74a95a..455d109 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -228,16 +228,18 @@
 /// Parse a constraint-expression.
 ///
 /// \verbatim
-///       constraint-expression: C++2a[temp.constr.decl]p1
+///       constraint-expression: [Concepts TS temp.constr.decl p1]
 ///         logical-or-expression
 /// \endverbatim
 ExprResult Parser::ParseConstraintExpression() {
-  EnterExpressionEvaluationContext ConstantEvaluated(
-      Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+  // FIXME: this may erroneously consume a function-body as the braced
+  // initializer list of a compound literal
+  //
+  // FIXME: this may erroneously consume a parenthesized rvalue reference
+  // declarator as a parenthesized address-of-label expression
   ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false));
   ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
-  if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get()))
-    return ExprError();
+
   return Res;
 }
 
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 89c3f6c..7423435 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -32,7 +32,6 @@
   SemaCast.cpp
   SemaChecking.cpp
   SemaCodeComplete.cpp
-  SemaConcept.cpp
   SemaConsumer.cpp
   SemaCoroutine.cpp
   SemaCUDA.cpp
diff --git a/lib/Sema/SemaConcept.cpp b/lib/Sema/SemaConcept.cpp
deleted file mode 100644
index 3131609..0000000
--- a/lib/Sema/SemaConcept.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file implements semantic analysis for C++ constraints and concepts.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/Sema/TemplateDeduction.h"
-#include "clang/Sema/Template.h"
-#include "clang/AST/ExprCXX.h"
-using namespace clang;
-using namespace sema;
-
-bool Sema::CheckConstraintExpression(Expr *ConstraintExpression) {
-  // C++2a [temp.constr.atomic]p1
-  // ..E shall be a constant expression of type bool.
-
-  ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
-
-  if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
-    if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
-      return CheckConstraintExpression(BinOp->getLHS()) &&
-             CheckConstraintExpression(BinOp->getRHS());
-  } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
-    return CheckConstraintExpression(C->getSubExpr());
-
-  // An atomic constraint!
-  if (ConstraintExpression->isTypeDependent())
-    return true;
-
-  QualType Type = ConstraintExpression->getType();
-  if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
-    Diag(ConstraintExpression->getExprLoc(),
-         diag::err_non_bool_atomic_constraint) << Type
-        << ConstraintExpression->getSourceRange();
-    return false;
-  }
-  return true;
-}
-
-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) {
-      if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),
-                                          IsSatisfied))
-        return true;
-      if (!IsSatisfied)
-        return false;
-      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(NamedConcept, MLTAL, BO->getRHS(),
-                                             IsSatisfied);
-    }
-  }
-  else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
-    return CalculateConstraintSatisfaction(NamedConcept, MLTAL, C->getSubExpr(),
-                                           IsSatisfied);
-
-  EnterExpressionEvaluationContext ConstantEvaluated(
-      *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);
-
-    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;
-    }
-  }
-
-  if (!CheckConstraintExpression(E.get()))
-    return true;
-
-  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;
-  }
-
-  IsSatisfied = EvalResult.Val.getInt().getBoolValue();
-
-  return false;
-}
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 76fd10d..0f3a272 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -1314,7 +1314,6 @@
   case Expr::SizeOfPackExprClass:
   case Expr::StringLiteralClass:
   case Expr::SourceLocExprClass:
-  case Expr::ConceptSpecializationExprClass:
     // These expressions can never throw.
     return CT_Cannot;
 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index cb756eb..284962f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4271,47 +4271,14 @@
 
 ExprResult
 Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
-                             SourceLocation TemplateKWLoc,
-                             SourceLocation ConceptNameLoc,
-                             NamedDecl *FoundDecl,
-                             ConceptDecl *NamedConcept,
+                             const DeclarationNameInfo &NameInfo,
+                             ConceptDecl *Template,
+                             SourceLocation TemplateLoc,
                              const TemplateArgumentListInfo *TemplateArgs) {
-  assert(NamedConcept && "A concept template id without a template?");
-
-  llvm::SmallVector<TemplateArgument, 4> Converted;
-  if (CheckTemplateArgumentList(NamedConcept, ConceptNameLoc,
-                           const_cast<TemplateArgumentListInfo&>(*TemplateArgs),
-                                /*PartialTemplateArgs=*/false, Converted,
-                                /*UpdateArgsWithConversion=*/false))
-    return ExprError();
-
-  Optional<bool> IsSatisfied;
-  bool AreArgsDependent = false;
-  for (TemplateArgument &Arg : Converted) {
-    if (Arg.isDependent()) {
-      AreArgsDependent = true;
-      break;
-    }
-  }
-  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,
-      IsSatisfied);
+  // TODO: Do concept specialization here.
+  Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) <<
+    "concept specialization";
+  return ExprError();
 }
 
 ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -4355,10 +4322,9 @@
   }
 
   if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) {
-    return CheckConceptTemplateId(SS, TemplateKWLoc,
-                                  R.getLookupNameInfo().getBeginLoc(),
-                                  R.getFoundDecl(),
-                                  R.getAsSingle<ConceptDecl>(), TemplateArgs);
+    return CheckConceptTemplateId(SS, R.getLookupNameInfo(),
+                                  R.getAsSingle<ConceptDecl>(),
+                                  TemplateKWLoc, TemplateArgs);
   }
 
   // We don't want lookup warnings at this point.
@@ -8088,7 +8054,20 @@
   ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name,
                                              TemplateParameterLists.front(),
                                              ConstraintExpr);
-                                             
+
+  if (!ConstraintExpr->isTypeDependent() &&
+      ConstraintExpr->getType() != Context.BoolTy) {
+    // C++2a [temp.constr.atomic]p3:
+    // E shall be a constant expression of type bool.
+    // TODO: Do this check for individual atomic constraints
+    // and not the constraint expression. Probably should do it in
+    // ParseConstraintExpression.
+    Diag(ConstraintExpr->getSourceRange().getBegin(),
+        diag::err_concept_initialized_with_non_bool_type)
+      << ConstraintExpr->getType();
+    NewDecl->setInvalidDecl();
+  }
+
   if (NewDecl->getAssociatedConstraints()) {
     // C++2a [temp.concept]p4:
     // A concept shall not have associated constraints.
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 42411c9..9091bc5 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -198,14 +198,12 @@
   case ExplicitTemplateArgumentSubstitution:
   case DeducedTemplateArgumentSubstitution:
   case PriorTemplateArgumentSubstitution:
-  case ConstraintsCheck:
     return true;
 
   case DefaultTemplateArgumentChecking:
   case DeclaringSpecialMember:
   case DefiningSynthesizedFunction:
   case ExceptionSpecEvaluation:
-  case ConstraintSubstitution:
     return false;
 
   // This function should never be called when Kind's value is Memoization.
@@ -360,24 +358,6 @@
           PointOfInstantiation, InstantiationRange, Param, Template,
           TemplateArgs) {}
 
-Sema::InstantiatingTemplate::InstantiatingTemplate(
-    Sema &SemaRef, SourceLocation PointOfInstantiation,
-    ConstraintsCheck, TemplateDecl *Template,
-    ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
-    : InstantiatingTemplate(
-          SemaRef, CodeSynthesisContext::ConstraintsCheck,
-          PointOfInstantiation, InstantiationRange, Template, nullptr,
-          TemplateArgs) {}
-
-Sema::InstantiatingTemplate::InstantiatingTemplate(
-    Sema &SemaRef, SourceLocation PointOfInstantiation,
-    ConstraintSubstitution, TemplateDecl *Template,
-    sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
-    : InstantiatingTemplate(
-          SemaRef, CodeSynthesisContext::ConstraintSubstitution,
-          PointOfInstantiation, InstantiationRange, Template, nullptr,
-          {}, &DeductionInfo) {}
-
 void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
   Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
   InNonInstantiationSFINAEContext = false;
@@ -684,30 +664,6 @@
 
     case CodeSynthesisContext::Memoization:
       break;
-    
-    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;
-      }
-      // 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)
-          << Active->InstantiationRange;
-      break;
     }
   }
 }
@@ -731,7 +687,6 @@
       LLVM_FALLTHROUGH;
     case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
     case CodeSynthesisContext::ExceptionSpecInstantiation:
-    case CodeSynthesisContext::ConstraintsCheck:
       // This is a template instantiation, so there is no SFINAE.
       return None;
 
@@ -745,10 +700,8 @@
 
     case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
     case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
-    case CodeSynthesisContext::ConstraintSubstitution:
-      // We're either substituting explicitly-specified template arguments
-      // or deduced template arguments or a constraint expression, so SFINAE
-      // applies.
+      // We're either substitution explicitly-specified template arguments
+      // or deduced template arguments, so SFINAE applies.
       assert(Active->DeductionInfo && "Missing deduction info pointer");
       return Active->DeductionInfo;
 
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 8184d4c..59cac78 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3019,25 +3019,6 @@
   ///
   /// By default, performs semantic analysis to build the new expression.
   /// Subclasses may override this routine to provide different behavior.
-  ExprResult RebuildConceptSpecializationExpr(NestedNameSpecifierLoc NNS,
-      SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
-      NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
-      TemplateArgumentListInfo *TALI) {
-    CXXScopeSpec SS;
-    SS.Adopt(NNS);
-    ExprResult Result = getSema().CheckConceptTemplateId(SS, TemplateKWLoc,
-                                                         ConceptNameLoc,
-                                                         FoundDecl,
-                                                         NamedConcept, TALI);
-    if (Result.isInvalid())
-      return ExprError();
-    return Result;
-  }
-
-    /// \brief Build a new Objective-C boxed expression.
-  ///
-  /// By default, performs semantic analysis to build the new expression.
-  /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
     return getSema().BuildObjCBoxedExpr(SR, ValueExpr);
   }
@@ -11035,23 +11016,6 @@
 
 template<typename Derived>
 ExprResult
-TreeTransform<Derived>::TransformConceptSpecializationExpr(
-                                                 ConceptSpecializationExpr *E) {
-  const ASTTemplateArgumentListInfo *Old = E->getTemplateArgsAsWritten();
-  TemplateArgumentListInfo TransArgs(Old->LAngleLoc, Old->RAngleLoc);
-  if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
-                                              Old->NumTemplateArgs, TransArgs))
-    return ExprError();
-
-  return getDerived().RebuildConceptSpecializationExpr(
-      E->getNestedNameSpecifierLoc(), E->getTemplateKWLoc(),
-      E->getConceptNameLoc(), E->getFoundDecl(), E->getNamedConcept(),
-      &TransArgs);
-}
-
-
-template<typename Derived>
-ExprResult
 TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
   TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());
   if (!T)
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 7eb56e1..0c802a6 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -734,24 +734,6 @@
   E->setRParenLoc(ReadSourceLocation());
 }
 
-void ASTStmtReader::VisitConceptSpecializationExpr(
-        ConceptSpecializationExpr *E) {
-  VisitExpr(E);
-  unsigned NumTemplateArgs = Record.readInt();
-  E->NestedNameSpec = Record.readNestedNameSpecifierLoc();
-  E->TemplateKWLoc = Record.readSourceLocation();
-  E->ConceptNameLoc = Record.readSourceLocation();
-  E->FoundDecl = ReadDeclAs<NamedDecl>();
-  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);
-  E->NamedConcept.setInt(Record.readInt() == 1);
-}
-
 void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
   VisitExpr(E);
   E->setLHS(Record.readSubExpr());
@@ -3508,12 +3490,6 @@
     case EXPR_DEPENDENT_COAWAIT:
       S = new (Context) DependentCoawaitExpr(Empty);
       break;
-
-    case EXPR_CONCEPT_SPECIALIZATION:
-      unsigned numTemplateArgs = Record[ASTStmtReader::NumExprFields];
-      S = ConceptSpecializationExpr::Create(Context, Empty, numTemplateArgs);
-      break;
-      
     }
 
     // We hit a STMT_STOP, so we're done with this expression.
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index deba1cc..387ed44 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -388,24 +388,6 @@
   Code = serialization::EXPR_DEPENDENT_COAWAIT;
 }
 
-void ASTStmtWriter::VisitConceptSpecializationExpr(
-        ConceptSpecializationExpr *E) {
-  VisitExpr(E);
-  ArrayRef<TemplateArgument> TemplateArgs = E->getTemplateArguments();
-  Record.push_back(TemplateArgs.size());
-  Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc());
-  Record.AddSourceLocation(E->getTemplateKWLoc());
-  Record.AddSourceLocation(E->getConceptNameLoc());
-  Record.AddDeclRef(E->getFoundDecl());
-  Record.AddDeclRef(E->getNamedConcept());
-  Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten());
-  for (const TemplateArgument &Arg : TemplateArgs)
-    Record.AddTemplateArgument(Arg);
-  Record.push_back(E->isSatisfied());
-  Code = serialization::EXPR_CONCEPT_SPECIALIZATION;
-}
-
-
 void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) {
   VisitStmt(S);
   // NumCaptures
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 8629fd9..855ecf1 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1370,7 +1370,6 @@
     case Stmt::CUDAKernelCallExprClass:
     case Stmt::OpaqueValueExprClass:
     case Stmt::AsTypeExprClass:
-    case Stmt::ConceptSpecializationExprClass:
       // Fall through.
 
     // Cases we intentionally don't evaluate, since they don't need
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
new file mode 100644
index 0000000..863b608
--- /dev/null
+++ b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
@@ -0,0 +1,61 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -fcxx-exceptions -x c++ -verify %s
+
+namespace A {
+  template<typename T> concept bool C1() { return true; }
+
+  template<typename T> concept bool C2 = true;
+}
+
+template<typename T> concept bool C3() { return (throw 0, true); }
+static_assert(noexcept(C3<int>()), "function concept should be treated as if noexcept(true) specified");
+
+template<typename T> concept bool D1(); // expected-error {{function concept declaration must be a definition}}
+
+struct B {
+  template<typename T> concept bool D2() { return true; } // expected-error {{concept declarations may only appear in namespace scope}}
+};
+
+struct C {
+  template<typename T> static concept bool D3 = true; // expected-error {{concept declarations may only appear in namespace scope}}
+};
+
+concept bool D4() { return true; } // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+
+concept bool D5 = true; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+
+template<typename T>
+concept bool D6; // expected-error {{variable concept declaration must be initialized}}
+
+template<typename T>
+concept bool D7() throw(int) { return true; } // expected-error {{function concept cannot have exception specification}}
+
+// Tag
+
+concept class CC1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+concept struct CS1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+concept union CU1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+concept enum CE1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+template <typename T> concept class TCC1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+template <typename T> concept struct TCS1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+template <typename T> concept union TCU1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+typedef concept int CI; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+void fpc(concept int i) {} // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+
+concept bool; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+
+template <typename T> concept bool VCEI{ true };
+template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+extern template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+
+template <typename T> concept bool VCPS{ true };
+template <typename T> concept bool VCPS<T *>{ true }; // expected-error {{'concept' cannot be applied on an partial specialization}}
+
+template <typename T> concept bool VCES{ true };
+template <> concept bool VCES<int>{ true }; // expected-error {{'concept' cannot be applied on an explicit specialization}}
+
+template <typename T> concept bool FCEI() { return true; }
+template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+extern template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+
+template <typename T> concept bool FCES() { return true; }
+template <> concept bool FCES<bool>() { return true; } // expected-error {{'concept' cannot be applied on an explicit specialization}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p2.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p2.cpp
new file mode 100644
index 0000000..4779109
--- /dev/null
+++ b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p2.cpp
@@ -0,0 +1,13 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template<typename T> concept thread_local bool VCTL = true; // expected-error {{variable concept cannot be declared 'thread_local'}}
+
+template<typename T> concept constexpr bool VCC = true; // expected-error {{variable concept cannot be declared 'constexpr'}}
+
+template<typename T> concept inline bool FCI() { return true; } // expected-error {{function concept cannot be declared 'inline'}}
+
+struct X {
+  template<typename T> concept friend bool FCF() { return true; } // expected-error {{function concept cannot be declared 'friend'}}
+};
+
+template<typename T> concept constexpr bool FCC() { return true; } // expected-error {{function concept cannot be declared 'constexpr'}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p5.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p5.cpp
new file mode 100644
index 0000000..69672ca
--- /dev/null
+++ b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p5.cpp
@@ -0,0 +1,25 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template<typename T>
+concept bool fcpv(void) { return true; }
+
+template<typename T>
+concept bool fcpi(int i = 0) { return true; } // expected-error {{function concept cannot have any parameters}}
+
+template<typename... Ts>
+concept bool fcpp(Ts... ts) { return true; } // expected-error {{function concept cannot have any parameters}}
+
+template<typename T>
+concept bool fcpva(...) { return true; } // expected-error {{function concept cannot have any parameters}}
+
+template<typename T>
+concept const bool fcrtc() { return true; } // expected-error {{declared return type of function concept must be 'bool'}}
+
+template<typename T>
+concept int fcrti() { return 5; } // expected-error {{declared return type of function concept must be 'bool'}}
+
+template<typename T>
+concept float fcrtf() { return 5.5; } // expected-error {{declared return type of function concept must be 'bool'}}
+
+template<typename T>
+concept decltype(auto) fcrtd(void) { return true; } // expected-error {{declared return type of function concept must be 'bool'}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p6.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p6.cpp
new file mode 100644
index 0000000..f8a1bb7
--- /dev/null
+++ b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p6.cpp
@@ -0,0 +1,25 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template<typename T>
+concept bool vc { true };
+
+template<typename T>
+struct B { typedef bool Boolean; };
+
+template<int N>
+B<void>::Boolean concept vctb(!0);
+
+template<typename T>
+concept const bool vctc { true }; // expected-error {{declared type of variable concept must be 'bool'}}
+
+template<typename T>
+concept int vcti { 5 }; // expected-error {{declared type of variable concept must be 'bool'}}
+
+template<typename T>
+concept float vctf { 5.5 }; // expected-error {{declared type of variable concept must be 'bool'}}
+
+template<typename T>
+concept auto vcta { true }; // expected-error {{declared type of variable concept must be 'bool'}}
+
+template<typename T>
+concept decltype(auto) vctd { true }; // expected-error {{declared type of variable concept must be 'bool'}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp
new file mode 100644
index 0000000..1bad6bb
--- /dev/null
+++ b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp
@@ -0,0 +1,18 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template <typename T> concept bool FCEI() { return true; } // expected-note {{previous declaration is here}} expected-note {{previous declaration is here}}
+template bool FCEI<int>(); // expected-error {{function concept cannot be explicitly instantiated}}
+extern template bool FCEI<double>(); // expected-error {{function concept cannot be explicitly instantiated}}
+
+template <typename T> concept bool FCES() { return true; } // expected-note {{previous declaration is here}}
+template <> bool FCES<int>() { return true; } // expected-error {{function concept cannot be explicitly specialized}}
+
+template <typename T> concept bool VC { true }; // expected-note {{previous declaration is here}} expected-note {{previous declaration is here}}
+template bool VC<int>; // expected-error {{variable concept cannot be explicitly instantiated}}
+extern template bool VC<double>; // expected-error {{variable concept cannot be explicitly instantiated}}
+
+template <typename T> concept bool VCES { true }; // expected-note {{previous declaration is here}}
+template <> bool VCES<int> { true }; // expected-error {{variable concept cannot be explicitly specialized}}
+
+template <typename T> concept bool VCPS { true }; // expected-note {{previous declaration is here}}
+template <typename T> bool VCPS<T *> { true }; // expected-error {{variable concept cannot be partially specialized}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/lit.cfg.py b/test/CXX/concepts-ts/dcl.dcl/lit.cfg.py
new file mode 100644
index 0000000..c705e3c
--- /dev/null
+++ b/test/CXX/concepts-ts/dcl.dcl/lit.cfg.py
@@ -0,0 +1,26 @@
+# -*- Python -*-
+
+import os
+import lit.formats
+
+from lit.llvm import llvm_config
+
+# Configuration file for the 'lit' test runner.
+
+# name: The name of this test suite.
+config.name = 'Clang-Concepts-TS-Unsupported'
+
+# testFormat: The test format to use to interpret tests.
+#
+# For now we require '&&' between commands, until they get globally killed and
+# the test runner updated.
+config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.c', '.cpp', '.cppm', '.m', '.mm', '.cu',
+                   '.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs']
+
+config.unsupported = True
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
diff --git a/test/CXX/concepts-ts/expr/expr.prim/expr.prim.id/p3.cpp b/test/CXX/concepts-ts/expr/expr.prim/expr.prim.id/p3.cpp
new file mode 100644
index 0000000..16da146
--- /dev/null
+++ b/test/CXX/concepts-ts/expr/expr.prim/expr.prim.id/p3.cpp
@@ -0,0 +1,4 @@
+// RUN:  %clang_cc1 -std=c++2a -fconcepts-ts -verify %s
+
+template<typename T> concept C = true;
+static_assert(C<int>); // expected-error{{sorry, unimplemented concepts feature concept specialization used}}
diff --git a/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp b/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
similarity index 100%
rename from test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
rename to test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
diff --git a/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp b/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
deleted file mode 100644
index dd3f0c0..0000000
--- a/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// RUN:  %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s
-
-template<typename T> concept C1 = true; // expected-note{{template is declared here}}
-static_assert(C1<int>);
-static_assert(C1);
-// expected-error@-1{{use of concept 'C1' requires template arguments}}
-
-template<typename T> concept C2 = sizeof(T) == 4;
-static_assert(C2<int>);
-static_assert(!C2<long long int>);
-static_assert(C2<char[4]>);
-static_assert(!C2<char[5]>);
-
-template<typename T> concept C3 = sizeof(*T{}) == 4;
-static_assert(C3<int*>);
-static_assert(!C3<long long int>);
-
-struct A {
-  static constexpr int add(int a, int b) {
-    return a + b;
-  }
-};
-struct B {
-  static int add(int a, int b) { // expected-note{{declared here}}
-    return a + b;
-  }
-};
-template<typename U>
-concept C4 = U::add(1, 2) == 3;
-// expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}}
-// expected-note@-2{{non-constexpr function 'add' cannot be used in a constant expression}}
-static_assert(C4<A>);
-static_assert(!C4<B>); // expected-note {{while checking the satisfaction of concept 'C4<B>' requested here}}
-
-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, typename U>
-concept Same = is_same_v<T, U>;
-
-static_assert(Same<int, int>);
-static_assert(Same<int, decltype(1)>);
-static_assert(!Same<int, unsigned int>);
-static_assert(!Same<A, B>);
-static_assert(Same<A, A>);
-
-static_assert(Same<bool, decltype(C1<int>)>);
-static_assert(Same<bool, decltype(C2<int>)>);
-static_assert(Same<bool, decltype(C3<int*>)>);
-static_assert(Same<bool, decltype(C4<A>)>);
-
-template<typename T> concept C5 = T{}; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
-constexpr bool x = C5<int>; // expected-note {{while checking the satisfaction of concept 'C5<int>' requested here}}
-
-template<int x>
-concept IsEven = (x % 2) == 0;
-
-static_assert(IsEven<20>);
-static_assert(!IsEven<11>);
-
-template<template<typename T> typename P>
-concept IsTypePredicate = is_same_v<decltype(P<bool>::value), const bool>
-                          && is_same_v<decltype(P<int>::value), const bool>
-                          && is_same_v<decltype(P<long long>::value), const bool>;
-
-template<typename T> struct T1 {};
-template<typename T> struct T2 { static constexpr bool value = sizeof(T) == 2; };
-
-static_assert(IsTypePredicate<T2>);
-static_assert(!IsTypePredicate<T1>);
-
-namespace piecewise_substitution {
-  template <typename T>
-  concept True = true;
-
-  template <typename T>
-  concept A = True<T> || T::value;
-
-  template <typename T>
-  concept B = (True<T> || T::value);
-
-  template <typename T>
-  concept C = !True<T> && T::value || true;
-
-  template <typename T>
-  concept D = (!True<T> && T::value) || true;
-
-  template <typename T>
-  concept E = T::value || True<T>;
-
-  template <typename T>
-  concept F = (T::value || True<T>);
-
-  template <typename T>
-  concept G = T::value && !True<T> || true;
-
-  template <typename T>
-  concept H = (T::value && !True<T>) || true;
-
-  template <typename T>
-  concept I = T::value;
-
-  static_assert(A<int>);
-  static_assert(B<int>);
-  static_assert(C<int>);
-  static_assert(D<int>);
-  static_assert(E<int>);
-  static_assert(F<int>);
-  static_assert(G<int>);
-  static_assert(H<int>);
-  static_assert(!I<int>);
-}
-
-// Short ciruiting
-
-template<typename T> struct T3 { using type = typename T::type; };
-// expected-error@-1{{type 'char' cannot be used prior to '::' because it has no members}}
-// expected-error@-2{{type 'short' cannot be used prior to '::' because it has no members}}
-
-template<typename T>
-concept C6 = sizeof(T) == 1 && sizeof(typename T3<T>::type) == 1;
-// expected-note@-1{{while substituting template arguments into constraint expression here}}
-// expected-note@-2{{in instantiation of template class 'T3<char>' requested here}}
-
-template<typename T>
-concept C7 = sizeof(T) == 1 || sizeof(
-// expected-note@-1{{while substituting template arguments into constraint expression here}}
-    typename
-      T3<T>
-// expected-note@-1{{in instantiation of template class 'T3<short>' requested here}}
-        ::type) == 1;
-
-static_assert(!C6<short>);
-static_assert(!C6<char>); // expected-note{{while checking the satisfaction of concept 'C6<char>' requested here}}
-static_assert(C7<char>);
-static_assert(!C7<short>); // expected-note{{while checking the satisfaction of concept 'C7<short>' requested here}}
-
-// Make sure argument list is converted when instantiating a CSE.
-
-template<typename T, typename U = int>
-concept SameSize = sizeof(T) == sizeof(U);
-
-template<typename T>
-struct X { static constexpr bool a = SameSize<T>; };
-
-static_assert(X<unsigned>::a);
diff --git a/test/PCH/cxx2a-concept-specialization-expr.cpp b/test/PCH/cxx2a-concept-specialization-expr.cpp
deleted file mode 100644
index 6227d57..0000000
--- a/test/PCH/cxx2a-concept-specialization-expr.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
-// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
-
-// expected-no-diagnostics
-
-#ifndef HEADER
-#define HEADER
-
-template<typename... T>
-concept C = true;
-
-namespace n {
-  template<typename... T>
-  concept C = true;
-}
-
-void f() {
-  (void)C<int>;
-  (void)C<int, void>;
-  (void)n::C<void>;
-}
-
-#else /*included pch*/
-
-int main() {
-  (void)C<int>;
-  (void)C<int, void>;
-  (void)n::C<void>;
-  f();
-}
-
-#endif // HEADER
diff --git a/test/Parser/cxx2a-concept-declaration.cpp b/test/Parser/cxx2a-concept-declaration.cpp
index 4dcfa3f..d80b3db 100644
--- a/test/Parser/cxx2a-concept-declaration.cpp
+++ b/test/Parser/cxx2a-concept-declaration.cpp
@@ -14,6 +14,8 @@
 // expected-error@-2{{template template parameter requires 'class' after the parameter list}}
 // expected-error@-3{{concept template parameter list must have at least one parameter; explicit specialization of concepts is not allowed}}
 
+template<typename T> concept C2 = 0.f; // expected-error {{constraint expression must be of type 'bool' but is of type 'float'}}
+
 struct S1 {
   template<typename T> concept C1 = true; // expected-error {{concept declarations may only appear in global or namespace scope}}
 };
@@ -24,15 +26,15 @@
 
 template<typename A>
 template<typename B>
-concept C2 = true; // expected-error {{extraneous template parameter list in concept definition}}
+concept C4 = true; // expected-error {{extraneous template parameter list in concept definition}}
 
-template<typename T> concept C3 = true; // expected-note {{previous}} expected-note {{previous}}
-int C3; // expected-error {{redefinition}}
-struct C3 {}; // expected-error {{redefinition}}
+template<typename T> concept C5 = true; // expected-note {{previous}} expected-note {{previous}}
+int C5; // expected-error {{redefinition}}
+struct C5 {}; // expected-error {{redefinition}}
 
-struct C4 {}; // expected-note{{previous definition is here}}
-template<typename T> concept C4 = true;
-// expected-error@-1{{redefinition of 'C4' as different kind of symbol}}
+struct C6 {}; // expected-note{{previous definition is here}}
+template<typename T> concept C6 = true;
+// expected-error@-1{{redefinition of 'C6' as different kind of symbol}}
 
 // TODO: Add test to prevent explicit specialization, partial specialization
 // and explicit instantiation of concepts.
@@ -41,60 +43,31 @@
 struct integral_constant { static constexpr T value = v; };
 
 namespace N {
-  template<typename T> concept C5 = true;
+  template<typename T> concept C7 = true;
 }
-using N::C5;
+using N::C7;
 
-template <bool word> concept C6 = integral_constant<bool, wor>::value;
+template <bool word> concept C8 = integral_constant<bool, wor>::value;
 // expected-error@-1{{use of undeclared identifier 'wor'; did you mean 'word'?}}
 // expected-note@-2{{'word' declared here}}
 
-template<typename T> concept bool C7 = true;
+template<typename T> concept bool C9 = true;
 // expected-warning@-1{{ISO C++2a does not permit the 'bool' keyword after 'concept'}}
 
-template<> concept C8 = false;
+template<> concept C10 = false;
 // expected-error@-1{{concept template parameter list must have at least one parameter; explicit specialization of concepts is not allowed}}
 
-template<> concept C7<int> = false;
+template<> concept C9<int> = false;
 // expected-error@-1{{name defined in concept definition must be an identifier}}
 
-template<typename T> concept N::C9 = false;
+template<typename T> concept N::C11 = false;
 // expected-error@-1{{name defined in concept definition must be an identifier}}
 
 class A { };
 // expected-note@-1{{'A' declared here}}
 
-template<typename T> concept A::C10 = false;
+template<typename T> concept A::C12 = false;
 // expected-error@-1{{expected namespace name}}
 
 template<typename T> concept operator int = false;
 // expected-error@-1{{name defined in concept definition must be an identifier}}
-
-template<bool x> concept C11 = 2; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
-template<bool x> concept C12 = 2 && x; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
-template<bool x> concept C13 = x || 2 || x; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
-template<bool x> concept C14 = 8ull && x || x; // expected-error {{atomic constraint must be of type 'bool' (found 'unsigned long long')}}
-template<typename T> concept C15 = sizeof(T); // expected-error {{atomic constraint must be of type 'bool' (found 'unsigned long')}}
-template<typename T> concept C16 = true && (0 && 0); // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}
-// expected-warning@-1{{use of logical '&&' with constant operand}}
-// expected-note@-2{{use '&' for a bitwise operation}}
-// expected-note@-3{{remove constant to silence this warning}}
-template<typename T> concept C17 = T{};
-static_assert(!C17<bool>);
-template<typename T> concept C18 = (bool&&)true;
-static_assert(C18<int>);
-template<typename T> concept C19 = (const bool&)true;
-static_assert(C19<int>);
-template<typename T> concept C20 = (const bool)true;
-static_assert(C20<int>);
-template <bool c> concept C21 = integral_constant<bool, c>::value && true;
-static_assert(C21<true>);
-static_assert(!C21<false>);
-template <bool c> concept C22 = integral_constant<bool, c>::value;
-static_assert(C22<true>);
-static_assert(!C22<false>);
-
-template <bool word> concept C23 = integral_constant<bool, wor>::value;
-// expected-error@-1{{use of undeclared identifier 'wor'; did you mean 'word'?}}
-// expected-note@-2{{'word' declared here}}
-
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 634b108..93e588e 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -256,7 +256,6 @@
   case Stmt::BinaryConditionalOperatorClass:
   case Stmt::TypeTraitExprClass:
   case Stmt::CoawaitExprClass:
-  case Stmt::ConceptSpecializationExprClass:
   case Stmt::DependentCoawaitExprClass:
   case Stmt::CoyieldExprClass:
   case Stmt::CXXBindTemporaryExprClass: