Fixing some bugs substituting through constraints. In particular, when diagnosing an error, make sure that we use the right arguments.
There was also a bug caused by substitution through a decltype-type. In particular, when folding a non-dependent expression containing a decltype-type, the inner type is not being resolved (because tsubst returns early when args == NULL_TREE). The second patch fixes a regression introduced by the first patch. 2014-08-11 Andrew Sutton <andrew.n.sut...@gmail.com> * gcc/cp/pt.c (tsubst): Don't short circuit substitution into types when processing constraints. * gcc/cp/constraint.c (tsubst_constraint_expr): Indicate that constraint processing is happening. (tsubst_constraint_info): Just substitute directly into the normalized constraints instead of re-normalizing. (diagnose_constraints): Adjust template arguments when diagnosing template constraint failures. * gcc/cp/logic.cc (decompose_assumptions): Handle null assumptions. Andrew Sutton
Index: pt.c =================================================================== --- pt.c (revision 213758) +++ pt.c (working copy) @@ -11960,6 +11960,8 @@ tsubst_exception_specification (tree fnt return new_specs; } +extern int processing_constraint; + /* Take the tree structure T and replace template parameters used therein with the argument vector ARGS. IN_DECL is an associated decl for diagnostics. If an error occurs, returns ERROR_MARK_NODE. @@ -11994,7 +11996,7 @@ tsubst (tree t, tree args, tsubst_flags_ if (DECL_P (t)) return tsubst_decl (t, args, complain); - if (args == NULL_TREE) + if (args == NULL_TREE && !processing_constraint) return t; code = TREE_CODE (t); Index: semantics.c =================================================================== --- semantics.c (revision 213758) +++ semantics.c (working copy) @@ -7011,6 +7011,7 @@ finish_decltype_type (tree expr, bool id return type; } + /* The type denoted by decltype(e) is defined as follows: */ expr = resolve_nondeduced_context (expr); @@ -7386,7 +7387,7 @@ finish_trait_expr (cp_trait_kind kind, t || kind == CPTK_IS_LITERAL_TYPE || kind == CPTK_IS_POD || kind == CPTK_IS_POLYMORPHIC - || kind == CPTK_IS_SAME_AS + || kind == CPTK_IS_SAME_AS || kind == CPTK_IS_STD_LAYOUT || kind == CPTK_IS_TRIVIAL || kind == CPTK_IS_UNION); Index: constraint.cc =================================================================== --- constraint.cc (revision 213758) +++ constraint.cc (working copy) @@ -241,7 +241,7 @@ tree normalize_stmt (tree); tree normalize_decl (tree); tree normalize_misc (tree); tree normalize_logical (tree); -tree normalize_call(tree); +tree normalize_call (tree); tree normalize_requires (tree); tree normalize_expr_req (tree); tree normalize_type_req (tree); @@ -1114,14 +1114,14 @@ tsubst_local_parms (tree t, } // Substitute ARGS into the requirement body (list of requirements), T. +// Note that if any substitutions fail, then this is equivalent to +// returning false. tree tsubst_requirement_body (tree t, tree args, tree in_decl) { tree r = NULL_TREE; while (t) { - // If any substitutions fail, then this is equivalent to - // returning false. tree e = tsubst_expr (TREE_VALUE (t), args, tf_none, in_decl, false); if (e == error_mark_node) e = boolean_false_node; @@ -1142,7 +1142,6 @@ tsubst_requires_expr (tree t, tree args, return finish_requires_expr (p, r); } - // Substitute ARGS into the valid-expr expression T. tree tsubst_validexpr_expr (tree t, tree args, tree in_decl) @@ -1197,6 +1196,12 @@ tsubst_nested_req (tree t, tree args, tr return tsubst_expr (TREE_OPERAND (t, 0), args, tf_none, in_decl, false); } +// Used in various contexts to control substitution. In particular, when +// non-zero, the substitution of NULL arguments into a type will still +// process the type as if passing non-NULL arguments, allowing type +// expressions to be fully elaborated during substitution. +int processing_constraint; + // Substitute the template arguments ARGS into the requirement // expression REQS. Errors resulting from substitution are not // diagnosed. @@ -1208,11 +1213,13 @@ tree tsubst_constraint_expr (tree reqs, tree args, bool do_not_fold) { cp_unevaluated guard; + ++processing_constraint; if (do_not_fold) ++processing_template_decl; tree r = tsubst_expr (reqs, args, tf_none, NULL_TREE, false); if (do_not_fold) --processing_template_decl; + --processing_constraint; return r; } @@ -1230,10 +1237,8 @@ tsubst_constraint_info (tree ci, tree ar result->leading_reqs = tsubst_constraint_expr (r, args, true); if (tree r = CI_TRAILING_REQS (ci)) result->trailing_reqs = tsubst_constraint_expr (r, args, true); - - // Build the normalized associated requiremnts. - tree r = conjoin_constraints (result->leading_reqs, result->trailing_reqs); - result->associated_reqs = normalize_constraints (r); + if (tree r = CI_ASSOCIATED_REQS (ci)) + result->associated_reqs = tsubst_constraint_expr (r, args, true); // Analyze the resulting constraints. // TODO: Is this actually necessary if the constraints are non-dependent? @@ -1269,7 +1274,6 @@ check_satisfied (tree req, tree args) // Requirements are satisfied when REQS evaluates to true. tree result = cxx_constant_value (req); - return result == boolean_true_node; } @@ -1677,7 +1681,14 @@ diagnose_constraints (location_t loc, tr return; } - // Otherwiise, diagnose the actual failed constraints. + // If this is a specialization of a template, we want to diagnose + // the dependent constraints. Also update the template arguments. + if (DECL_USE_TEMPLATE (decl)) { + args = DECL_TI_ARGS (decl); + decl = DECL_TI_TEMPLATE (decl); + } + + // Otherwise, diagnose the actual failed constraints. if (TREE_CODE (decl) == TEMPLATE_DECL) inform (loc, " constraints not satisfied %S", make_subst (decl, args)); else Index: logic.cc =================================================================== --- logic.cc (revision 213758) +++ logic.cc (working copy) @@ -391,7 +391,7 @@ extract_assumptions (proof_state& s) tree decompose_assumptions (tree t) { - if (t == error_mark_node) + if (!t || t == error_mark_node) return t; // Create a proof state, and insert T as the sole assumption.
Index: pt.c =================================================================== --- pt.c (revision 213822) +++ pt.c (working copy) @@ -12132,6 +12132,9 @@ tsubst (tree t, tree args, tsubst_flags_ r = NULL_TREE; + if (!args) + return t; + gcc_assert (TREE_VEC_LENGTH (args) > 0); template_parm_level_and_index (t, &level, &idx);