diff options
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 4 | ||||
-rwxr-xr-x | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp | 5 | ||||
-rw-r--r-- | clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp | 17 |
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 |