<div dir="ltr">Hi,<div>Sorry for the late reply, I was driving.</div><div>Fixed the test and recommitted in r374903</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 15, 2019 at 5:44 PM Nico Weber <<a href="mailto:thakis@chromium.org">thakis@chromium.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Reverted in r374899.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 15, 2019 at 8:58 AM Nico Weber <<a href="mailto:thakis@chromium.org" target="_blank">thakis@chromium.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">The test is failing on Windows. Please take a look, and if it takes a while to fix please revert while you investigate:<div><br></div><div><a href="http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/11533/steps/stage%201%20check/logs/stdio" target="_blank">http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/11533/steps/stage%201%20check/logs/stdio</a><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 15, 2019 at 7:46 AM Saar Raz via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: saar.raz<br>
Date: Tue Oct 15 04:48:58 2019<br>
New Revision: 374882<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=374882&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=374882&view=rev</a><br>
Log:<br>
[Concepts] Concept Specialization Expressions<br>
<br>
Part of C++20 Concepts implementation effort. Added Concept Specialization Expressions that are created when a concept is referenced with arguments, and tests thereof.<br>
<br>
<br>
<br>
Added:<br>
  cfe/trunk/lib/Sema/SemaConcept.cpp<br>
  cfe/trunk/test/CXX/expr/expr.prim/<a href="http://expr.prim.id/" rel="noreferrer" target="_blank">expr.prim.id/</a><br>
  cfe/trunk/test/CXX/expr/expr.prim/<a href="http://expr.prim.id/p3.cpp" rel="noreferrer" target="_blank">expr.prim.id/p3.cpp</a><br>
  cfe/trunk/test/CXX/temp/temp.constr/<br>
  cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/<br>
  cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp<br>
  cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp<br>
Removed:<br>
  cfe/trunk/test/CXX/concepts-ts/<br>
Modified:<br>
  cfe/trunk/include/clang/AST/ExprCXX.h<br>
  cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
  cfe/trunk/include/clang/Basic/StmtNodes.td<br>
  cfe/trunk/include/clang/Sema/Sema.h<br>
  cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
  cfe/trunk/lib/AST/Expr.cpp<br>
  cfe/trunk/lib/AST/ExprCXX.cpp<br>
  cfe/trunk/lib/AST/ExprClassification.cpp<br>
  cfe/trunk/lib/AST/ExprConstant.cpp<br>
  cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
  cfe/trunk/lib/AST/StmtPrinter.cpp<br>
  cfe/trunk/lib/AST/StmtProfile.cpp<br>
  cfe/trunk/lib/CodeGen/CGExprScalar.cpp<br>
  cfe/trunk/lib/Frontend/FrontendActions.cpp<br>
  cfe/trunk/lib/Parse/ParseExpr.cpp<br>
  cfe/trunk/lib/Sema/CMakeLists.txt<br>
  cfe/trunk/lib/Sema/SemaExceptionSpec.cpp<br>
  cfe/trunk/lib/Sema/SemaTemplate.cpp<br>
  cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br>
  cfe/trunk/lib/Sema/TreeTransform.h<br>
  cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
  cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
  cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp<br>
  cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp<br>
  cfe/trunk/tools/libclang/CXCursor.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/ExprCXX.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)<br>
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Oct 15 04:48:58 2019<br>
@@ -17,6 +17,7 @@<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/DeclBase.h"<br>
 #include "clang/AST/DeclCXX.h"<br>
+#include "clang/AST/DeclTemplate.h"<br>
 #include "clang/AST/DeclarationName.h"<br>
 #include "clang/AST/Expr.h"<br>
 #include "clang/AST/NestedNameSpecifier.h"<br>
@@ -56,6 +57,7 @@ class IdentifierInfo;<br>
 class LambdaCapture;<br>
 class NonTypeTemplateParmDecl;<br>
 class TemplateParameterList;<br>
+class Sema;<br>
<br>
 //===--------------------------------------------------------------------===//<br>
 // C++ Expressions.<br>
@@ -4750,6 +4752,125 @@ public:<br>
  }<br>
 };<br>
<br>
+/// \brief Represents the specialization of a concept - evaluates to a prvalue<br>
+/// of type bool.<br>
+///<br>
+/// According to C++2a [<a href="http://expr.prim.id" rel="noreferrer" target="_blank">expr.prim.id</a>]p3 an id-expression that denotes the<br>
+/// specialization of a concept results in a prvalue of type bool.<br>
+class ConceptSpecializationExpr final : public Expr,<br>
+Â Â Â private llvm::TrailingObjects<ConceptSpecializationExpr,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TemplateArgument> {<br>
+Â friend class ASTStmtReader;<br>
+Â friend TrailingObjects;<br>
+<br>
+Â // \brief The optional nested name specifier used when naming the concept.<br>
+Â NestedNameSpecifierLoc NestedNameSpec;<br>
+<br>
+Â /// \brief The location of the template keyword, if specified when naming the<br>
+Â /// concept.<br>
+Â SourceLocation TemplateKWLoc;<br>
+<br>
+Â /// \brief The location of the concept name in the expression.<br>
+Â SourceLocation ConceptNameLoc;<br>
+<br>
+Â /// \brief The declaration found by name lookup when the expression was<br>
+Â /// created.<br>
+Â /// Can differ from NamedConcept when, for example, the concept was found<br>
+Â /// through a UsingShadowDecl.<br>
+Â NamedDecl *FoundDecl;<br>
+<br>
+Â /// \brief The concept named, and whether or not the concept with the given<br>
+Â /// arguments was satisfied when the expression was created.<br>
+Â /// If any of the template arguments are dependent (this expr would then be<br>
+Â /// isValueDependent()), this bit is to be ignored.<br>
+Â llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept;<br>
+<br>
+Â /// \brief The template argument list source info used to specialize the<br>
+Â /// concept.<br>
+Â const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;<br>
+<br>
+Â /// \brief The number of template arguments in the tail-allocated list of<br>
+Â /// converted template arguments.<br>
+Â unsigned NumTemplateArgs;<br>
+<br>
+Â ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptDecl *NamedConcept,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â const ASTTemplateArgumentListInfo *ArgsAsWritten,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â ArrayRef<TemplateArgument> ConvertedArgs,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Optional<bool> IsSatisfied);<br>
+<br>
+Â ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);<br>
+<br>
+public:<br>
+<br>
+Â static ConceptSpecializationExpr *<br>
+Â Create(ASTContext &C, NestedNameSpecifierLoc NNS,<br>
+Â Â Â Â Â SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,<br>
+Â Â Â Â Â NamedDecl *FoundDecl, ConceptDecl *NamedConcept,<br>
+Â Â Â Â Â const ASTTemplateArgumentListInfo *ArgsAsWritten,<br>
+Â Â Â Â Â ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied);<br>
+<br>
+Â static ConceptSpecializationExpr *<br>
+Â Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);<br>
+<br>
+Â const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {<br>
+Â Â return NestedNameSpec;<br>
+Â }<br>
+<br>
+Â NamedDecl *getFoundDecl() const {<br>
+Â Â return FoundDecl;<br>
+Â }<br>
+<br>
+Â ConceptDecl *getNamedConcept() const {<br>
+Â Â return NamedConcept.getPointer();<br>
+Â }<br>
+<br>
+Â ArrayRef<TemplateArgument> getTemplateArguments() const {<br>
+Â Â return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NumTemplateArgs);<br>
+Â }<br>
+<br>
+Â const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {<br>
+Â Â return ArgsAsWritten;<br>
+Â }<br>
+<br>
+Â /// \brief Set new template arguments for this concept specialization.<br>
+Â void setTemplateArguments(const ASTTemplateArgumentListInfo *ArgsAsWritten,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â ArrayRef<TemplateArgument> Converted);<br>
+<br>
+Â /// \brief Whether or not the concept with the given arguments was satisfied<br>
+Â /// when the expression was created. This method assumes that the expression<br>
+Â /// is not dependent!<br>
+Â bool isSatisfied() const {<br>
+Â Â assert(!isValueDependent()<br>
+Â Â Â Â Â Â && "isSatisfied called on a dependent ConceptSpecializationExpr");<br>
+Â Â return NamedConcept.getInt();<br>
+Â }<br>
+<br>
+Â SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }<br>
+<br>
+Â SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }<br>
+<br>
+Â static bool classof(const Stmt *T) {<br>
+Â Â return T->getStmtClass() == ConceptSpecializationExprClass;<br>
+Â }<br>
+<br>
+Â SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; }<br>
+Â SourceLocation getEndLoc() const LLVM_READONLY {<br>
+Â Â return ArgsAsWritten->RAngleLoc;<br>
+Â }<br>
+<br>
+Â // Iterators<br>
+Â child_range children() {<br>
+Â Â return child_range(child_iterator(), child_iterator());<br>
+Â }<br>
+Â const_child_range children() const {<br>
+Â Â return const_child_range(const_child_iterator(), const_child_iterator());<br>
+Â }<br>
+};<br>
+<br>
 } // namespace clang<br>
