I just tried building a fresh pull of cmcstl2, and I'm not seeing any errors as a result of not handling those missing codes in tsubst_constraint. At one point, I think it was not possible to get those other constraints in this context because they were nested in a parm_constr. But that seems obviously untrue now. But still... that gcc_unreachable isn't being triggered by any code in cmcstl.
I attached a patch that adds tsubsts for the missing constraints. Unfortunately, I don't have time to test thoroughly today. I did find another bug building cmcstl2, hence the attached disable-opt patch. For some reason, the memoization of concept satisfaction is giving momoized results for concept + args that have not yet been evaluated. This is exactly the same problem that made me disable the lookup/memoize_constraint_sat optimizations. Somehow I'm getting the same hash code for different arguments, and they also happen to compare equal. This doesn't seem to affect memoization of concept satisfaction. At least I haven't seen it yet. Anyways, disabling that optimization lets me build cmcstl2 with concepts. Sort of; there's a bug in the library, which is why Casey is added to the mailing. You're missing a const overload of operator* for basic_operator. Patch forthcoming. Changelogs below. 2016-07-10 Andrew Sutton <andrew.n.sut...@gmail.com> * constraint.cc (tsubst_type_constr, tsubst_implicit_conversion_constr, tsubst_argument_deduction_constr, tsubst_exception_constr): New. (tsubst_constraint): Add cases for missing constraints. 2016-07-10 Andrew Sutton <andrew.n.sut...@gmail.com> * pt.c (lookup_concept_satisfaction, memoize_concept_satisfaction): Disable memoization of concept results. Andrew Sutton On Sat, Jul 9, 2016 at 11:24 AM, Andrew Sutton <andrew.n.sut...@gmail.com> wrote: > Do we have a smaller test that reproduces this? One reason I didn't make > much progress was that I could never find a small test that triggers the > problem. I just pulled your branch and plan to do some digging tomorrow. > > > > On Fri, Jul 8, 2016 at 6:42 PM Jason Merrill <ja...@redhat.com> wrote: >> >> On Wed, Jun 22, 2016 at 2:25 AM, Andrew Sutton >> <andrew.n.sut...@gmail.com> wrote: >> >> > I've run into some trouble building cmcstl2: declarator requirements >> >> > on a function can lead to constraints that tsubst_constraint doesn't >> >> > handle. What was your theory of only handling a few _CONSTR codes >> >> > there? This is blocking me from checking in the patch. >> > >> > I wonder if those were the problems that I was running into, but hadn't >> > diagnosed. I had thought it shouldn't be possible to get the full set of >> > constraints in tsubst_constraint. I may have mis-analyzed the problem >> > for >> > function constraints. >> >> Any further thoughts? >> >> Jason > > -- > Andrew Sutton
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 145ae1e..745cbbc 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1625,12 +1625,70 @@ static tree tsubst_expr_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl) { cp_unevaluated guard; - tree expr = EXPR_CONSTR_EXPR (t); - tree check = tsubst_expr (expr, args, complain, in_decl, false); - if (check == error_mark_node) + tree ret = tsubst_expr (expr, args, complain, in_decl, false); + if (ret == error_mark_node) + return error_mark_node; + return build_nt (EXPR_CONSTR, ret); +} + +static tree +tsubst_type_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl) +{ + tree type = TYPE_CONSTR_TYPE (t); + tree ret = tsubst (type, args, complain, in_decl); + if (ret == error_mark_node) return error_mark_node; - return build_nt (EXPR_CONSTR, check); + return build_nt (TYPE_CONSTR, ret); +} + +static tree +tsubst_implicit_conversion_constr (tree t, tree args, tsubst_flags_t complain, + tree in_decl) +{ + cp_unevaluated guard; + tree expr = ICONV_CONSTR_EXPR (t); + tree type = ICONV_CONSTR_TYPE (t); + tree new_expr = tsubst_expr (expr, args, complain, in_decl, false); + if (new_expr == error_mark_node) + return error_mark_node; + tree new_type = tsubst (type, args, complain, in_decl); + if (new_type == error_mark_node) + return error_mark_node; + return build_nt (ICONV_CONSTR, new_expr, new_type); +} + +static tree +tsubst_argument_deduction_constr (tree t, tree args, tsubst_flags_t complain, + tree in_decl) +{ + cp_unevaluated guard; + tree expr = DEDUCT_CONSTR_EXPR (t); + tree pattern = DEDUCT_CONSTR_PATTERN (t); + tree autos = DEDUCT_CONSTR_PLACEHOLDER(t); + tree new_expr = tsubst_expr (expr, args, complain, in_decl, false); + if (new_expr == error_mark_node) + return error_mark_node; + /* It seems like substituting through the pattern will not affect the + placeholders. We should (?) be able to reuse the existing list + without any problems. If not, then we probably want to create a + new list of placeholders and then instantiate the pattern using + those. */ + tree new_pattern = tsubst (pattern, args, complain, in_decl); + if (new_pattern == error_mark_node) + return error_mark_node; + return build_nt (DEDUCT_CONSTR, new_expr, new_pattern, autos); +} + +static tree +tsubst_exception_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl) +{ + cp_unevaluated guard; + tree expr = EXCEPT_CONSTR_EXPR (t); + tree ret = tsubst_expr (expr, args, complain, in_decl, false); + if (ret == error_mark_node) + return error_mark_node; + return build_nt (EXCEPT_CONSTR, ret); } static tree tsubst_parameterized_constraint (tree, tree, tsubst_flags_t, tree); @@ -1655,6 +1713,14 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) return tsubst_parameterized_constraint (t, args, complain, in_decl); case EXPR_CONSTR: return tsubst_expr_constr (t, args, complain, in_decl); + case TYPE_CONSTR: + return tsubst_type_constr (t, args, complain, in_decl); + case ICONV_CONSTR: + return tsubst_implicit_conversion_constr (t, args, complain, in_decl); + case DEDUCT_CONSTR: + return tsubst_argument_deduction_constr (t, args, complain, in_decl); + case EXCEPT_CONSTR: + return tsubst_exception_constr (t, args, complain, in_decl); default: gcc_unreachable (); } @@ -1665,6 +1731,7 @@ tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) specializations for each of parameter in PARMS and its corresponding substituted constraint variable in VARS. Returns VARS. */ + static tree declare_constraint_vars (tree parms, tree vars) {
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 70f3208..780c119 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -24724,27 +24724,29 @@ memoize_constraint_satisfaction (tree, tree, tree result) /* Search for a memoized satisfaction result for a concept. */ tree -lookup_concept_satisfaction (tree tmpl, tree args) +lookup_concept_satisfaction (tree, tree) { - concept_spec_entry elt = { tmpl, args, NULL_TREE }; - concept_spec_entry* found = concept_memos->find (&elt); - if (found) - return found->result; - else - return NULL_TREE; + return NULL_TREE; + // concept_spec_entry elt = { tmpl, args, NULL_TREE }; + // concept_spec_entry* found = concept_memos->find (&elt); + // if (found) + // return found->result; + // else + // return NULL_TREE; } /* Memoize the result of a concept check. Returns the saved result. */ tree -memoize_concept_satisfaction (tree tmpl, tree args, tree result) +memoize_concept_satisfaction (tree, tree, tree result) { - concept_spec_entry elt = {tmpl, args, result}; - concept_spec_entry** slot = concept_memos->find_slot (&elt, INSERT); - concept_spec_entry* entry = ggc_alloc<concept_spec_entry> (); - *entry = elt; - *slot = entry; return result; + // concept_spec_entry elt = {tmpl, args, result}; + // concept_spec_entry** slot = concept_memos->find_slot (&elt, INSERT); + // concept_spec_entry* entry = ggc_alloc<concept_spec_entry> (); + // *entry = elt; + // *slot = entry; + // return result; } static GTY (()) hash_table<concept_spec_hasher> *concept_expansions;