summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Parse/ParseExpr.cpp4
-rwxr-xr-xclang/lib/Sema/SemaTemplateInstantiateDecl.cpp8
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp5
-rw-r--r--clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp17
4 files changed, 25 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index df8388926db..1eb3ad6afd1 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 92f6e0dc1c9..fbbab8f0070 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 bc093a0fc50..b45b57f6b92 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 00000000000..a2a7232b4b8
--- /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
OpenPOWER on IntegriCloud