<br>
 #endif // LLVM_CLANG_AST_EXPRCXX_H<br>
<br>
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Oct 15 04:48:58 2019<br>
@@ -2659,6 +2659,12 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {<br>
  }<br>
 })<br>
<br>
+DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {<br>
+Â TRY_TO(TraverseTemplateArgumentLocsHelper(<br>
+Â Â Â Â Â S->getTemplateArgsAsWritten()->getTemplateArgs(),<br>
+Â Â Â Â Â S->getTemplateArgsAsWritten()->NumTemplateArgs));<br>
+})<br>
+<br>
 // These literals (all of them) do not need any action.<br>
 DEF_TRAVERSE_STMT(IntegerLiteral, {})<br>
 DEF_TRAVERSE_STMT(FixedPointLiteral, {})<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct 15 04:48:58 2019<br>
@@ -2526,8 +2526,6 @@ def note_private_extern : Note<<br>
  "use __attribute__((visibility(\"hidden\"))) attribute instead">;<br>
<br>
 // C++ Concepts<br>
-def err_concept_initialized_with_non_bool_type : Error<<br>
-Â "constraint expression must be of type 'bool' but is of type %0">;<br>
 def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<<br>
  "concept declarations may only appear in global or namespace scope">;<br>
 def err_concept_no_parameters : Error<<br>
@@ -2539,6 +2537,11 @@ def err_concept_no_associated_constraint<br>
  "concept cannot have associated constraints">;<br>
 def err_concept_not_implemented : Error<<br>
  "sorry, unimplemented concepts feature %0 used">;<br>
+def err_non_constant_constraint_expression : Error<<br>
+Â "substitution into constraint expression resulted in a non-constant "<br>
+Â "expression">;<br>
+def err_non_bool_atomic_constraint : Error<<br>
+Â "atomic constraint must be of type 'bool' (found %0)">;<br>
<br>
 def err_template_different_associated_constraints : Error<<br>
  "associated constraints differ in template redeclaration">;<br>
@@ -4496,6 +4499,10 @@ def note_prior_template_arg_substitution<br>
  " template parameter%1 %2">;<br>
 def note_template_default_arg_checking : Note<<br>
  "while checking a default template argument used here">;<br>
+def note_concept_specialization_here : Note<<br>
+Â "while checking the satisfaction of concept '%0' requested here">;<br>
+def note_constraint_substitution_here : Note<<br>
+Â "while substituting template arguments into constraint expression here">;<br>
 def note_instantiation_contexts_suppressed : Note<<br>
  "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "<br>
  "see all)">;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/StmtNodes.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)<br>
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Oct 15 04:48:58 2019<br>
@@ -163,6 +163,9 @@ def CoawaitExpr : DStmt<CoroutineSuspend<br>
 def DependentCoawaitExpr : DStmt<Expr>;<br>
 def CoyieldExpr : DStmt<CoroutineSuspendExpr>;<br>
<br>
+// C++2a Concepts expressions<br>
+def ConceptSpecializationExpr : DStmt<Expr>;<br>
+<br>
 // Obj-C Expressions.<br>
 def ObjCStringLiteral : DStmt<Expr>;<br>
 def ObjCBoxedExpr : DStmt<Expr>;<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 15 04:48:58 2019<br>
@@ -6047,7 +6047,16 @@ public:<br>
                      CXXConversionDecl *Conv,<br>
                      Expr *Src);<br>
<br>
-Â // ParseObjCStringLiteral - Parse Objective-C string literals.<br>
+Â /// Check whether the given expression is a valid constraint expression.<br>
+Â /// A diagnostic is emitted if it is not, and false is returned.<br>
+Â bool CheckConstraintExpression(Expr *CE);<br>
+<br>
+Â bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â MultiLevelTemplateArgumentList &MLTAL,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Expr *ConstraintExpr,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool &IsSatisfied);<br>
+<br>
+Â Â // ParseObjCStringLiteral - Parse Objective-C string literals.<br>
  ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,<br>
                   ArrayRef<Expr *> Strings);<br>
<br>
@@ -6718,9 +6727,9 @@ public:<br>
<br>
  ExprResult<br>
  CheckConceptTemplateId(const CXXScopeSpec &SS,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â const DeclarationNameInfo &NameInfo,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptDecl *Template,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation TemplateLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptDecl *NamedConcept,<br>
             const TemplateArgumentListInfo *TemplateArgs);<br>
<br>
  void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);<br>
@@ -7639,6 +7648,15 @@ public:<br>
    /// member).<br>
    DefiningSynthesizedFunction,<br>
<br>
+Â Â Â // We are checking the constraints associated with a constrained entity or<br>
+Â Â Â // the constraint expression of a concept. This includes the checks that<br>
+Â Â Â // atomic constraints have the type 'bool' and that they can be constant<br>
+Â Â Â // evaluated.<br>
+Â Â Â ConstraintsCheck,<br>
+<br>
+Â Â Â // We are substituting template arguments into a constraint expression.<br>
+Â Â Â ConstraintSubstitution,<br>
+<br>
    /// Added for Template instantiation observation.<br>
    /// Memoization means we are _not_ instantiating a template because<br>
    /// it is already instantiated (but we entered a context where we<br>
@@ -7899,6 +7917,23 @@ public:<br>
              ArrayRef<TemplateArgument> TemplateArgs,<br>
              SourceRange InstantiationRange);<br>
<br>
+Â Â struct ConstraintsCheck {};<br>
+Â Â /// \brief Note that we are checking the constraints associated with some<br>
+Â Â /// constrained entity (a concept declaration or a template with associated<br>
+Â Â /// constraints).<br>
+Â Â InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â ConstraintsCheck, TemplateDecl *Template,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â ArrayRef<TemplateArgument> TemplateArgs,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â SourceRange InstantiationRange);<br>
+<br>
+Â Â struct ConstraintSubstitution {};<br>
+Â Â /// \brief Note that we are checking a constraint expression associated<br>
+Â Â /// with a template declaration or as part of the satisfaction check of a<br>
+Â Â /// concept.<br>
+Â Â InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â ConstraintSubstitution, TemplateDecl *Template,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â sema::TemplateDeductionInfo &DeductionInfo,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â SourceRange InstantiationRange);<br>
<br>
   /// Note that we have finished instantiating this template.<br>
   void Clear();<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Oct 15 04:48:58 2019<br>
@@ -1912,6 +1912,7 @@ namespace serialization {<br>
    EXPR_FUNCTION_PARM_PACK,  // FunctionParmPackExpr<br>
    EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr<br>
    EXPR_CXX_FOLD,       // CXXFoldExpr<br>
+Â Â Â EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr<br>
<br>
    // CUDA<br>
    EXPR_CUDA_KERNEL_CALL,    // CUDAKernelCallExpr<br>
<br>
Modified: cfe/trunk/lib/AST/Expr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Expr.cpp (original)<br>
+++ cfe/trunk/lib/AST/Expr.cpp Tue Oct 15 04:48:58 2019<br>
@@ -3403,6 +3403,7 @@ bool Expr::HasSideEffects(const ASTConte<br>
  case CXXUuidofExprClass:<br>
  case OpaqueValueExprClass:<br>
  case SourceLocExprClass:<br>
+Â case ConceptSpecializationExprClass:<br>
   // These never have a side-effect.<br>
   return false;<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Oct 15 04:48:58 2019<br>
@@ -28,6 +28,9 @@<br>
 #include "clang/Basic/OperatorKinds.h"<br>
 #include "clang/Basic/SourceLocation.h"<br>
 #include "clang/Basic/Specifiers.h"<br>
+#include "clang/Sema/Template.h"<br>
+#include "clang/Sema/SemaDiagnostic.h"<br>
+#include "clang/Sema/Sema.h"<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/Support/Casting.h"<br>
 #include "llvm/Support/ErrorHandling.h"<br>
@@ -1680,3 +1683,82 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::<br>
              alignof(CUDAKernelCallExpr));<br>
  return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);<br>
 }<br>
