From f32d78f99ac4a860e45856bdc98917a24f470a4e Mon Sep 17 00:00:00 2001 From: asutton Date: Mon, 20 Apr 2015 13:43:31 +0000 Subject: [PATCH] 2015-04-20 Andrew Sutton PR65681 * gcc/cp/constraint.cc (tsubst_simple_requirement): Substitute in a template-processing context to avoid doing full resolution on types and expressions. (tsubst_type_requirement): Likewise. (tsubst_compound_requirement): Likewise. (tsubst_nested_requirement): Likewise. * gcc/testsuite/g++.dg/concepts/p465681.C: New. * gcc/testsuite/g++.dg/concepts/req2.C: Remove check for spurious diagnostics. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/c++-concepts@222236 138bc75d-0d04-0410-961f-82ee72b054a4 --- ChangeLog.concepts | 13 ++++ gcc/cp/constraint.cc | 9 ++- gcc/testsuite/g++.dg/concepts/pr65681.C | 106 ++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/concepts/req2.C | 1 - 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/concepts/pr65681.C diff --git a/ChangeLog.concepts b/ChangeLog.concepts index e5189128d85..4c1ec8fb026 100644 --- a/ChangeLog.concepts +++ b/ChangeLog.concepts @@ -1,5 +1,18 @@ 2015-04-20 Andrew Sutton + PR65681 + * gcc/cp/constraint.cc (tsubst_simple_requirement): Substitute + in a template-processing context to avoid doing full resolution + on types and expressions. + (tsubst_type_requirement): Likewise. + (tsubst_compound_requirement): Likewise. + (tsubst_nested_requirement): Likewise. + * gcc/testsuite/g++.dg/concepts/p465681.C: New. + * gcc/testsuite/g++.dg/concepts/req2.C: Remove check for spurious + diagnostics. + +2015-04-20 Andrew Sutton + Improve pretty printing output for constraints * gcc/cp/error.c (dump_expr): Print predicate constraints just like other constraints. diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 0fd0b9133ec..d370e7a7e6b 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1390,7 +1390,9 @@ inline tree tsubst_simple_requirement (tree t, tree args, tsubst_flags_t complain, tree in_decl) { + ++processing_template_decl; tree expr = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl, false); + --processing_template_decl; return finish_simple_requirement (expr); } @@ -1402,7 +1404,9 @@ inline tree tsubst_type_requirement (tree t, tree args, tsubst_flags_t complain, tree in_decl) { + ++processing_template_decl; tree type = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl); + --processing_template_decl; return finish_type_requirement (type); } @@ -1415,8 +1419,10 @@ tree tsubst_compound_requirement (tree t, tree args, tsubst_flags_t complain, tree in_decl) { + ++processing_template_decl; tree expr = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl, false); tree type = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl); + --processing_template_decl; bool noexcept_p = COMPOUND_REQ_NOEXCEPT_P (t); return finish_compound_requirement (expr, type, noexcept_p); } @@ -1426,7 +1432,9 @@ tree tsubst_nested_requirement (tree t, tree args, tsubst_flags_t complain, tree in_decl) { + ++processing_template_decl; tree expr = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl, false); + --processing_template_decl; return finish_nested_requirement (expr); } @@ -1614,7 +1622,6 @@ check_predicate_constraint (tree t, tree args, return cxx_constant_value (result); } - /* Check an expression constraint. The constraint is satisfied if substitution succeeds ([temp.constr.expr]). diff --git a/gcc/testsuite/g++.dg/concepts/pr65681.C b/gcc/testsuite/g++.dg/concepts/pr65681.C new file mode 100644 index 00000000000..12e0771c2d8 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr65681.C @@ -0,0 +1,106 @@ +// { dg-options "-std=c++1z" } + +template +concept bool C() +{ + return requires (T t) { t.mf(); }; +} + +template +concept bool CA1() +{ + return C(); +} + +template +concept bool CA2() +{ + return CA1() && requires () { typename T::ca2_type; }; +} + +template +concept bool CA3() +{ + return CA2() && requires () { typename T::ca3_type; }; +} + +template +concept bool CB1() +{ + return requires () { typename T::cb1_type; }; +} + +template +concept bool CB2() +{ + return CB1() && requires () { typename T::cb2_type; }; +} + +template +concept bool CB3() +{ + return CB2() && requires () { typename T::cb3_type; }; +} + + +struct MC { void mf(); }; +static_assert(C(), ""); + + +struct MA1 { using ca1_type = MC; }; +struct MA2 : MA1 { using ca2_type = int; }; +struct MA3 : MA2 { using ca3_type = int; }; +static_assert(CA1(), ""); +static_assert(CA2(), ""); +static_assert(CA3(), ""); + +struct MB1 { using cb1_type = int; }; +struct MB2 : MB1 { using cb2_type = int; }; +struct MB3 : MB2 { using cb3_type = int; }; +static_assert(CB1(), ""); +static_assert(CB2(), ""); +static_assert(CB3(), ""); + + +template +struct S; + +template +struct S // Specialization #1 +{ + static constexpr int value = 1; +}; + +template + requires !CA2() +struct S // Specialization #2 +{ + static constexpr int value = 2; +}; + +template + requires !CA3() +struct S // Specialization #3 +{ + static constexpr int value = 3; +}; + +S s11; +S s12; +S s13; +S s21; +S s22; +S s23; +S s31; +S s32; +S s33; + +static_assert(S::value == 1, ""); +static_assert(S::value == 2, ""); +static_assert(S::value == 2, ""); +static_assert(S::value == 1, ""); +static_assert(S::value == 1, ""); +static_assert(S::value == 3, ""); +static_assert(S::value == 1, ""); +static_assert(S::value == 1, ""); +static_assert(S::value == 1, ""); diff --git a/gcc/testsuite/g++.dg/concepts/req2.C b/gcc/testsuite/g++.dg/concepts/req2.C index 62501282af7..3c415233959 100644 --- a/gcc/testsuite/g++.dg/concepts/req2.C +++ b/gcc/testsuite/g++.dg/concepts/req2.C @@ -18,4 +18,3 @@ int main() { f2((void*)0); // { dg-error "cannot call" } } -// { dg-excess-errors "x|with" } -- 2.11.4.GIT