This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[c++-concepts] substitution fixes


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); 
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]