+<br>
+ConceptSpecializationExpr::ConceptSpecializationExpr(ASTContext &C,<br>
+Â Â NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,<br>
+Â Â SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,<br>
+Â Â ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,<br>
+Â Â ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool> IsSatisfied)<br>
+Â Â : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,<br>
+Â Â Â Â Â Â /*TypeDependent=*/false,<br>
+Â Â Â Â Â Â // All the flags below are set in setTemplateArguments.<br>
+Â Â Â Â Â Â /*ValueDependent=*/!IsSatisfied.hasValue(),<br>
+Â Â Â Â Â Â /*InstantiationDependent=*/false,<br>
+Â Â Â Â Â Â /*ContainsUnexpandedParameterPacks=*/false),<br>
+Â Â Â NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),<br>
+Â Â Â ConceptNameLoc(ConceptNameLoc), FoundDecl(FoundDecl),<br>
+Â Â Â NamedConcept(NamedConcept, IsSatisfied ? *IsSatisfied : true),<br>
+Â Â Â NumTemplateArgs(ConvertedArgs.size()) {<br>
+<br>
+Â setTemplateArguments(ArgsAsWritten, ConvertedArgs);<br>
+}<br>
+<br>
+ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,<br>
+Â Â unsigned NumTemplateArgs)<br>
+Â Â : Expr(ConceptSpecializationExprClass, Empty),<br>
+Â Â Â NumTemplateArgs(NumTemplateArgs) { }<br>
+<br>
+void ConceptSpecializationExpr::setTemplateArguments(<br>
+Â Â const ASTTemplateArgumentListInfo *ArgsAsWritten,<br>
+Â Â ArrayRef<TemplateArgument> Converted) {<br>
+Â assert(Converted.size() == NumTemplateArgs);<br>
+Â assert(!this->ArgsAsWritten && "setTemplateArguments can only be used once");<br>
+Â this->ArgsAsWritten = ArgsAsWritten;<br>
+Â std::uninitialized_copy(Converted.begin(), Converted.end(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â getTrailingObjects<TemplateArgument>());<br>
+Â bool IsInstantiationDependent = false;<br>
+Â bool ContainsUnexpandedParameterPack = false;<br>
+Â for (const TemplateArgumentLoc& LocInfo : ArgsAsWritten->arguments()) {<br>
+Â Â if (LocInfo.getArgument().isInstantiationDependent())<br>
+Â Â Â IsInstantiationDependent = true;<br>
+Â Â if (LocInfo.getArgument().containsUnexpandedParameterPack())<br>
+Â Â Â ContainsUnexpandedParameterPack = true;<br>
+Â Â if (ContainsUnexpandedParameterPack && IsInstantiationDependent)<br>
+Â Â Â break;<br>
+Â }<br>
+<br>
+Â // Currently guaranteed by the fact concepts can only be at namespace-scope.<br>
+Â assert(!NestedNameSpec ||<br>
+Â Â Â Â Â (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&<br>
+Â Â Â Â Â !NestedNameSpec.getNestedNameSpecifier()<br>
+Â Â Â Â Â Â Â ->containsUnexpandedParameterPack()));<br>
+Â setInstantiationDependent(IsInstantiationDependent);<br>
+Â setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);<br>
+Â assert((!isValueDependent() || isInstantiationDependent()) &&<br>
+Â Â Â Â Â "should not be value-dependent");<br>
+}<br>
+<br>
+ConceptSpecializationExpr *<br>
+ConceptSpecializationExpr::Create(ASTContext &C, NestedNameSpecifierLoc NNS,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation ConceptNameLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NamedDecl *FoundDecl,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptDecl *NamedConcept,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const ASTTemplateArgumentListInfo *ArgsAsWritten,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ArrayRef<TemplateArgument> ConvertedArgs,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Optional<bool> IsSatisfied) {<br>
+Â void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConvertedArgs.size()));<br>
+Â return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptNameLoc, FoundDecl,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NamedConcept, ArgsAsWritten,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConvertedArgs, IsSatisfied);<br>
+}<br>
+<br>
+ConceptSpecializationExpr *<br>
+ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned NumTemplateArgs) {<br>
+Â void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NumTemplateArgs));<br>
+Â return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);<br>
+}<br>
\ No newline at end of file<br>
<br>
Modified: cfe/trunk/lib/AST/ExprClassification.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Oct 15 04:48:58 2019<br>
@@ -192,6 +192,7 @@ static Cl::Kinds ClassifyInternal(ASTCon<br>
  case Expr::NoInitExprClass:<br>
  case Expr::DesignatedInitUpdateExprClass:<br>
  case Expr::SourceLocExprClass:<br>
+Â case Expr::ConceptSpecializationExprClass:<br>
   return Cl::CL_PRValue;<br>
<br>
  case Expr::ConstantExprClass:<br>
<br>
Modified: cfe/trunk/lib/AST/ExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Oct 15 04:48:58 2019<br>
@@ -9768,6 +9768,7 @@ public:<br>
  bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);<br>
  bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);<br>
  bool VisitSourceLocExpr(const SourceLocExpr *E);<br>
+Â bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);<br>
  // FIXME: Missing: array subscript of vector, member of vector<br>
 };<br>
<br>
@@ -12250,6 +12251,12 @@ bool IntExprEvaluator::VisitCXXNoexceptE<br>
  return Success(E->getValue(), E);<br>
 }<br>
<br>
+bool IntExprEvaluator::VisitConceptSpecializationExpr(<br>
+Â Â Â Â const ConceptSpecializationExpr *E) {<br>
+Â return Success(E->isSatisfied(), E);<br>
+}<br>
+<br>
+<br>
 bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {<br>
  switch (E->getOpcode()) {<br>
   default:<br>
@@ -13923,6 +13930,7 @@ static ICEDiag CheckICE(const Expr* E, c<br>
  case Expr::CXXBoolLiteralExprClass:<br>
  case Expr::CXXScalarValueInitExprClass:<br>
  case Expr::TypeTraitExprClass:<br>
+Â case Expr::ConceptSpecializationExprClass:<br>
  case Expr::ArrayTypeTraitExprClass:<br>
  case Expr::ExpressionTraitExprClass:<br>
  case Expr::CXXNoexceptExprClass:<br>
<br>
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)<br>
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Oct 15 04:48:58 2019<br>
@@ -3658,6 +3658,7 @@ recurse:<br>
  case Expr::ConvertVectorExprClass:<br>
  case Expr::StmtExprClass:<br>
  case Expr::TypeTraitExprClass:<br>
+Â case Expr::ConceptSpecializationExprClass:<br>
  case Expr::ArrayTypeTraitExprClass:<br>
  case Expr::ExpressionTraitExprClass:<br>
  case Expr::VAArgExprClass:<br>
<br>
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Oct 15 04:48:58 2019<br>
@@ -2231,6 +2231,17 @@ void StmtPrinter::VisitCXXFoldExpr(CXXFo<br>
  OS << ")";<br>
 }<br>
<br>
+void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {<br>
+Â NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();<br>
+Â if (NNS)<br>
+Â Â NNS.getNestedNameSpecifier()->print(OS, Policy);<br>
+Â if (E->getTemplateKWLoc().isValid())<br>
+Â Â OS << "template ";<br>
+Â OS << E->getFoundDecl()->getName();<br>
+Â printTemplateArgumentList(OS, E->getTemplateArgsAsWritten()->arguments(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Policy);<br>
+}<br>
+<br>
 // C++ Coroutines TS<br>
<br>
 void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {<br>
<br>
Modified: cfe/trunk/lib/AST/StmtProfile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)<br>
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Oct 15 04:48:58 2019<br>
@@ -1309,6 +1309,14 @@ void StmtProfiler::VisitAtomicExpr(const<br>
  ID.AddInteger(S->getOp());<br>
 }<br>
<br>
+void StmtProfiler::VisitConceptSpecializationExpr(<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const ConceptSpecializationExpr *S) {<br>
+Â VisitExpr(S);<br>
+Â VisitDecl(S->getFoundDecl());<br>
+Â VisitTemplateArguments(S->getTemplateArgsAsWritten()->getTemplateArgs(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â S->getTemplateArgsAsWritten()->NumTemplateArgs);<br>
+}<br>
+<br>
 static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,<br>
                      UnaryOperatorKind &UnaryOp,<br>
                      BinaryOperatorKind &BinaryOp) {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Oct 15 04:48:58 2019<br>
@@ -673,6 +673,10 @@ public:<br>
   return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());<br>
  }<br>
<br>
+Â Value *VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {<br>
+Â Â return Builder.getInt1(E->isSatisfied());<br>
+Â }<br>
+<br>
  Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {<br>
   return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue());<br>
  }<br>
<br>
Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Tue Oct 15 04:48:58 2019<br>
@@ -417,6 +417,10 @@ private:<br>
    return "DefiningSynthesizedFunction";<br>
   case CodeSynthesisContext::Memoization:<br>
    return "Memoization";<br>
+Â Â case CodeSynthesisContext::ConstraintsCheck:<br>
+Â Â Â return "ConstraintsCheck";<br>
+Â Â case CodeSynthesisContext::ConstraintSubstitution:<br>
+Â Â Â return "ConstraintSubstitution";<br>
   }<br>
   return "";<br>
  }<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Oct 15 04:48:58 2019<br>
