Author: Saar Raz
Date: 2020-01-24T02:24:21+02:00
New Revision: 73eaf62463b4a29adf4194685af12d1a5d172987

URL: 
https://github.com/llvm/llvm-project/commit/73eaf62463b4a29adf4194685af12d1a5d172987
DIFF: 
https://github.com/llvm/llvm-project/commit/73eaf62463b4a29adf4194685af12d1a5d172987.diff

LOG: [Concepts] Make constraint expressions unevaluated until satisfaction 
checking

As per P1980R0, constraint expressions are unevaluated operands, and their 
constituent atomic
constraints only become constant evaluated during satisfaction checking.

Change the evaluation context during parsing and instantiation of constraints 
to unevaluated.

Added: 
    clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp

Modified: 
    clang/lib/Parse/ParseExpr.cpp
    clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
    clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index ba7525ecf527..e0c53df992e8 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -234,7 +234,7 @@ ExprResult Parser::ParseCaseExpression(SourceLocation 
CaseLoc) {
 /// \endverbatim
 ExprResult Parser::ParseConstraintExpression() {
   EnterExpressionEvaluationContext ConstantEvaluated(
-      Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+      Actions, Sema::ExpressionEvaluationContext::Unevaluated);
   ExprResult LHS(ParseCastExpression(AnyCastExpr));
   ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
   if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {
@@ -256,7 +256,7 @@ ExprResult Parser::ParseConstraintExpression() {
 ExprResult
 Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
   EnterExpressionEvaluationContext ConstantEvaluated(
-      Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+      Actions, Sema::ExpressionEvaluationContext::Unevaluated);
   bool NotPrimaryExpression = false;
   auto ParsePrimary = [&] () {
     ExprResult E = ParseCastExpression(PrimaryExprOnly,

diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 92f6e0dc1c90..fbbab8f00703 100755
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1849,7 +1849,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
   Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
   if (TrailingRequiresClause) {
     EnterExpressionEvaluationContext ConstantEvaluated(
-        SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+        SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
     ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
                                            TemplateArgs);
     if (SubstRC.isInvalid())
@@ -2189,7 +2189,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
   Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
   if (TrailingRequiresClause) {
     EnterExpressionEvaluationContext ConstantEvaluated(
-        SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+        SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
     ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
                                            TemplateArgs);
     if (SubstRC.isInvalid())
@@ -2529,8 +2529,6 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
     TemplateArgumentListInfo InstArgs;
 
     if (TemplArgInfo) {
-      EnterExpressionEvaluationContext ConstantEvaluated(
-        SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
       InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
       InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
       if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(),
@@ -3736,7 +3734,7 @@ 
TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
   Expr *InstRequiresClause = nullptr;
   if (Expr *E = L->getRequiresClause()) {
     EnterExpressionEvaluationContext ConstantEvaluated(
-        SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+        SemaRef, Sema::ExpressionEvaluationContext::Unevaluated);
     ExprResult Res = SemaRef.SubstExpr(E, TemplateArgs);
     if (Res.isInvalid() || !Res.isUsable()) {
       return nullptr;

diff  --git 
a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp 
b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
index bc093a0fc50e..b45b57f6b924 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
@@ -39,8 +39,9 @@ namespace std_example {
   using dc1 = D_check<short>; // expected-error{{constraints not satisfied for 
class template 'D_check' [with T = short]}}
 
   template<typename T>
-  concept C2 = requires (T a) { // expected-note{{'a' declared here}}
+  concept C2 = requires (T a) {
       requires sizeof(a) == 4; // OK
-      requires a == 0; // expected-error{{constraint variable 'a' cannot be 
used in an evaluated context}}
+      requires a == 0; // expected-note{{because 'a == 0' would be invalid: 
constraint variable 'a' cannot be used in an evaluated context}}
     };
+  static_assert(C2<int>); // expected-note{{because 'int' does not satisfy 
'C2'}} expected-error{{static_assert failed}}
 }
\ No newline at end of file

diff  --git a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp 
b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
new file mode 100644
index 000000000000..a2a7232b4b88
--- /dev/null
+++ b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
@@ -0,0 +1,17 @@
+// RUN:  %clang_cc1 -std=c++2a -verify %s
+
+// Make sure constraint expressions are unevaluated before being substituted
+// into during satisfaction checking.
+
+template<typename T> constexpr int f() { return T::value; }
+template<typename T> concept Foo = false && (f<int>(), true);
+bool k = Foo<int>;
+template<typename T> requires false && (f<int>(), true) struct S {};
+// expected-note@-1{{because}}
+using s = S<int>; // expected-error {{constraints not satisfied}}
+template<typename T> void foo() requires false && (f<int>(), true) { };
+// expected-note@-1{{because}} expected-note@-1{{candidate template ignored}}
+int a = (foo<int>(), 0); // expected-error{{no matching function}}
+template<typename T> void bar() requires requires { requires false && 
(f<int>(), true); } { };
+// expected-note@-1{{because}} expected-note@-1{{candidate template ignored}}
+int b = (bar<int>(), 0); // expected-error{{no matching function}}
\ No newline at end of file


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to