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 <[email protected]>
* 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 <[email protected]>
* 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
<[email protected]> 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 <[email protected]> wrote:
>>
>> On Wed, Jun 22, 2016 at 2:25 AM, Andrew Sutton
>> <[email protected]> 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;