@@ -228,18 +228,16 @@ ExprResult Parser::ParseCaseExpression(S<br>
 /// Parse a constraint-expression.<br>
 ///<br>
 /// \verbatim<br>
-///Â Â Â Â constraint-expression: [Concepts TS temp.constr.decl p1]<br>
+///Â Â Â Â constraint-expression: C++2a[temp.constr.decl]p1<br>
 ///     logical-or-expression<br>
 /// \endverbatim<br>
 ExprResult Parser::ParseConstraintExpression() {<br>
-Â // FIXME: this may erroneously consume a function-body as the braced<br>
-Â // initializer list of a compound literal<br>
-Â //<br>
-Â // FIXME: this may erroneously consume a parenthesized rvalue reference<br>
-Â // declarator as a parenthesized address-of-label expression<br>
+Â EnterExpressionEvaluationContext ConstantEvaluated(<br>
+Â Â Â Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);<br>
  ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false));<br>
  ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));<br>
-<br>
+Â if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get()))<br>
+Â Â return ExprError();<br>
  return Res;<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)<br>
+++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Oct 15 04:48:58 2019<br>
@@ -32,6 +32,7 @@ add_clang_library(clangSema<br>
  SemaCast.cpp<br>
  SemaChecking.cpp<br>
  SemaCodeComplete.cpp<br>
+Â SemaConcept.cpp<br>
  SemaConsumer.cpp<br>
  SemaCoroutine.cpp<br>
  SemaCUDA.cpp<br>
<br>
Added: cfe/trunk/lib/Sema/SemaConcept.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaConcept.cpp?rev=374882&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaConcept.cpp?rev=374882&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaConcept.cpp (added)<br>
+++ cfe/trunk/lib/Sema/SemaConcept.cpp Tue Oct 15 04:48:58 2019<br>
@@ -0,0 +1,125 @@<br>
+//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//<br>
+//<br>
+//Â Â Â Â Â Â Â Â Â Â Â The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+//Â This file implements semantic analysis for C++ constraints and concepts.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "clang/Sema/Sema.h"<br>
+#include "clang/Sema/SemaDiagnostic.h"<br>
+#include "clang/Sema/TemplateDeduction.h"<br>
+#include "clang/Sema/Template.h"<br>
+#include "clang/AST/ExprCXX.h"<br>
+using namespace clang;<br>
+using namespace sema;<br>
+<br>
+bool Sema::CheckConstraintExpression(Expr *ConstraintExpression) {<br>
+Â // C++2a [temp.constr.atomic]p1<br>
+Â // ..E shall be a constant expression of type bool.<br>
+<br>
+Â ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();<br>
+<br>
+Â if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {<br>
+Â Â if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)<br>
+Â Â Â return CheckConstraintExpression(BinOp->getLHS()) &&<br>
+Â Â Â Â Â Â Â CheckConstraintExpression(BinOp->getRHS());<br>
+Â } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))<br>
+Â Â return CheckConstraintExpression(C->getSubExpr());<br>
+<br>
+Â // An atomic constraint!<br>
+Â if (ConstraintExpression->isTypeDependent())<br>
+Â Â return true;<br>
+<br>
+Â QualType Type = ConstraintExpression->getType();<br>
+Â if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {<br>
+Â Â Diag(ConstraintExpression->getExprLoc(),<br>
+Â Â Â Â Â diag::err_non_bool_atomic_constraint) << Type<br>
+Â Â Â Â << ConstraintExpression->getSourceRange();<br>
+Â Â return false;<br>
+Â }<br>
+Â return true;<br>
+}<br>
+<br>
+bool<br>
+Sema::CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â MultiLevelTemplateArgumentList &MLTAL,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Expr *ConstraintExpr,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool &IsSatisfied) {<br>
+Â ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();<br>
+<br>
+Â if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {<br>
+Â Â if (BO->getOpcode() == BO_LAnd) {<br>
+Â Â Â if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IsSatisfied))<br>
+Â Â Â Â return true;<br>
+Â Â Â if (!IsSatisfied)<br>
+Â Â Â Â return false;<br>
+Â Â Â return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IsSatisfied);<br>
+Â Â } else if (BO->getOpcode() == BO_LOr) {<br>
+Â Â Â if (CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getLHS(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IsSatisfied))<br>
+Â Â Â Â return true;<br>
+Â Â Â if (IsSatisfied)<br>
+Â Â Â Â return false;<br>
+Â Â Â return CalculateConstraintSatisfaction(NamedConcept, MLTAL, BO->getRHS(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IsSatisfied);<br>
+Â Â }<br>
+Â }<br>
+Â else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))<br>
+Â Â return CalculateConstraintSatisfaction(NamedConcept, MLTAL, C->getSubExpr(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IsSatisfied);<br>
+<br>
+Â EnterExpressionEvaluationContext ConstantEvaluated(<br>
+Â Â Â *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);<br>
+<br>
+Â // Atomic constraint - substitute arguments and check satisfaction.<br>
+Â ExprResult E;<br>
+Â {<br>
+Â Â TemplateDeductionInfo Info(ConstraintExpr->getBeginLoc());<br>
+Â Â InstantiatingTemplate Inst(*this, ConstraintExpr->getBeginLoc(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â InstantiatingTemplate::ConstraintSubstitution{},<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NamedConcept, Info,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConstraintExpr->getSourceRange());<br>
+Â Â if (Inst.isInvalid())<br>
+Â Â Â return true;<br>
+Â Â // We do not want error diagnostics escaping here.<br>
+Â Â Sema::SFINAETrap Trap(*this);<br>
+<br>
+Â Â E = SubstExpr(ConstraintExpr, MLTAL);<br>
+Â Â if (E.isInvalid() || Trap.hasErrorOccurred()) {<br>
+Â Â Â // C++2a [temp.constr.atomic]p1<br>
+Â Â Â //Â Â ...If substitution results in an invalid type or expression, the<br>
+Â Â Â //Â Â constraint is not satisfied.<br>
+Â Â Â IsSatisfied = false;<br>
+Â Â Â return false;<br>
+Â Â }<br>
+Â }<br>
+<br>
+Â if (!CheckConstraintExpression(E.get()))<br>
+Â Â return true;<br>
+<br>
+Â SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;<br>
+Â Expr::EvalResult EvalResult;<br>
+Â EvalResult.Diag = &EvaluationDiags;<br>
+Â if (!E.get()->EvaluateAsRValue(EvalResult, Context)) {<br>
+Â Â // C++2a [temp.constr.atomic]p1<br>
+Â Â //Â Â ...E shall be a constant expression of type bool.<br>
+Â Â Diag(E.get()->getBeginLoc(),<br>
+Â Â Â Â Â diag::err_non_constant_constraint_expression)<br>
+Â Â Â Â << E.get()->getSourceRange();<br>
+Â Â for (const PartialDiagnosticAt &PDiag : EvaluationDiags)<br>
+Â Â Â Diag(PDiag.first, PDiag.second);<br>
+Â Â return true;<br>
+Â }<br>
+<br>
+Â IsSatisfied = EvalResult.Val.getInt().getBoolValue();<br>
+<br>
+Â return false;<br>
+}<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Oct 15 04:48:58 2019<br>
@@ -1314,6 +1314,7 @@ CanThrowResult Sema::canThrow(const Expr<br>
  case Expr::SizeOfPackExprClass:<br>
  case Expr::StringLiteralClass:<br>
  case Expr::SourceLocExprClass:<br>
+Â case Expr::ConceptSpecializationExprClass:<br>
   // These expressions can never throw.<br>
   return CT_Cannot;<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Oct 15 04:48:58 2019<br>
@@ -4271,14 +4271,47 @@ void Sema::diagnoseMissingTemplateArgume<br>
<br>
 ExprResult<br>
 Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const DeclarationNameInfo &NameInfo,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptDecl *Template,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation TemplateLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SourceLocation ConceptNameLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NamedDecl *FoundDecl,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptDecl *NamedConcept,<br>
               const TemplateArgumentListInfo *TemplateArgs) {<br>
-Â // TODO: Do concept specialization here.<br>
-Â Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) <<<br>
-Â Â "concept specialization";<br>
-Â return ExprError();<br>
+Â assert(NamedConcept && "A concept template id without a template?");<br>
+<br>
+Â llvm::SmallVector<TemplateArgument, 4> Converted;<br>
+Â if (CheckTemplateArgumentList(NamedConcept, ConceptNameLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â const_cast<TemplateArgumentListInfo&>(*TemplateArgs),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /*PartialTemplateArgs=*/false, Converted,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /*UpdateArgsWithConversion=*/false))<br>
+Â Â return ExprError();<br>
+<br>
+Â Optional<bool> IsSatisfied;<br>
+Â bool AreArgsDependent = false;<br>
+Â for (TemplateArgument &Arg : Converted) {<br>
+Â Â if (Arg.isDependent()) {<br>
+Â Â Â AreArgsDependent = true;<br>
+Â Â Â break;<br>
+Â Â }<br>
+Â }<br>
+Â if (!AreArgsDependent) {<br>
+Â Â InstantiatingTemplate Inst(*this, ConceptNameLoc,<br>
+Â Â Â Â InstantiatingTemplate::ConstraintsCheck{}, NamedConcept, Converted,<br>
+Â Â Â Â SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameLoc,<br>
+Â Â Â Â Â Â Â Â Â Â TemplateArgs->getRAngleLoc()));<br>
+Â Â MultiLevelTemplateArgumentList MLTAL;<br>
+Â Â MLTAL.addOuterTemplateArguments(Converted);<br>
+Â Â bool Satisfied;<br>
+Â Â if (CalculateConstraintSatisfaction(NamedConcept, MLTAL,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NamedConcept->getConstraintExpr(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Satisfied))<br>
+Â Â Â return ExprError();<br>
+Â Â IsSatisfied = Satisfied;<br>
+Â }<br>
+Â return ConceptSpecializationExpr::Create(Context,<br>
+Â Â Â SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},<br>
+Â Â Â TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept,<br>
+Â Â Â ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), Converted,<br>
+Â Â Â IsSatisfied);<br>
 }<br>
