This patch rearranges the step in tsubst where a type's PLACEHOLDER_TYPE_CONSTRAINTS are set so that it happens before calling the function canonical_type_parameter.
canonical_type_parameter makes comparisons between types stored in the canonical_template_parms global variable. One of the steps in comparing types (equivalent_placeholder_constraints) references the PLACEHOLDER_TYPE_CONSTRAINTS on types. If constraints aren't set at this point, types with different PLACEHOLDER_TYPE_CONSTRAINTS can compare equal and receive the same TYPE_CANONICAL parameter. Bootstrapped and regression tested on x86_64-linux 2015-11-19 Ryan Burn <cont...@rnburn.com> PR c++/68434 * pt.c (tsubst): Set PLACEHOLDER_TYPE_CONSTRAINTS before calling canonical_type_parameter. * g++.dg/concepts/pr68434.C: New test
Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 230777) +++ gcc/cp/pt.c (working copy) @@ -12977,6 +12977,12 @@ TYPE_POINTER_TO (r) = NULL_TREE; TYPE_REFERENCE_TO (r) = NULL_TREE; + /* Propagate constraints on placeholders. */ + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) + if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (t)) + PLACEHOLDER_TYPE_CONSTRAINTS (r) + = tsubst_constraint (constr, args, complain, in_decl); + if (TREE_CODE (r) == TEMPLATE_TEMPLATE_PARM) /* We have reduced the level of the template template parameter, but not the levels of its @@ -12991,12 +12997,6 @@ else TYPE_CANONICAL (r) = canonical_type_parameter (r); - /* Propagate constraints on placeholders. */ - if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) - if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (t)) - PLACEHOLDER_TYPE_CONSTRAINTS (r) - = tsubst_constraint (constr, args, complain, in_decl); - if (code == BOUND_TEMPLATE_TEMPLATE_PARM) { tree argvec = tsubst (TYPE_TI_ARGS (t), args, Index: gcc/testsuite/g++.dg/concepts/pr68434.C =================================================================== --- gcc/testsuite/g++.dg/concepts/pr68434.C (revision 0) +++ gcc/testsuite/g++.dg/concepts/pr68434.C (working copy) @@ -0,0 +1,21 @@ +// { dg-options "-std=c++1z" } + +template <class> +concept bool C1 () { + return true; +} + +template <class> +concept bool C2 () { + return true; +} + +template <class Expr> +concept bool C3 () { + return requires (Expr expr) { + {expr}->C1; + {expr}->C2; + }; +} + +auto f (C3);