public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [c++-concepts]: constraint association
@ 2013-06-22 15:57 Andrew Sutton
  2013-06-22 16:41 ` Gabriel Dos Reis
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Sutton @ 2013-06-22 15:57 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3397 bytes --]

I changed the implementation to associate constraints with template
decls (actually lang_decl_min) rather than template_info.

The handling of constrained non-template member functions changes a
little. When a class template is instantiated the instantiated
requirements are associated directly with the synthesized function
declaration since there is no template to attach them to. These are
checked in add_function_candidate.

This does not include support partial template specialization or
friend templates yet.

I did update part of the implementation for inherited constructors,
but its probably incomplete. I think I may also need to propagate
constraints from constrained non-template constructors as well.

Changelog:


2013-06-22  Andrew Sutton  <andrew.n.sutton@gmail.com>
        * gcc/cp/cp-tree.h (tree_template_info). Remove constraint from
        template info.
        (check_template_info): Removed (unused).
        (TI_CONSTRAINT): Removed (no longer needed) along with related macros.
        (DECL_CONSTRAONTS): New.
        (build_template_inof): Removed overload taking constraints.
        (get_constraints): Removed (no longer needed).
        * gcc/cp/class.c (are_constrained_member_overlaods): Allow constrained
        member function templates to be differentiated as overloads.
        * gcc/cp/decl.c (decls_match): Only compare constraints on
        declarations.
        (grokfndecl): Don't pass constraints to build_template_info.
        * gcc/cp/tree.c (bind_template_template_parm): Don't pass constraints
        to build_template_info.
        * gcc/cp/pt.c (build_template_info): Removed overload taking
        constraints.
        (check_explicit_specialization): Don't build new constraints for
        template info.
        (build_template_decl): Pass constraints. Update docs.
        (process_partial_specialization): Stub out support for constrained
        partial specialiations.
        (push_template_decl_real): Build template decls with current template
        reqs. Don't pass constraints to build_template_info.
        (add_inherited_template_parms): Build new constraints from inherited
        template constructors.
        (redeclare_class_template): Update to new constraint interface.
        (is_compatible_template_arg): Update to new constraint interface.
        (lookup_template_class_1): Don't build new constraints or pass them to
        build_template_info.
        (instantiate_class_template_1): Update to new constraints interface.
        (tsubst_decl): Don't build new constraints or pass them to
        build_template_info. For function templates, explicitly instantiate
        new constraints for member functions of class templates.
        * gcc/cp/semantics.c: Associate constraints with template template
        parms directly, not through template info.
        * gcc/cp/constraint.cc (get_constraints): Remove (no longer needed)
        along with related functions.
        (check_constraints): Update to use new constraints interface.
        (equivalently_constrained): Update to use new constraints interface.
        (more_constrained): Update to use new constraints interface.
        * gcc/cp/parser.cpp (cp_parser_late_parsing_for_member): Update to use
        new constraints interface.
        * gcc/cp/call.c (add_function_candidate): Update to use new constraints
        interface.

Andrew

[-- Attachment #2: template-decl.patch --]
[-- Type: application/octet-stream, Size: 25344 bytes --]

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 200329)
+++ cp/cp-tree.h	(working copy)
@@ -785,14 +785,13 @@ typedef struct qualified_typedef_usage_s
 
 struct GTY(()) tree_template_info {
   struct tree_common common;
-  tree constraint;
   vec<qualified_typedef_usage_t, va_gc> *typedefs_needing_access_checking;
 };
 
 /* Constraint information for a C++ declaration. This includes the
    requirements (as a constant expression) and the decomposed assumptions
    and conclusions. The assumptions and conclusions are cached for the
-   purposes of overlaod resolution and diagnostics. */
+   purposes of overload resolution and diagnostics. */
 struct GTY(()) tree_constraint_info {
   struct tree_base base;
   tree spelling;
@@ -809,15 +808,6 @@ check_constraint_info (tree t)
   return NULL;
 }
 
-// Returns true iff T is non-null and is a template info object.
-inline tree_template_info *
-check_template_info (tree t)
-{
-  if (t && TREE_CODE (t) == TEMPLATE_INFO)
-    return (tree_template_info *)t;
-  return NULL;
-}
-
 // Get the spelling of the requirements
 #define CI_SPELLING(NODE) \
   check_nonnull (check_constraint_info (NODE))->spelling
@@ -830,42 +820,9 @@ check_template_info (tree t)
 #define CI_ASSUMPTIONS(NODE) \
   check_nonnull (check_constraint_info (NODE))->assumptions
 
-// Get the constraint associated with the template info NODE.
-#define TI_CONSTRAINT(NODE) \
-  check_nonnull (check_template_info (NODE))->constraint
-
-// Get the spelling of constraints associated
-#define TI_SPELLING(NODE) \
-  check_nonnull (check_constraint_info (TI_CONSTRAINT (NODE)))->spelling
-
-// Get requirements associated with the template info NODE.
-#define TI_REQUIREMENTS(NODE) \
-  check_nonnull (check_constraint_info (TI_CONSTRAINT (NODE)))->requirements
-
-// Get assumptions associated with the template info NODE.
-#define TI_ASSUMPTIONS(NODE) \
-  check_nonnull (check_constraint_info (TI_CONSTRAINT (NODE)))->assumptions
-
-// Access constraint information for C++ declarations. Note that
-// NODE must have DECL_LANG_SPECIFIC.
-#define DECL_TEMPLATE_CONSTRAINT(NODE) \
-  TI_CONSTRAINT (DECL_TEMPLATE_INFO (NODE))
-
-// Access constraint information for class types.
-#define CLASSTYPE_TEMPLATE_CONSTRAINT(NODE) \
-  TI_CONSTRAINT (CLASSTYPE_TEMPLATE_INFO (NODE))
-
-// Access constraint information for enum types.
-#define ENUM_TEMPLATE_CONSTRAINT(NODE) \
-  TI_CONSTRAINT (ENUM_TEMPLATE_INFO (NODE))
-
-// Access constraint information for template template parameters.
-#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_CONSTRAINT(NODE) \
-  TI_CONSTRAINT (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE))
-
-// Access constraint information for any type.
-#define TYPE_TEMPLATE_CONSTRAINT(NODE) \
-  TI_CONSTRAINT (TYPE_TEMPLATE_INFO (NODE))
+// Access constraints for the declaration, NODE. 
+#define DECL_CONSTRAINTS(NODE) \
+  DECL_LANG_SPECIFIC (NODE)->u.min.constraint_info
 
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
@@ -2050,6 +2007,9 @@ struct GTY(()) lang_decl_min {
      DECL_TEMPLATE_INFO.  */
   tree template_info;
 
+  /* Template and declaration constraints. */
+  tree constraint_info;
+
   union lang_decl_u2 {
     /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
        THUNK_VIRTUAL_OFFSET.
@@ -5621,7 +5581,6 @@ extern bool function_parameter_expanded_
 extern tree make_pack_expansion                 (tree);
 extern bool check_for_bare_parameter_packs      (tree);
 extern tree build_template_info			(tree, tree);
-extern tree build_template_info                 (tree, tree, tree);
 extern tree get_template_info			(const_tree);
 extern vec<qualified_typedef_usage_t, va_gc> *get_types_needing_access_check (tree);
 extern int template_class_depth			(tree);
@@ -6281,7 +6240,6 @@ extern tree conjoin_requirements
 extern tree disjoin_requirements                (tree, tree);
 extern tree reduce_requirements                 (tree);
 extern tree make_constraints                    (tree);
-extern tree get_constraints                     (tree);
 extern bool check_constraints                   (tree);
 extern bool check_constraints                   (tree, tree);
 extern bool check_template_constraints          (tree, tree);
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 200329)
+++ cp/class.c	(working copy)
@@ -938,14 +938,19 @@ modify_vtable_entry (tree t,
 // of a class template with with different constraints. The types of the 
 // functions are assumed to be equivalent.
 static inline bool
-are_constrained_member_overloads (tree new_fn, tree old_fn) 
+are_constrained_member_overloads (tree newdecl, tree olddecl) 
 {
-  // Non-temploids cannot be constrained.
-  if (!DECL_TEMPLOID_INSTANTIATION (new_fn) 
-      && !DECL_TEMPLOID_INSTANTIATION (old_fn))
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    newdecl = DECL_TI_TEMPLATE (newdecl);
+  if (TREE_CODE (olddecl) == FUNCTION_DECL)
+    olddecl = DECL_TI_TEMPLATE (olddecl);
+
+  // If neither is a template or temploid, then they cannot
+  // be constrained declarations.
+  if (!newdecl && !olddecl)
     return false;
   else 
-    return !equivalently_constrained (new_fn, old_fn);
+    return !equivalently_constrained (newdecl, olddecl);
 }
 
 \f
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 200329)
+++ cp/decl.c	(working copy)
@@ -1082,16 +1082,9 @@ decls_match (tree newdecl, tree olddecl)
 	types_match = decls_match (oldres, newres);
 
         // If the types of the underlying templates match, compare
-        // their constraints. The declarations could differ there.
-        //
-        // Note that NEWDECL may not have been fully configured (no template
-        // info). If not, use the current temnplate requirements as those
-        // that would be associated with decl.
-        tree oldreqs = DECL_TEMPLATE_CONSTRAINT (oldres);
-        tree newreqs = DECL_TEMPLATE_INFO (newres)
-            ? DECL_TEMPLATE_CONSTRAINT (newres) : current_template_reqs;
+      // the template constraints. The declarations could differ there.
         if (types_match)
-          types_match = equivalent_constraints (oldreqs, newreqs);
+        types_match = equivalently_constrained (olddecl, newdecl);
     }
   else
     {
@@ -1564,8 +1557,7 @@ duplicate_decls (tree newdecl, tree oldd
 				   TREE_TYPE (TREE_TYPE (olddecl)))
                    // Template functions can also be disambiguated by
                    // constraints.
-                   && equivalent_constraints (get_constraints (olddecl), 
-                                              current_template_reqs))
+                   && equivalently_constrained (olddecl, newdecl))
 	    {
 	      error ("new declaration %q#D", newdecl);
 	      error ("ambiguates old declaration %q+#D", olddecl);
@@ -7516,7 +7508,7 @@ grokfndecl (tree ctype,
 	      fns = TREE_OPERAND (fns, 1);
 	    }
 	  gcc_assert (identifier_p (fns) || TREE_CODE (fns) == OVERLOAD);
-	  DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args, NULL_TREE);
+	  DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
 
 	  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
 	    if (TREE_PURPOSE (t)
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 200329)
+++ cp/tree.c	(working copy)
@@ -2030,8 +2030,7 @@ bind_template_template_parm (tree t, tre
   TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
   TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
    TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
-    = build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), 
-                           newargs, NULL_TREE);
+    = build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), newargs);
   
   TREE_TYPE (decl) = t2;
   TYPE_NAME (t2) = decl;
Index: cp/cxx-pretty-print.c
===================================================================
--- cp/cxx-pretty-print.c	(revision 200329)
+++ cp/cxx-pretty-print.c	(working copy)
@@ -2183,7 +2183,7 @@ pp_cxx_template_declaration (cxx_pretty_
       pp_newline_and_indent (pp, 3);
     }
 
-  if (tree c = get_constraints (t))
+  if (tree c = DECL_CONSTRAINTS (t))
     {
       pp_cxx_ws_string (pp, "requires");
       pp_cxx_expression (pp, CI_REQUIREMENTS (c));
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 200329)
+++ cp/pt.c	(working copy)
@@ -318,16 +318,9 @@ finish_member_template_decl (tree decl)
 tree
 build_template_info (tree template_decl, tree template_args)
 {
-  return build_template_info (template_decl, template_args, NULL_TREE);
-}
-
-tree
-build_template_info (tree template_decl, tree template_args, tree template_reqs)
-{
   tree result = make_node (TEMPLATE_INFO);
   TI_TEMPLATE (result) = template_decl;
   TI_ARGS (result) = template_args;
-  TI_CONSTRAINT (result) = template_reqs;
   return result;
 }
 
@@ -2715,8 +2708,6 @@ check_explicit_specialization (tree decl
 	    }
 
 	  /* Set up the DECL_TEMPLATE_INFO for DECL.  */
-          tree fn = DECL_TEMPLATE_RESULT (tmpl);
-          tree cons = tsubst_constraint (DECL_TEMPLATE_CONSTRAINT (fn), targs);
 	  DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, targs);
 
 	  /* Inherit default function arguments from the template
@@ -3974,14 +3965,15 @@ maybe_update_decl_type (tree orig_type,
 }
 
 /* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
-   template PARMS.  If MEMBER_TEMPLATE_P is true, the new template is
-   a member template.  Used by push_template_decl below.  */
+   template PARMS and constraints, CONS.  If MEMBER_TEMPLATE_P is true, 
+   the new  template is a member template. */
 
-static tree
-build_template_decl (tree decl, tree parms, bool member_template_p)
+tree
+build_template_decl (tree decl, tree parms, tree cons, bool member_template_p)
 {
   tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = parms;
+  DECL_CONSTRAINTS (tmpl) = cons;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
@@ -4066,6 +4058,10 @@ process_partial_specialization (tree dec
 
   gcc_assert (current_template_parms);
 
+  // TODO: Implement me!
+  if (current_template_reqs)
+    sorry("constrained partial specialization");
+
   inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
   ntparms = TREE_VEC_LENGTH (inner_parms);
 
@@ -4279,7 +4275,10 @@ process_partial_specialization (tree dec
   /* We should only get here once.  */
   gcc_assert (!COMPLETE_TYPE_P (type));
 
-  tree tmpl = build_template_decl (decl, current_template_parms,
+  // TODO: Implement constrained partial template specialization.
+  tree tmpl = build_template_decl (decl, 
+                                   current_template_parms, 
+                                   NULL_TREE,
 				   DECL_MEMBER_TEMPLATE_P (maintmpl));
   TREE_TYPE (tmpl) = type;
   DECL_TEMPLATE_RESULT (tmpl) = decl;
@@ -4747,7 +4746,9 @@ push_template_decl_real (tree decl, bool
 	}
       else
 	{
-	  tmpl = build_template_decl (decl, current_template_parms,
+	  tmpl = build_template_decl (decl, 
+                                current_template_parms,
+                                current_template_reqs,
 				      member_template_p);
 	  new_template_p = 1;
 
@@ -4790,15 +4791,15 @@ push_template_decl_real (tree decl, bool
 	     earlier call to check_explicit_specialization.  */
 	  args = DECL_TI_ARGS (decl);
 
-	  new_tmpl
-	    = build_template_decl (decl, current_template_parms,
+	  new_tmpl = build_template_decl (decl,
+                                    current_template_parms,
+                                    current_template_reqs,
 				   member_template_p);
 	  DECL_TEMPLATE_RESULT (new_tmpl) = decl;
 	  TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
 	  DECL_TI_TEMPLATE (decl) = new_tmpl;
 	  SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
-	  DECL_TEMPLATE_INFO (new_tmpl)
-	    = build_template_info (tmpl, args);
+	  DECL_TEMPLATE_INFO (new_tmpl) = build_template_info (tmpl, args);
 
 	  register_specialization (new_tmpl,
 				   most_general_template (tmpl),
@@ -4920,7 +4921,7 @@ template arguments to %qD do not match o
   if (DECL_TEMPLATE_INFO (tmpl))
     args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
 
-  info = build_template_info (tmpl, args, current_template_reqs);
+  info = build_template_info (tmpl, args);
 
   if (DECL_IMPLICIT_TYPEDEF_P (decl))
     SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
@@ -4954,8 +4955,19 @@ add_inherited_template_parms (tree fn, t
   tree parms
     = tree_cons (size_int (processing_template_decl + 1),
 		 inner_parms, current_template_parms);
-  tree tmpl = build_template_decl (fn, parms, /*member*/true);
+  tree tmpl = build_template_decl (fn, parms, NULL_TREE, /*member*/true);
   tree args = template_parms_to_args (parms);
+
+  // If the inherited constructor was constrained, then also
+  // propagate the constraints to the new declaration by
+  // rewriting them in terms of the local template parameters.
+  tree cons = DECL_CONSTRAINTS (inherited);
+  if (cons)
+    {
+      tree reqs = instantiate_requirements (CI_REQUIREMENTS (cons), args);
+      DECL_CONSTRAINTS (tmpl) = make_constraints (reqs);
+    }
+
   DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
   TREE_TYPE (tmpl) = TREE_TYPE (fn);
   DECL_TEMPLATE_RESULT (tmpl) = fn;
@@ -5072,10 +5084,8 @@ redeclare_class_template (tree type, tre
     }
 
   // Cannot redeclare a class template with a different set of constraints. 
-  tree tmpl_type = TREE_TYPE (tmpl);
-  if (!equivalent_constraints (TYPE_TEMPLATE_CONSTRAINT (tmpl_type), cons))
+  if (!equivalent_constraints (DECL_CONSTRAINTS (tmpl), cons))
     {
-      // FIXME: This points to the wrong line.
       error_at (input_location, "redeclaration %q#D with different "
                                 "constraints", tmpl);
       inform (DECL_SOURCE_LOCATION (tmpl), 
@@ -6230,14 +6240,16 @@ is_compatible_template_arg (tree parm, t
         return true;
     }
 
+  tree parmcons = DECL_CONSTRAINTS (parm);
+  tree argcons = DECL_CONSTRAINTS (arg);
+
   // If the template parameter is constrained, we need to rewrite its
   // constraints in terms of the ARG's template parameters. This ensures
   // that all of the template parameter types will have the same depth.
   //
   // Note that this is only valid when coerce_template_template_parm is
   // true for the innermost template parameters of PARM and ARG. In other
-  // words, because coercion is successful, conversion will be valid.
-  tree parmcons = DECL_TEMPLATE_CONSTRAINT (DECL_TEMPLATE_RESULT (parm));
+  // words, because coercion is successful, this conversion will be valid.
   if (parmcons)
     {
       tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (arg));
@@ -6249,8 +6261,6 @@ is_compatible_template_arg (tree parm, t
       parmcons = make_constraints (reqs);
     }
 
-  tree argtype = TREE_TYPE (arg);
-  tree argcons = get_constraints (argtype);
   return more_constraints (argcons, parmcons);
 }
 
@@ -7658,10 +7668,8 @@ lookup_template_class_1 (tree d1, tree a
 	    : CLASSTYPE_TI_TEMPLATE (found);
 	}
 
-      // Build the constraints for this type. 
-      tree type = TREE_TYPE (found);
-      tree cons = tsubst_constraint (TYPE_TEMPLATE_CONSTRAINT (type), arglist);
-       SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist, cons));
+      // Build template info for the new specialization.
+      SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
 
       elt.spec = t;
       slot = htab_find_slot_with_hash (type_specializations,
@@ -8501,8 +8509,7 @@ tsubst_friend_class (tree friend_tmpl, t
 
           saved_input_location = input_location;
           input_location = DECL_SOURCE_LOCATION (friend_tmpl);
-          tree type = TREE_TYPE (tmpl);
-          tree cons = CLASSTYPE_TEMPLATE_CONSTRAINT (type);
+          tree cons = DECL_CONSTRAINTS (tmpl);
           redeclare_class_template (TREE_TYPE (tmpl), parms, cons);
           input_location = saved_input_location;
           
@@ -8731,7 +8738,7 @@ instantiate_class_template_1 (tree type)
       // Check class template requirements. Note that constraints will 
       // already have been checked when trying to find a most specialized 
       // class among multiple specializations.
-      if (!check_template_constraints (pattern, args))
+      if (!check_template_constraints (templ, args))
         return error_mark_node;
     }
 
@@ -10182,13 +10189,8 @@ tsubst_decl (tree t, tree args, tsubst_f
 	gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
 	DECL_CHAIN (r) = NULL_TREE;
 
-        // Rebuild the constraints on the original template.
-        tree cons = get_constraints (t);
-        cons = tsubst_constraint (cons, args);
- 
-        // Build new template info linking to the original template
-        // decl, but having these args and constraints.
-        DECL_TEMPLATE_INFO (r) = build_template_info (t, args, cons);	
+        // Build new template info linking to the original template decl.
+        DECL_TEMPLATE_INFO (r) = build_template_info (t, args);	
 
 	if (TREE_CODE (decl) == TYPE_DECL
 	    && !TYPE_DECL_ALIAS_P (decl))
@@ -10428,11 +10430,17 @@ tsubst_decl (tree t, tree args, tsubst_f
 	   GEN_TMPL is NULL.  */
 	if (gen_tmpl)
 	  {
-            // Rebuild the template constraint.
-            tree cons = tsubst_constraint (DECL_TEMPLATE_CONSTRAINT (t), args);
+            // If the template declaration is constrained, propagate the
+            // constraints to new declaraiton.
+            tree cons = DECL_CONSTRAINTS (gen_tmpl);
+            if (cons)
+              {
+                tree reqs 
+                  = instantiate_requirements (CI_REQUIREMENTS (cons), argvec);
+                DECL_CONSTRAINTS (r) = make_constraints (reqs);;
+              }
 	    
-            DECL_TEMPLATE_INFO (r)
-	      = build_template_info (gen_tmpl, argvec, cons);
+            DECL_TEMPLATE_INFO (r) = build_template_info (gen_tmpl, argvec);
 	    SET_DECL_IMPLICIT_INSTANTIATION (r);
 
 	    tree new_r
@@ -10659,7 +10667,7 @@ tsubst_decl (tree t, tree args, tsubst_f
 	    DECL_INITIAL (r) = void_zero_node;
 	    gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
 	    retrofit_lang_decl (r);
-	    DECL_TEMPLATE_INFO (r) = build_template_info (t, args, NULL_TREE);
+	    DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
 	  }
 	/* We don't have to set DECL_CONTEXT here; it is set by
 	   finish_member_declaration.  */
@@ -10889,8 +10897,7 @@ tsubst_decl (tree t, tree args, tsubst_f
 
 	    register_specialization (r, gen_tmpl, argvec, false, hash);
 
-	    DECL_TEMPLATE_INFO (r) = 
-                build_template_info (tmpl, argvec, NULL_TREE);
+	    DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
 	    SET_DECL_IMPLICIT_INSTANTIATION (r);
 	  }
 	else if (cp_unevaluated_operand)
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 200329)
+++ cp/semantics.c	(working copy)
@@ -2570,16 +2570,13 @@ finish_template_template_parm (tree aggr
 {
   tree decl = build_lang_decl_loc (input_location,
 			  TYPE_DECL, identifier, NULL_TREE);
+
   tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
+  DECL_CONSTRAINTS (tmpl) = current_template_reqs;
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   DECL_ARTIFICIAL (decl) = 1;
 
-  // Build template info and associate it with the parameter.
-  DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, 
-                                                   current_template_args (), 
-                                                   current_template_reqs);
-
   end_template_decl ();
 
   gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
Index: cp/constraint.cc
===================================================================
--- cp/constraint.cc	(revision 200329)
+++ cp/constraint.cc	(working copy)
@@ -451,46 +451,8 @@ make_constraints (tree reqs)
   return (tree)cinfo;
 }
 
-namespace {
-
-inline tree
-get_type_constraints (tree t)
-{
-  // Template template arguments may not have template info.
-  if (!TYPE_TEMPLATE_INFO (t))
-    return NULL_TREE;
-  return TYPE_TEMPLATE_CONSTRAINT (t);
-}
-
-inline tree
-get_decl_constraints (tree t)
-{
-  if (TREE_CODE (t) == TEMPLATE_DECL)
-    {
-      tree d = DECL_TEMPLATE_RESULT (t);
-      if (TREE_CODE (d) == TYPE_DECL)
-        return get_type_constraints (TREE_TYPE (t));
-      else
-        return get_decl_constraints (d);
-    }
-  return DECL_TEMPLATE_CONSTRAINT (t);
-}
-
-} // end namespace
-
-// Return constraint info for the node T, regardless of the
-// kind of node.
-tree
-get_constraints (tree t)
-{
-  if (TYPE_P (t))
-    return get_type_constraints (t);
-  else if (DECL_P (t))
-    return get_decl_constraints (t);
-  else
-    gcc_unreachable ();
-  return false;
-}
+// -------------------------------------------------------------------------- //
+// Check Constraints
 
 // Returns true if the requirements expression REQS is satisfied
 // and false otherwise. The requirements are checked by simply 
@@ -539,28 +501,13 @@ check_constraints (tree cinfo, tree args
   return check_requirements (CI_REQUIREMENTS (cinfo), args);
 }
 
-static inline bool
-check_type_constraints (tree t, tree args)
-{
-  return check_constraints (CLASSTYPE_TEMPLATE_CONSTRAINT (t), args);
-}
-
-static inline bool
-check_decl_constraints (tree t, tree args)
-{
-  if (TREE_CODE (t) == TEMPLATE_DECL)
-    return check_decl_constraints (DECL_TEMPLATE_RESULT (t), args);
-  else
-    return check_constraints (DECL_TEMPLATE_CONSTRAINT (t), args);
-}
-
 // Check the constraints of the declaration or type T, against 
 // the specified arguments. Returns true if the constraints are 
 // satisfied and false otherwise.
 bool
 check_template_constraints (tree t, tree args)
 {
-  return check_constraints (get_constraints (t), args);
+  return check_constraints (DECL_CONSTRAINTS (t), args);
 }
 
 // Returns true when A and B are equivalent constraints.
@@ -577,7 +524,7 @@ bool
 equivalently_constrained (tree a, tree b)
 {
   gcc_assert (TREE_CODE (a) == TREE_CODE (b));
-  return equivalent_constraints (get_constraints (a), get_constraints (b));
+  return equivalent_constraints (DECL_CONSTRAINTS (a), DECL_CONSTRAINTS (b));
 }
 
 // Returns true when the A contains more atomic properties than B.
@@ -593,7 +540,7 @@ bool
 more_constrained (tree a, tree b)
 {
   gcc_assert (TREE_CODE (a) == TREE_CODE (b));
-  return more_constraints (get_constraints (a), get_constraints (b));
+  return more_constraints (DECL_CONSTRAINTS (a), DECL_CONSTRAINTS (b));
 }
 
 
@@ -799,7 +746,7 @@ diagnose_constraint_failure (location_t
 
   // Diagnose the constraints by recursively decomposing and
   // evaluating the template requirements.
-  tree reqs = CI_SPELLING (get_constraints (tmpl));
+  tree reqs = CI_SPELLING (DECL_CONSTRAINTS (tmpl));
   diagnose_requirements (loc, reqs, args);
 }
 
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 200329)
+++ cp/parser.c	(working copy)
@@ -22837,8 +22837,7 @@ cp_parser_late_parsing_for_member (cp_pa
   // Restore the declaration's requirements for the parsing of
   // the definition.
   tree saved_template_reqs = release (current_template_reqs);
-  if (tree tinfo = DECL_TEMPLATE_INFO (member_function))
-    current_template_reqs = TI_CONSTRAINT (tinfo);
+  current_template_reqs = DECL_CONSTRAINTS (member_function);
 
   /* If the body of the function has not yet been parsed, parse it
      now.  */
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 200329)
+++ cp/call.c	(working copy)
@@ -1870,14 +1870,11 @@ add_function_candidate (struct z_candida
 
   // Viable functions
   //
-  // Functions whose constraints are not satisfied are non-viable.
-  //
-  // This only happens with constrained non-template members, which
-  // we've currently disabled.
+  // Functions whose constraints are not satisfied are non-viable. Note
+  // that this only applies to non-template member functions (temploids).
   if (DECL_USE_TEMPLATE (fn))
     {
-      tree cons = DECL_TEMPLATE_CONSTRAINT (fn);
-      if (!check_constraints (cons))
+      if (!check_constraints (DECL_CONSTRAINTS (fn)))
         {
           tree tmpl = DECL_TI_TEMPLATE (fn);
           tree args = DECL_TI_ARGS (fn);
@@ -3024,8 +3021,7 @@ add_template_candidate_real (struct z_ca
          for this will point at template <class T> template <> S<T>::f(int),
          so that we can find the definition.  For the purposes of
          overload resolution, however, we want the original TMPL.  */
-      tree cons = tsubst_constraint (DECL_TEMPLATE_CONSTRAINT (fn), targs);
-      cand->template_decl = build_template_info (tmpl, targs, cons);
+      cand->template_decl = build_template_info (tmpl, targs);
     }
   else
     cand->template_decl = DECL_TEMPLATE_INFO (fn);

^ permalink raw reply	[flat|nested] 19+ messages in thread
* [c++-concepts] constraint association
@ 2014-06-28 14:57 Andrew Sutton
  0 siblings, 0 replies; 19+ messages in thread
From: Andrew Sutton @ 2014-06-28 14:57 UTC (permalink / raw)
  To: gcc-patches, Jason Merrill, Braden Obrzut

[-- Attachment #1: Type: text/plain, Size: 1928 bytes --]

After merging from trunk this morning, I discovered that
DECL_SIZE_UNIT is now being used to store lists of specializations. I
had been using that to store template constraints. Oops.

This patch moves constraints outside the usual tree structures into an
association maintained in a hash table. It also lays the framework for
allowing constraints to be associated with any _*DECL node (templates,
functions, variables, types, etc).

Changelog below; committed as 212103.

2014-06-28  Andrew Sutton  <andrew.n.sutton@gmail.com>
        * gcc/cp/cp-tree.h (DECL_CONSTRAINTS): Remove this macro; use
        get_constraints instead.
        (set_constraints): new.
        * gcc/cp/cxx-pretty-print.c (pp_cxx_template_declaration): Use
        get_constraints.
        * gcc/cp/pt.c (get_specialization_constraints): Use get_constraints.
        (build_template_decl): Use get_constraints.
        (process_partial_specialization): Use get_constraints.
        (add_inherited_template_parms): Use get_constraints.
        (redeclare_class_template): Use get_constraints.
        (is_compatible_template_arg): Use get_constraints.
        (tsubst_friend_class): Use get_constraints.
        (tsubst_decl): Uset get_constraints.
        * gcc/cp/semantics.c (finish_template_template_parm): Use
        get_constraints.
        (fixup_template_type): Use get_constraints.
        * gcc/cp/constraint.cc (constraints): New global association
        of declarations to constraints.
        (get_constraints): Return the associated constraints from the
        hash table.
        (set_constraints): New. Associate constraints with a declaration.
        (check_template_constraints): Use get_constraints.
        (equivalently_constrained): Use get_constraints.
        (more_constrained): Use get_constraints.
        (diagnose_constraints): Use get_constraints.
        * gcc/testsuite/g++.dg/concepts/partial-spec.C: New.

Andrew

[-- Attachment #2: constraint-assoc.patch --]
[-- Type: text/x-patch, Size: 9851 bytes --]

Index: gcc/cp/cxx-pretty-print.c
===================================================================
--- gcc/cp/cxx-pretty-print.c	(revision 212100)
+++ gcc/cp/cxx-pretty-print.c	(working copy)
@@ -2220,7 +2220,7 @@ pp_cxx_template_declaration (cxx_pretty_
       pp_newline_and_indent (pp, 3);
     }
 
-  if (tree c = DECL_CONSTRAINTS (t))
+  if (tree c = get_constraints (t))
     {
       pp_cxx_ws_string (pp, "requires");
       pp->expression (CI_REQUIREMENTS (c));
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 212101)
+++ gcc/cp/pt.c	(working copy)
@@ -846,7 +846,7 @@ get_specialization_constraints (tree typ
   // that type. If it is an explicit specialization, return null since
   // non-templates cannot be constrained.
   if (tree d = get_specializing_template_decl (type))
-    return DECL_CONSTRAINTS (d);
+    return get_constraints (d);
   else
     return NULL_TREE;
 }
@@ -4147,10 +4147,10 @@ build_template_decl (tree decl, tree par
 {
   tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = parms;
-  DECL_CONSTRAINTS (tmpl) = constr;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
+  set_constraints (tmpl, constr);
 
   return tmpl;
 }
@@ -4319,7 +4319,7 @@ process_partial_specialization (tree dec
      arguments but different constraints. */
   tree main_type = TREE_TYPE (maintmpl);
   tree main_args = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (main_type));
-  tree main_constr = DECL_CONSTRAINTS (maintmpl);
+  tree main_constr = get_constraints (maintmpl);
   if (comp_template_args (inner_args, main_args)
       && equivalent_constraints (current_template_reqs, main_constr))
     error ("partial specialization %qT does not specialize any "
@@ -5229,13 +5229,13 @@ add_inherited_template_parms (tree fn, t
   // If the inherited constructor was constrained, then also
   // propagate the constraints to the new declaration by
   // rewriting them in terms of the local template parameters.
-  tree cons = DECL_CONSTRAINTS (inherited);
+  tree cons = get_constraints (inherited);
   if (cons)
     {
       ++processing_template_decl;
       tree reqs = instantiate_requirements (CI_REQUIREMENTS (cons), args);
       --processing_template_decl;
-      DECL_CONSTRAINTS (tmpl) = make_constraints (reqs);
+      set_constraints (tmpl, make_constraints (reqs));
     }
 
   DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
@@ -5354,7 +5354,7 @@ redeclare_class_template (tree type, tre
     }
 
   // Cannot redeclare a class template with a different set of constraints. 
-  if (!equivalent_constraints (DECL_CONSTRAINTS (tmpl), cons))
+  if (!equivalent_constraints (get_constraints (tmpl), cons))
     {
       error_at (input_location, "redeclaration %q#D with different "
                                 "constraints", tmpl);
@@ -6586,8 +6586,8 @@ is_compatible_template_arg (tree parm, t
         return true;
     }
 
-  tree parmcons = DECL_CONSTRAINTS (parm);
-  tree argcons = DECL_CONSTRAINTS (arg);
+  tree parmcons = get_constraints (parm);
+  tree argcons = get_constraints (arg);
 
   // If the template parameter is constrained, we need to rewrite its
   // constraints in terms of the ARG's template parameters. This ensures
@@ -8997,7 +8997,7 @@ tsubst_friend_class (tree friend_tmpl, t
 
           saved_input_location = input_location;
           input_location = DECL_SOURCE_LOCATION (friend_tmpl);
-          tree cons = DECL_CONSTRAINTS (tmpl);
+          tree cons = get_constraints (tmpl);
           redeclare_class_template (TREE_TYPE (tmpl), parms, cons);
           input_location = saved_input_location;
           
@@ -10800,10 +10800,10 @@ tsubst_decl (tree t, tree args, tsubst_f
         // If constrained, also instantiate requirements.
         // TODO: Instantiate shorthand constraints on parameters also.
         // See tsubst_template_parms for that. 
-        if (tree ci = DECL_CONSTRAINTS (t))
+        if (tree ci = get_constraints (t))
           {
             tree reqs = instantiate_requirements (CI_SPELLING (ci), args);
-            DECL_CONSTRAINTS (r) = finish_template_requirements (reqs);
+            set_constraints (r, make_constraints (reqs));
           }
 
 	if (PRIMARY_TEMPLATE_P (t))
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 212101)
+++ gcc/cp/semantics.c	(working copy)
@@ -2693,9 +2693,9 @@ finish_template_template_parm (tree aggr
 
   tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
-  DECL_CONSTRAINTS (tmpl) = current_template_reqs;
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   DECL_ARTIFICIAL (decl) = 1;
+  set_constraints (tmpl, current_template_reqs);
 
   end_template_decl ();
 
@@ -3012,7 +3012,7 @@ fixup_template_type (tree type)
   tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
   while (specs)
     {
-      tree spec_constr = DECL_CONSTRAINTS (TREE_VALUE (specs));
+      tree spec_constr = get_constraints (TREE_VALUE (specs));
 
       // If the type and constraints match a specialization, then we
       // are entering that type. Note that the type comparison is
Index: gcc/cp/constraint.cc
===================================================================
--- gcc/cp/constraint.cc	(revision 212100)
+++ gcc/cp/constraint.cc	(working copy)
@@ -38,7 +38,7 @@ along with GCC; see the file COPYING3.
 #include "vec.h"
 #include "target.h"
 #include "bitmap.h"
-
+#include "hash-map.h"
 
 // -------------------------------------------------------------------------- //
 // Requirement Construction
@@ -564,22 +564,39 @@ make_constraints (tree reqs)
   return (tree)cinfo;
 }
 
+typedef hash_map<tree, tree> constraint_map;
+
+// Constraints (constraint_info nodes) are associatd with declrations 
+// via this mapping. Note that we don't store constraints directly in trees 
+// so we don't use the extra memory when concepts are not enabled. This also 
+// provides the ability to associate constraint information with a broader 
+// set of declarations (i.e., templates, functions, variables, template
+// parameters, etc).
+static constraint_map constraints;
+
 // Returns the template constraints of declaration T. If T is not a
 // template, this return NULL_TREE. Note that T must be non-null.
 tree
 get_constraints (tree t)
 {
   gcc_assert (DECL_P (t));
-  if (TREE_CODE (t) != TEMPLATE_DECL)
-    {
-      if (!DECL_TEMPLATE_INFO (t))
-        return NULL_TREE;
-      else
-        return DECL_CONSTRAINTS (DECL_TI_TEMPLATE (t));
-    }
-  return DECL_CONSTRAINTS (t);
+  if (tree* r = constraints.get(t))
+    return *r;
+  else
+    return NULL_TREE;
 }
 
+// Associate the given constraint information with the declaration.
+// Once set, constraints cannot be overwritten.
+void
+set_constraints (tree t, tree ci)
+{
+  gcc_assert (DECL_P (t));
+  gcc_assert(!get_constraints(t));
+  constraints.put(t, ci);
+}
+
+
 // Returns a conjunction of shorthand requirements for the template
 // parameter list PARMS. Note that the requirements are stored in
 // the TYPE of each tree node.
@@ -1187,7 +1204,7 @@ check_constraints (tree cinfo, tree args
 bool
 check_template_constraints (tree t, tree args)
 {
-  return check_constraints (DECL_CONSTRAINTS (t), args);
+  return check_constraints (get_constraints (t), args);
 }
 
 // -------------------------------------------------------------------------- //
@@ -1212,7 +1229,7 @@ bool
 equivalently_constrained (tree a, tree b)
 {
   gcc_assert (TREE_CODE (a) == TREE_CODE (b));
-  return equivalent_constraints (DECL_CONSTRAINTS (a), DECL_CONSTRAINTS (b));
+  return equivalent_constraints (get_constraints (a), get_constraints (b));
 }
 
 // Returns true when the A contains more atomic properties than B.
@@ -1228,7 +1245,7 @@ bool
 more_constrained (tree a, tree b)
 {
   gcc_assert (TREE_CODE (a) == TREE_CODE (b));
-  return more_constraints (DECL_CONSTRAINTS (a), DECL_CONSTRAINTS (b));
+  return more_constraints (get_constraints (a), get_constraints (b));
 }
 
 
@@ -1535,7 +1552,7 @@ diagnose_constraints (location_t loc, tr
 
   // Diagnose the constraints by recursively decomposing and
   // evaluating the template requirements.
-  tree reqs = CI_SPELLING (DECL_CONSTRAINTS (tmpl));
+  tree reqs = CI_SPELLING (get_constraints (tmpl));
   diagnose_requirements (loc, reqs, args);
 }
 
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 212101)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -828,16 +828,6 @@ check_constraint_info (tree t)
 #define CI_ASSUMPTIONS(NODE) \
   check_nonnull (check_constraint_info (NODE))->assumptions
 
-// Access constraints for the declaration, NODE.
-//
-// For TEMPLATE_DECL nodes, the constraints are stored in the
-// DECL_SIZE_UNIT node.
-//
-// TODO: This will need to be updated for shorthand constraints and
-// constrained auto declarations.
-#define DECL_CONSTRAINTS(NODE) \
-  (DECL_SIZE_UNIT (TEMPLATE_DECL_CHECK (NODE)))
-
 // Access the logical constraints on the template parameters introduced 
 // at a given template parameter list level indicated by NODE.
 #define TEMPLATE_PARMS_CONSTRAINTS(NODE) \
@@ -6358,6 +6348,7 @@ extern tree conjoin_requirements
 extern tree reduce_requirements                 (tree);
 extern tree make_constraints                    (tree);
 extern tree get_constraints                     (tree);
+extern void set_constraints                     (tree, tree);
 extern tree get_shorthand_requirements          (tree);
 
 extern tree build_concept_check                 (tree, tree, tree = NULL_TREE);

[-- Attachment #3: constraint-assoc-test.patch --]
[-- Type: text/x-patch, Size: 518 bytes --]

Index: gcc/testsuite/g++.dg/concepts/partial-spec.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/partial-spec.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/partial-spec.C	(revision 0)
@@ -0,0 +1,15 @@
+// { dg-options "-std=c++1z" }
+
+// Check that constraints don't break unconstrained partial
+// specializations. 
+
+template<typename T>
+  struct S { };
+
+template<typename T>
+  struct S<T*> { };
+
+template<>
+  struct S<int> { };
+
+int main() { }

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2014-06-28 14:57 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-22 15:57 [c++-concepts]: constraint association Andrew Sutton
2013-06-22 16:41 ` Gabriel Dos Reis
2013-06-22 16:56   ` Andrew Sutton
2013-06-22 17:11     ` Gabriel Dos Reis
2013-06-22 17:24       ` Gabriel Dos Reis
2013-06-22 18:05         ` Andrew Sutton
2013-06-22 18:27           ` Gabriel Dos Reis
2013-06-22 20:11             ` Andrew Sutton
2013-06-22 22:03               ` Gabriel Dos Reis
2013-06-22 22:55                 ` Andrew Sutton
2013-06-22 23:27                   ` Gabriel Dos Reis
2013-06-22 22:56               ` Gabriel Dos Reis
2013-06-22 23:04                 ` Andrew Sutton
2013-06-22 23:43                   ` Gabriel Dos Reis
2013-06-24 15:57                     ` Andrew Sutton
2013-06-24 17:16                       ` Gabriel Dos Reis
2013-06-27 14:38                       ` Jason Merrill
2013-06-27 14:47                         ` Jason Merrill
2014-06-28 14:57 [c++-concepts] " Andrew Sutton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).