This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[c++-concepts] substitution fixes
- From: Andrew Sutton <andrew dot n dot sutton at gmail dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>, Braden Obrzut <admin at maniacsvault dot net>
- Date: Mon, 11 Aug 2014 13:32:24 -0400
- Subject: [c++-concepts] substitution fixes
- Authentication-results: sourceware.org; auth=none
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.sutton@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);