<br>
 ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,<br>
@@ -4322,9 +4355,10 @@ ExprResult Sema::BuildTemplateIdExpr(con<br>
  }<br>
<br>
  if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) {<br>
-Â Â return CheckConceptTemplateId(SS, R.getLookupNameInfo(),<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â R.getAsSingle<ConceptDecl>(),<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TemplateKWLoc, TemplateArgs);<br>
+Â Â return CheckConceptTemplateId(SS, TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â R.getLookupNameInfo().getBeginLoc(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â R.getFoundDecl(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â R.getAsSingle<ConceptDecl>(), TemplateArgs);<br>
  }<br>
<br>
  // We don't want lookup warnings at this point.<br>
@@ -8054,20 +8088,7 @@ Decl *Sema::ActOnConceptDefinition(Scope<br>
  ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name,<br>
                       TemplateParameterLists.front(),<br>
                       ConstraintExpr);<br>
-<br>
-Â if (!ConstraintExpr->isTypeDependent() &&<br>
-Â Â Â ConstraintExpr->getType() != Context.BoolTy) {<br>
-Â Â // C++2a [temp.constr.atomic]p3:<br>
-Â Â // E shall be a constant expression of type bool.<br>
-Â Â // TODO: Do this check for individual atomic constraints<br>
-Â Â // and not the constraint expression. Probably should do it in<br>
-Â Â // ParseConstraintExpression.<br>
-Â Â Diag(ConstraintExpr->getSourceRange().getBegin(),<br>
-Â Â Â Â diag::err_concept_initialized_with_non_bool_type)<br>
-Â Â Â << ConstraintExpr->getType();<br>
-Â Â NewDecl->setInvalidDecl();<br>
-Â }<br>
-<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <br>
  if (NewDecl->getAssociatedConstraints()) {<br>
   // C++2a [temp.concept]p4:<br>
   // A concept shall not have associated constraints.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Oct 15 04:48:58 2019<br>
@@ -198,12 +198,14 @@ bool Sema::CodeSynthesisContext::isInsta<br>
  case ExplicitTemplateArgumentSubstitution:<br>
  case DeducedTemplateArgumentSubstitution:<br>
  case PriorTemplateArgumentSubstitution:<br>
+Â case ConstraintsCheck:<br>
   return true;<br>
<br>
  case DefaultTemplateArgumentChecking:<br>
  case DeclaringSpecialMember:<br>
  case DefiningSynthesizedFunction:<br>
  case ExceptionSpecEvaluation:<br>
+Â case ConstraintSubstitution:<br>
   return false;<br>
<br>
  // This function should never be called when Kind's value is Memoization.<br>
@@ -358,6 +360,24 @@ Sema::InstantiatingTemplate::Instantiati<br>
      PointOfInstantiation, InstantiationRange, Param, Template,<br>
      TemplateArgs) {}<br>
<br>
+Sema::InstantiatingTemplate::InstantiatingTemplate(<br>
+Â Â Sema &SemaRef, SourceLocation PointOfInstantiation,<br>
+Â Â ConstraintsCheck, TemplateDecl *Template,<br>
+Â Â ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)<br>
+Â Â : InstantiatingTemplate(<br>
+Â Â Â Â Â SemaRef, CodeSynthesisContext::ConstraintsCheck,<br>
+Â Â Â Â Â PointOfInstantiation, InstantiationRange, Template, nullptr,<br>
+Â Â Â Â Â TemplateArgs) {}<br>
+<br>
+Sema::InstantiatingTemplate::InstantiatingTemplate(<br>
+Â Â Sema &SemaRef, SourceLocation PointOfInstantiation,<br>
+Â Â ConstraintSubstitution, TemplateDecl *Template,<br>
+Â Â sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)<br>
+Â Â : InstantiatingTemplate(<br>
+Â Â Â Â Â SemaRef, CodeSynthesisContext::ConstraintSubstitution,<br>
+Â Â Â Â Â PointOfInstantiation, InstantiationRange, Template, nullptr,<br>
+Â Â Â Â Â {}, &DeductionInfo) {}<br>
+<br>
 void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {<br>
  Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;<br>
  InNonInstantiationSFINAEContext = false;<br>
@@ -664,6 +684,30 @@ void Sema::PrintInstantiationStack() {<br>
<br>
   case CodeSynthesisContext::Memoization:<br>
    break;<br>
+Â Â <br>
+Â Â case CodeSynthesisContext::ConstraintsCheck:<br>
+Â Â Â if (auto *CD = dyn_cast<ConceptDecl>(Active->Entity)) {<br>
+Â Â Â Â SmallVector<char, 128> TemplateArgsStr;<br>
+Â Â Â Â llvm::raw_svector_ostream OS(TemplateArgsStr);<br>
+Â Â Â Â CD->printName(OS);<br>
+Â Â Â Â printTemplateArgumentList(OS, Active->template_arguments(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â getPrintingPolicy());<br>
+Â Â Â Â Diags.Report(Active->PointOfInstantiation,<br>
+Â Â Â Â Â Â Â Â Â Â Â diag::note_concept_specialization_here)<br>
+Â Â Â Â Â << OS.str()<br>
+Â Â Â Â Â << Active->InstantiationRange;<br>
+Â Â Â Â break;<br>
+Â Â Â }<br>
+Â Â Â // TODO: Concepts - implement this for constrained templates and partial<br>
+Â Â Â // specializations.<br>
+Â Â Â llvm_unreachable("only concept constraints are supported right now");<br>
+Â Â Â break;<br>
+Â Â Â <br>
+Â Â case CodeSynthesisContext::ConstraintSubstitution:<br>
+Â Â Â Diags.Report(Active->PointOfInstantiation,<br>
+Â Â Â Â Â Â Â Â Â Â diag::note_constraint_substitution_here)<br>
+Â Â Â Â Â << Active->InstantiationRange;<br>
+Â Â Â break;<br>
   }<br>
  }<br>
 }<br>
@@ -687,6 +731,7 @@ Optional<TemplateDeductionInfo *> Sema::<br>
    LLVM_FALLTHROUGH;<br>
   case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:<br>
   case CodeSynthesisContext::ExceptionSpecInstantiation:<br>
+Â Â case CodeSynthesisContext::ConstraintsCheck:<br>
    // This is a template instantiation, so there is no SFINAE.<br>
    return None;<br>
<br>
@@ -700,8 +745,10 @@ Optional<TemplateDeductionInfo *> Sema::<br>
<br>
   case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:<br>
   case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:<br>
-Â Â Â // We're either substitution explicitly-specified template arguments<br>
-Â Â Â // or deduced template arguments, so SFINAE applies.<br>
+Â Â case CodeSynthesisContext::ConstraintSubstitution:<br>
+Â Â Â // We're either substituting explicitly-specified template arguments<br>
+Â Â Â // or deduced template arguments or a constraint expression, so SFINAE<br>
+Â Â Â // applies.<br>
    assert(Active->DeductionInfo && "Missing deduction info pointer");<br>
    return Active->DeductionInfo;<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 15 04:48:58 2019<br>
@@ -3019,6 +3019,25 @@ public:<br>
  ///<br>
  /// By default, performs semantic analysis to build the new expression.<br>
  /// Subclasses may override this routine to provide different behavior.<br>
+Â ExprResult RebuildConceptSpecializationExpr(NestedNameSpecifierLoc NNS,<br>
+Â Â Â SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,<br>
+Â Â Â NamedDecl *FoundDecl, ConceptDecl *NamedConcept,<br>
+Â Â Â TemplateArgumentListInfo *TALI) {<br>
+Â Â CXXScopeSpec SS;<br>
+Â Â SS.Adopt(NNS);<br>
+Â Â ExprResult Result = getSema().CheckConceptTemplateId(SS, TemplateKWLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptNameLoc,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â FoundDecl,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NamedConcept, TALI);<br>
+Â Â if (Result.isInvalid())<br>
+Â Â Â return ExprError();<br>
+Â Â return Result;<br>
+Â }<br>
+<br>
+Â Â /// \brief Build a new Objective-C boxed expression.<br>
+Â ///<br>
+Â /// By default, performs semantic analysis to build the new expression.<br>
+Â /// Subclasses may override this routine to provide different behavior.<br>
  ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {<br>
   return getSema().BuildObjCBoxedExpr(SR, ValueExpr);<br>
  }<br>
@@ -11016,6 +11035,23 @@ TreeTransform<Derived>::TransformTypeTra<br>
<br>
 template<typename Derived><br>
 ExprResult<br>
+TreeTransform<Derived>::TransformConceptSpecializationExpr(<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ConceptSpecializationExpr *E) {<br>
+Â const ASTTemplateArgumentListInfo *Old = E->getTemplateArgsAsWritten();<br>
+Â TemplateArgumentListInfo TransArgs(Old->LAngleLoc, Old->RAngleLoc);<br>
+Â if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Old->NumTemplateArgs, TransArgs))<br>
+Â Â return ExprError();<br>
+<br>
+Â return getDerived().RebuildConceptSpecializationExpr(<br>
+Â Â Â E->getNestedNameSpecifierLoc(), E->getTemplateKWLoc(),<br>
+Â Â Â E->getConceptNameLoc(), E->getFoundDecl(), E->getNamedConcept(),<br>
+Â Â Â &TransArgs);<br>
+}<br>
+<br>
+<br>
+template<typename Derived><br>
+ExprResult<br>
 TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {<br>
  TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo());<br>
  if (!T)<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Oct 15 04:48:58 2019<br>
