From 1253b4d5bc406f75bd741e3977fb815a7fea9bdb Mon Sep 17 00:00:00 2001 From: asutton Date: Tue, 19 May 2015 12:59:54 +0000 Subject: [PATCH] 2015-05-19 Andrew Sutton Stop template processing during constraint satisfication. * gcc/cp/constraint.cc (satisfy_constraint): Rename to satisfy_constraint_1 and assert that we are not processing template declarations. (satisfy_*_constraint): Use satisfy_constraint_1. (satisfy_constraint): Turn off template processing. * gcc/testsuite/g++.dg/concepts/fn10.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/c++-concepts@223364 138bc75d-0d04-0410-961f-82ee72b054a4 --- ChangeLog.concepts | 10 ++++++++ gcc/cp/constraint.cc | 35 ++++++++++++++------------ gcc/testsuite/g++.dg/concepts/fn10.C | 49 ++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/concepts/fn10.C diff --git a/ChangeLog.concepts b/ChangeLog.concepts index 85d462bd35a..6ed176b3fa0 100644 --- a/ChangeLog.concepts +++ b/ChangeLog.concepts @@ -1,5 +1,15 @@ 2015-05-19 Andrew Sutton + Stop template processing during constraint satisfication. + * gcc/cp/constraint.cc (satisfy_constraint): Rename to + satisfy_constraint_1 and assert that we are not processing + template declarations. + (satisfy_*_constraint): Use satisfy_constraint_1. + (satisfy_constraint): Turn off template processing. + * gcc/testsuite/g++.dg/concepts/fn10.C: New. + +2015-05-19 Andrew Sutton + Handle naked non-type template arguments as constraints. * gcc/cp/constraint.cc (xform_misc): Removed. (transform_expr): All misc tree classes are atomic constraints. diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index e35c436a3d0..574764f6f7c 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1688,7 +1688,7 @@ tsubst_constraint_info (tree t, tree args, namespace { -tree satisfy_constraint (tree, tree, tsubst_flags_t, tree); +tree satisfy_constraint_1 (tree, tree, tsubst_flags_t, tree); /* Check the pack expansion by first transforming it into a conjunction of constraints. */ @@ -1728,7 +1728,7 @@ satisfy_pack_expansion (tree t, tree args, tree constr = transform_expression (expr); result = conjoin_constraints (result, constr); } - return satisfy_constraint (result, args, complain, in_decl); + return satisfy_constraint_1 (result, args, complain, in_decl); } /* A predicate constraint is satisfied if its expression evaluates @@ -1832,11 +1832,8 @@ satisfy_implicit_conversion_constraint (tree t, tree args, /* Don't tsubst as if we're processing a template. If we try to we can end up generating template-like expressions (e.g., modop-exprs) that aren't properly typed. */ - int saved_template_decl = processing_template_decl; - processing_template_decl = 0; tree expr = tsubst_expr (ICONV_CONSTR_EXPR (t), args, complain, in_decl, false); - processing_template_decl = saved_template_decl; if (expr == error_mark_node) return boolean_false_node; @@ -1908,7 +1905,7 @@ satisfy_parameterized_constraint (tree t, tree args, if (vars == error_mark_node) return boolean_false_node; tree constr = PARM_CONSTR_OPERAND (t); - return satisfy_constraint (constr, args, complain, in_decl); + return satisfy_constraint_1 (constr, args, complain, in_decl); } /* Check that the conjunction of constraints is satisfied. Note @@ -1923,10 +1920,10 @@ satisfy_parameterized_constraint (tree t, tree args, tree satisfy_conjunction (tree t, tree args, tsubst_flags_t complain, tree in_decl) { - tree t0 = satisfy_constraint (TREE_OPERAND (t, 0), args, complain, in_decl); + tree t0 = satisfy_constraint_1 (TREE_OPERAND (t, 0), args, complain, in_decl); if (t0 == boolean_false_node) return t0; - tree t1 = satisfy_constraint (TREE_OPERAND (t, 1), args, complain, in_decl); + tree t1 = satisfy_constraint_1 (TREE_OPERAND (t, 1), args, complain, in_decl); if (t1 == boolean_false_node) return t1; return boolean_true_node; @@ -1939,22 +1936,23 @@ satisfy_conjunction (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree satisfy_disjunction (tree t, tree args, tsubst_flags_t complain, tree in_decl) { - tree t0 = satisfy_constraint (TREE_OPERAND (t, 0), args, complain, in_decl); + tree t0 = satisfy_constraint_1 (TREE_OPERAND (t, 0), args, complain, in_decl); if (t0 == boolean_true_node) return boolean_true_node; - tree t1 = satisfy_constraint (TREE_OPERAND (t, 1), args, complain, in_decl); + tree t1 = satisfy_constraint_1 (TREE_OPERAND (t, 1), args, complain, in_decl); if (t1 == boolean_true_node) return boolean_true_node; return boolean_false_node; } -/* Check that the constraint is satisfied, according to the rules - for that constraint. Note that each satisfy_* function returns - true or false, depending on whether it is satisfied or not. */ +/* Dispatch to an appropriate satisfaction routine depending on the + tree code of T. */ tree -satisfy_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) +satisfy_constraint_1 (tree t, tree args, tsubst_flags_t complain, tree in_decl) { + gcc_assert (!processing_template_decl); + if (!t) return boolean_false_node; @@ -1996,12 +1994,17 @@ satisfy_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) return boolean_false_node; } -/* Same as above but will not emit diagnostics. */ +/* Check that the constraint is satisfied, according to the rules + for that constraint. Note that each satisfy_* function returns + true or false, depending on whether it is satisfied or not. */ tree satisfy_constraint (tree t, tree args) { - return satisfy_constraint (t, args, tf_none, NULL_TREE); + /* Turn off template processing. Constraint satisfaction only applies + to non-dependent terms, so we want full checking here. */ + processing_template_decl_sentinel sentinel (true); + return satisfy_constraint_1 (t, args, tf_none, NULL_TREE); } /* Check the associated constraints in CI against the given diff --git a/gcc/testsuite/g++.dg/concepts/fn10.C b/gcc/testsuite/g++.dg/concepts/fn10.C new file mode 100644 index 00000000000..55eca34a0b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/fn10.C @@ -0,0 +1,49 @@ +// { dg-do compile } +// { dg-options "-std=c++1z" } + +// Test that constraint satisfaction checks work even when +// processing template declarations. + +namespace std +{ + struct ostream { }; + ostream cout; +} + +template + concept bool Float() + { + return __is_same_as( T, float ); + } + +template + constexpr decltype(auto) project( T t ) + { + return t; + } + +template + concept bool Concept() + { + return requires( T t ) { + requires Float(); + }; + } + +template + constexpr decltype(auto) operator<<( E&& e, F&& f ) {} + +template + void foo( T t ) + { + // Try to resolve operator<< from within a template context but + // with non-dependent arguments. We need to ensure that template + // processing is turned off whenever checking for satisfaction. + std::cout << "OK"; // { dg-error "no match" } + } + +int main() +{ + foo( 12.5f ); + return 0; +} -- 2.11.4.GIT