[Concepts] Concept Specialization Expressions

Part of C++20 Concepts implementation effort. Added Concept Specialization Expressions that are created when a concept is refe$

D41217 on Phabricator.

(recommit after fixing failing Parser test on windows)

llvm-svn: 374903
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 284962f..cb756eb 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4271,14 +4271,47 @@
 
 ExprResult
 Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
-                             const DeclarationNameInfo &NameInfo,
-                             ConceptDecl *Template,
-                             SourceLocation TemplateLoc,
+                             SourceLocation TemplateKWLoc,
+                             SourceLocation ConceptNameLoc,
+                             NamedDecl *FoundDecl,
+                             ConceptDecl *NamedConcept,
                              const TemplateArgumentListInfo *TemplateArgs) {
-  // TODO: Do concept specialization here.
-  Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) <<
-    "concept specialization";
-  return ExprError();
+  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);
 }
 
 ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
@@ -4322,9 +4355,10 @@
   }
 
   if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) {
-    return CheckConceptTemplateId(SS, R.getLookupNameInfo(),
-                                  R.getAsSingle<ConceptDecl>(),
-                                  TemplateKWLoc, TemplateArgs);
+    return CheckConceptTemplateId(SS, TemplateKWLoc,
+                                  R.getLookupNameInfo().getBeginLoc(),
+                                  R.getFoundDecl(),
+                                  R.getAsSingle<ConceptDecl>(), TemplateArgs);
   }
 
   // We don't want lookup warnings at this point.
@@ -8054,20 +8088,7 @@
   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.