@@ -734,6 +734,24 @@ void ASTStmtReader::VisitUnaryExprOrType<br>
  E->setRParenLoc(ReadSourceLocation());<br>
 }<br>
<br>
+void ASTStmtReader::VisitConceptSpecializationExpr(<br>
+Â Â Â Â ConceptSpecializationExpr *E) {<br>
+Â VisitExpr(E);<br>
+Â unsigned NumTemplateArgs = Record.readInt();<br>
+Â E->NestedNameSpec = Record.readNestedNameSpecifierLoc();<br>
+Â E->TemplateKWLoc = Record.readSourceLocation();<br>
+Â E->ConceptNameLoc = Record.readSourceLocation();<br>
+Â E->FoundDecl = ReadDeclAs<NamedDecl>();<br>
+Â E->NamedConcept.setPointer(ReadDeclAs<ConceptDecl>());<br>
+Â const ASTTemplateArgumentListInfo *ArgsAsWritten =<br>
+Â Â Â Record.readASTTemplateArgumentListInfo();<br>
+Â llvm::SmallVector<TemplateArgument, 4> Args;<br>
+Â for (unsigned I = 0; I < NumTemplateArgs; ++I)<br>
+Â Â Args.push_back(Record.readTemplateArgument());<br>
+Â E->setTemplateArguments(ArgsAsWritten, Args);<br>
+Â E->NamedConcept.setInt(Record.readInt() == 1);<br>
+}<br>
+<br>
 void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {<br>
  VisitExpr(E);<br>
  E->setLHS(Record.readSubExpr());<br>
@@ -3490,6 +3508,12 @@ Stmt *ASTReader::ReadStmtFromStream(Modu<br>
   case EXPR_DEPENDENT_COAWAIT:<br>
    S = new (Context) DependentCoawaitExpr(Empty);<br>
    break;<br>
+<br>
+Â Â case EXPR_CONCEPT_SPECIALIZATION:<br>
+Â Â Â unsigned numTemplateArgs = Record[ASTStmtReader::NumExprFields];<br>
+Â Â Â S = ConceptSpecializationExpr::Create(Context, Empty, numTemplateArgs);<br>
+Â Â Â break;<br>
+Â Â Â <br>
   }<br>
<br>
   // We hit a STMT_STOP, so we're done with this expression.<br>
<br>
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Oct 15 04:48:58 2019<br>
@@ -388,6 +388,24 @@ void ASTStmtWriter::VisitDependentCoawai<br>
  Code = serialization::EXPR_DEPENDENT_COAWAIT;<br>
 }<br>
<br>
+void ASTStmtWriter::VisitConceptSpecializationExpr(<br>
+Â Â Â Â ConceptSpecializationExpr *E) {<br>
+Â VisitExpr(E);<br>
+Â ArrayRef<TemplateArgument> TemplateArgs = E->getTemplateArguments();<br>
+Â Record.push_back(TemplateArgs.size());<br>
+Â Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc());<br>
+Â Record.AddSourceLocation(E->getTemplateKWLoc());<br>
+Â Record.AddSourceLocation(E->getConceptNameLoc());<br>
+Â Record.AddDeclRef(E->getFoundDecl());<br>
+Â Record.AddDeclRef(E->getNamedConcept());<br>
+Â Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten());<br>
+Â for (const TemplateArgument &Arg : TemplateArgs)<br>
+Â Â Record.AddTemplateArgument(Arg);<br>
+Â Record.push_back(E->isSatisfied());<br>
+Â Code = serialization::EXPR_CONCEPT_SPECIALIZATION;<br>
+}<br>
+<br>
+<br>
 void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) {<br>
  VisitStmt(S);<br>
  // NumCaptures<br>
<br>
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Oct 15 04:48:58 2019<br>
@@ -1370,6 +1370,7 @@ void ExprEngine::Visit(const Stmt *S, Ex<br>
   case Stmt::CUDAKernelCallExprClass:<br>
   case Stmt::OpaqueValueExprClass:<br>
   case Stmt::AsTypeExprClass:<br>
+Â Â case Stmt::ConceptSpecializationExprClass:<br>
    // Fall through.<br>
<br>
   // Cases we intentionally don't evaluate, since they don't need<br>
<br>
Added: cfe/trunk/test/CXX/expr/expr.prim/<a href="http://expr.prim.id/p3.cpp" rel="noreferrer" target="_blank">expr.prim.id/p3.cpp</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp?rev=374882&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp?rev=374882&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/expr/expr.prim/<a href="http://expr.prim.id/p3.cpp" rel="noreferrer" target="_blank">expr.prim.id/p3.cpp</a> (added)<br>
+++ cfe/trunk/test/CXX/expr/expr.prim/<a href="http://expr.prim.id/p3.cpp" rel="noreferrer" target="_blank">expr.prim.id/p3.cpp</a> Tue Oct 15 04:48:58 2019<br>
@@ -0,0 +1,149 @@<br>
+// RUN:Â %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s<br>
+<br>
+template<typename T> concept C1 = true; // expected-note{{template is declared here}}<br>
+static_assert(C1<int>);<br>
+static_assert(C1);<br>
+// expected-error@-1{{use of concept 'C1' requires template arguments}}<br>
+<br>
+template<typename T> concept C2 = sizeof(T) == 4;<br>
+static_assert(C2<int>);<br>
+static_assert(!C2<long long int>);<br>
+static_assert(C2<char[4]>);<br>
+static_assert(!C2<char[5]>);<br>
+<br>
+template<typename T> concept C3 = sizeof(*T{}) == 4;<br>
+static_assert(C3<int*>);<br>
+static_assert(!C3<long long int>);<br>
+<br>
+struct A {<br>
+Â static constexpr int add(int a, int b) {<br>
+Â Â return a + b;<br>
+Â }<br>
+};<br>
+struct B {<br>
+Â static int add(int a, int b) { // expected-note{{declared here}}<br>
+Â Â return a + b;<br>
+Â }<br>
+};<br>
+template<typename U><br>
+concept C4 = U::add(1, 2) == 3;<br>
+// expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}}<br>
+// expected-note@-2{{non-constexpr function 'add' cannot be used in a constant expression}}<br>
+static_assert(C4<A>);<br>
+static_assert(!C4<B>); // expected-note {{while checking the satisfaction of concept 'C4<B>' requested here}}<br>
+<br>
+template<typename T, typename U><br>
+constexpr bool is_same_v = false;<br>
+<br>
+template<typename T><br>
+constexpr bool is_same_v<T, T> = true;<br>
+<br>
+template<typename T, typename U><br>
+concept Same = is_same_v<T, U>;<br>
+<br>
+static_assert(Same<int, int>);<br>
+static_assert(Same<int, decltype(1)>);<br>
+static_assert(!Same<int, unsigned int>);<br>
+static_assert(!Same<A, B>);<br>
+static_assert(Same<A, A>);<br>
+<br>
+static_assert(Same<bool, decltype(C1<int>)>);<br>
+static_assert(Same<bool, decltype(C2<int>)>);<br>
+static_assert(Same<bool, decltype(C3<int*>)>);<br>
+static_assert(Same<bool, decltype(C4<A>)>);<br>
+<br>
+template<typename T> concept C5 = T{}; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}<br>
+constexpr bool x = C5<int>; // expected-note {{while checking the satisfaction of concept 'C5<int>' requested here}}<br>
+<br>
+template<int x><br>
+concept IsEven = (x % 2) == 0;<br>
+<br>
+static_assert(IsEven<20>);<br>
+static_assert(!IsEven<11>);<br>
+<br>
+template<template<typename T> typename P><br>
+concept IsTypePredicate = is_same_v<decltype(P<bool>::value), const bool><br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â && is_same_v<decltype(P<int>::value), const bool><br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â && is_same_v<decltype(P<long long>::value), const bool>;<br>
+<br>
+template<typename T> struct T1 {};<br>
+template<typename T> struct T2 { static constexpr bool value = sizeof(T) == 2; };<br>
+<br>
+static_assert(IsTypePredicate<T2>);<br>
+static_assert(!IsTypePredicate<T1>);<br>
+<br>
+namespace piecewise_substitution {<br>
+Â template <typename T><br>
+Â concept True = true;<br>
+<br>
+Â template <typename T><br>
+Â concept A = True<T> || T::value;<br>
+<br>
+Â template <typename T><br>
+Â concept B = (True<T> || T::value);<br>
+<br>
+Â template <typename T><br>
+Â concept C = !True<T> && T::value || true;<br>
+<br>
+Â template <typename T><br>
+Â concept D = (!True<T> && T::value) || true;<br>
+<br>
+Â template <typename T><br>
+Â concept E = T::value || True<T>;<br>
+<br>
+Â template <typename T><br>
+Â concept F = (T::value || True<T>);<br>
+<br>
+Â template <typename T><br>
+Â concept G = T::value && !True<T> || true;<br>
+<br>
+Â template <typename T><br>
+Â concept H = (T::value && !True<T>) || true;<br>
+<br>
+Â template <typename T><br>
+Â concept I = T::value;<br>
+<br>
+Â static_assert(A<int>);<br>
+Â static_assert(B<int>);<br>
+Â static_assert(C<int>);<br>
+Â static_assert(D<int>);<br>
+Â static_assert(E<int>);<br>
+Â static_assert(F<int>);<br>
+Â static_assert(G<int>);<br>
+Â static_assert(H<int>);<br>
+Â static_assert(!I<int>);<br>
+}<br>
+<br>
+// Short ciruiting<br>
+<br>
+template<typename T> struct T3 { using type = typename T::type; };<br>
+// expected-error@-1{{type 'char' cannot be used prior to '::' because it has no members}}<br>
+// expected-error@-2{{type 'short' cannot be used prior to '::' because it has no members}}<br>
+<br>
+template<typename T><br>
+concept C6 = sizeof(T) == 1 && sizeof(typename T3<T>::type) == 1;<br>
+// expected-note@-1{{while substituting template arguments into constraint expression here}}<br>
+// expected-note@-2{{in instantiation of template class 'T3<char>' requested here}}<br>
+<br>
+template<typename T><br>
+concept C7 = sizeof(T) == 1 || sizeof(<br>
+// expected-note@-1{{while substituting template arguments into constraint expression here}}<br>
+Â Â typename<br>
+Â Â Â T3<T><br>
+// expected-note@-1{{in instantiation of template class 'T3<short>' requested here}}<br>
+Â Â Â Â ::type) == 1;<br>
+<br>
+static_assert(!C6<short>);<br>
+static_assert(!C6<char>); // expected-note{{while checking the satisfaction of concept 'C6<char>' requested here}}<br>
+static_assert(C7<char>);<br>
+static_assert(!C7<short>); // expected-note{{while checking the satisfaction of concept 'C7<short>' requested here}}<br>
+<br>
+// Make sure argument list is converted when instantiating a CSE.<br>
+<br>
+template<typename T, typename U = int><br>
+concept SameSize = sizeof(T) == sizeof(U);<br>
+<br>
+template<typename T><br>
+struct X { static constexpr bool a = SameSize<T>; };<br>
+<br>
+static_assert(X<unsigned>::a);<br>
<br>
Added: cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp?rev=374882&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp?rev=374882&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp (added)<br>
+++ cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp Tue Oct 15 04:48:58 2019<br>
@@ -0,0 +1,65 @@<br>
+// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s<br>
+<br>
+namespace nodiag {<br>
+<br>
+template <typename T> requires bool(T())<br>
+struct A;<br>
+template <typename U> requires bool(U())<br>
+struct A;<br>
+<br>
+} // end namespace nodiag<br>
+<br>
+namespace diag {<br>
+<br>
+template <typename T> requires true // expected-note{{previous template declaration is here}}<br>
+struct A;<br>
+template <typename T> struct A; // expected-error{{associated constraints differ in template redeclaration}}<br>
+<br>
+template <typename T> struct B; // expected-note{{previous template declaration is here}}<br>
+template <typename T> requires true // expected-error{{associated constraints differ in template redeclaration}}<br>
+struct B;<br>
+<br>
+template <typename T> requires true // expected-note{{previous template declaration is here}}<br>
+struct C;<br>
+template <typename T> requires !0 // expected-error{{associated constraints differ in template redeclaration}}<br>
+struct C;<br>
+<br>
+} // end namespace diag<br>
+<br>
+namespace nodiag {<br>
+<br>
+struct AA {<br>
+Â template <typename T> requires someFunc(T())<br>
+Â struct A;<br>
+};<br>
+<br>
+template <typename T> requires someFunc(T())<br>
+struct AA::A { };<br>
+<br>
+struct AAF {<br>
+Â template <typename T> requires someFunc(T())<br>
+Â friend struct AA::A;<br>
+};<br>
+<br>
+} // end namespace nodiag<br>
+<br>
+namespace diag {<br>
+<br>
+template <unsigned N><br>
+struct TA {<br>
+Â template <template <unsigned> class TT> requires TT<N>::happy // expected-note 2{{previous template declaration is here}}<br>
+Â struct A;<br>
+<br>
+Â struct AF;<br>
+};<br>
+<br>
+template <unsigned N><br>
+template <template <unsigned> class TT> struct TA<N>::A { }; // expected-error{{associated constraints differ in template redeclaration}}<br>
+<br>
+template <unsigned N><br>
+struct TA<N>::AF {<br>
+Â template <template <unsigned> class TT> requires TT<N + 0>::happy // expected-error{{associated constraints differ in template redeclaration}}<br>
+Â friend struct TA::A;<br>
+};<br>
+<br>
+} // end namespace diag<br>
<br>
Added: cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp?rev=374882&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp?rev=374882&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp (added)<br>
+++ cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp Tue Oct 15 04:48:58 2019<br>
@@ -0,0 +1,32 @@<br>
+// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t<br>
+// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s<br>
+<br>
+// expected-no-diagnostics<br>
+<br>
+#ifndef HEADER<br>
+#define HEADER<br>
+<br>
+template<typename... T><br>
+concept C = true;<br>
+<br>
+namespace n {<br>
+Â template<typename... T><br>
+Â concept C = true;<br>
+}<br>
+<br>
+void f() {<br>
+Â (void)C<int>;<br>
+Â (void)C<int, void>;<br>
+Â (void)n::C<void>;<br>
+}<br>
+<br>
+#else /*included pch*/<br>
+<br>
+int main() {<br>
+Â (void)C<int>;<br>
+Â (void)C<int, void>;<br>
+Â (void)n::C<void>;<br>
+Â f();<br>
+}<br>
+<br>
+#endif // HEADER<br>
<br>
Modified: cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp Tue Oct 15 04:48:58 2019<br>
@@ -14,8 +14,6 @@ template<template<typename> concept T> c<br>
 // expected-error@-2{{template template parameter requires 'class' after the parameter list}}<br>
 // expected-error@-3{{concept template parameter list must have at least one parameter; explicit specialization of concepts is not allowed}}<br>
<br>
-template<typename T> concept C2 = 0.f; // expected-error {{constraint expression must be of type 'bool' but is of type 'float'}}<br>
-<br>
 struct S1 {<br>
  template<typename T> concept C1 = true; // expected-error {{concept declarations may only appear in global or namespace scope}}<br>
 };<br>
@@ -26,15 +24,15 @@ extern "C++" {<br>
<br>
 template<typename A><br>
 template<typename B><br>
-concept C4 = true; // expected-error {{extraneous template parameter list in concept definition}}<br>
+concept C2 = true; // expected-error {{extraneous template parameter list in concept definition}}<br>
<br>
-template<typename T> concept C5 = true; // expected-note {{previous}} expected-note {{previous}}<br>
-int C5; // expected-error {{redefinition}}<br>
-struct C5 {}; // expected-error {{redefinition}}<br>
-<br>
-struct C6 {}; // expected-note{{previous definition is here}}<br>
-template<typename T> concept C6 = true;<br>
-// expected-error@-1{{redefinition of 'C6' as different kind of symbol}}<br>
+template<typename T> concept C3 = true; // expected-note {{previous}} expected-note {{previous}}<br>
+int C3; // expected-error {{redefinition}}<br>
+struct C3 {}; // expected-error {{redefinition}}<br>
+<br>
+struct C4 {}; // expected-note{{previous definition is here}}<br>
+template<typename T> concept C4 = true;<br>
+// expected-error@-1{{redefinition of 'C4' as different kind of symbol}}<br>
<br>
 // TODO: Add test to prevent explicit specialization, partial specialization<br>
 // and explicit instantiation of concepts.<br>
@@ -43,31 +41,60 @@ template<typename T, T v><br>
 struct integral_constant { static constexpr T value = v; };<br>
<br>
 namespace N {<br>
-Â template<typename T> concept C7 = true;<br>
+Â template<typename T> concept C5 = true;<br>
 }<br>
-using N::C7;<br>
+using N::C5;<br>
<br>
-template <bool word> concept C8 = integral_constant<bool, wor>::value;<br>
+template <bool word> concept C6 = integral_constant<bool, wor>::value;<br>
 // expected-error@-1{{use of undeclared identifier 'wor'; did you mean 'word'?}}<br>
 // expected-note@-2{{'word' declared here}}<br>
<br>
-template<typename T> concept bool C9 = true;<br>
+template<typename T> concept bool C7 = true;<br>
 // expected-warning@-1{{ISO C++2a does not permit the 'bool' keyword after 'concept'}}<br>
<br>
-template<> concept C10 = false;<br>
+template<> concept C8 = false;<br>
 // expected-error@-1{{concept template parameter list must have at least one parameter; explicit specialization of concepts is not allowed}}<br>
<br>
-template<> concept C9<int> = false;<br>
+template<> concept C7<int> = false;<br>
 // expected-error@-1{{name defined in concept definition must be an identifier}}<br>
<br>
-template<typename T> concept N::C11 = false;<br>
+template<typename T> concept N::C9 = false;<br>
 // expected-error@-1{{name defined in concept definition must be an identifier}}<br>
<br>
 class A { };<br>
 // expected-note@-1{{'A' declared here}}<br>
<br>
-template<typename T> concept A::C12 = false;<br>
+template<typename T> concept A::C10 = false;<br>
 // expected-error@-1{{expected namespace name}}<br>
<br>
 template<typename T> concept operator int = false;<br>
 // expected-error@-1{{name defined in concept definition must be an identifier}}<br>
+<br>
+template<bool x> concept C11 = 2; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}<br>
+template<bool x> concept C12 = 2 && x; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}<br>
+template<bool x> concept C13 = x || 2 || x; // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}<br>
+template<bool x> concept C14 = 8ull && x || x; // expected-error {{atomic constraint must be of type 'bool' (found 'unsigned long long')}}<br>
+template<typename T> concept C15 = sizeof(T); // expected-error {{atomic constraint must be of type 'bool' (found 'unsigned long')}}<br>
+template<typename T> concept C16 = true && (0 && 0); // expected-error {{atomic constraint must be of type 'bool' (found 'int')}}<br>
+// expected-warning@-1{{use of logical '&&' with constant operand}}<br>
+// expected-note@-2{{use '&' for a bitwise operation}}<br>
+// expected-note@-3{{remove constant to silence this warning}}<br>
+template<typename T> concept C17 = T{};<br>
+static_assert(!C17<bool>);<br>
+template<typename T> concept C18 = (bool&&)true;<br>
+static_assert(C18<int>);<br>
+template<typename T> concept C19 = (const bool&)true;<br>
+static_assert(C19<int>);<br>
+template<typename T> concept C20 = (const bool)true;<br>
+static_assert(C20<int>);<br>
+template <bool c> concept C21 = integral_constant<bool, c>::value && true;<br>
+static_assert(C21<true>);<br>
+static_assert(!C21<false>);<br>
+template <bool c> concept C22 = integral_constant<bool, c>::value;<br>
+static_assert(C22<true>);<br>
+static_assert(!C22<false>);<br>
+<br>
+template <bool word> concept C23 = integral_constant<bool, wor>::value;<br>
+// expected-error@-1{{use of undeclared identifier 'wor'; did you mean 'word'?}}<br>
+// expected-note@-2{{'word' declared here}}<br>
+<br>
<br>
Modified: cfe/trunk/tools/libclang/CXCursor.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=374882&r1=374881&r2=374882&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=374882&r1=374881&r2=374882&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Oct 15 04:48:58 2019<br>
@@ -256,6 +256,7 @@ CXCursor cxcursor::MakeCXCursor(const St<br>
  case Stmt::BinaryConditionalOperatorClass:<br>
  case Stmt::TypeTraitExprClass:<br>
  case Stmt::CoawaitExprClass:<br>
+Â case Stmt::ConceptSpecializationExprClass:<br>
  case Stmt::DependentCoawaitExprClass:<br>
  case Stmt::CoyieldExprClass:<br>
  case Stmt::CXXBindTemporaryExprClass:<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>
</blockquote></div>
</blockquote></div>