public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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

* Re: [c++-concepts]: constraint association
  2013-06-27 14:38                       ` Jason Merrill
@ 2013-06-27 14:47                         ` Jason Merrill
  0 siblings, 0 replies; 19+ messages in thread
From: Jason Merrill @ 2013-06-27 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-patches

Just a couple of typos:

On 06/24/2013 11:56 AM, Andrew Sutton wrote:
> +// Returns true if NEWDECL and OLDDEC are member functions with with

"OLDDECL"

> +// different constraints. If NEWDECL and OLDDECL are non-template members
> +// or specializations of non-template members, they overloads are

"the overloads"

> +// differentiated by the template constraints.

Jason


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

* Re: [c++-concepts]: constraint association
  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
  1 sibling, 1 reply; 19+ messages in thread
From: Jason Merrill @ 2013-06-27 14:38 UTC (permalink / raw)
  To: Andrew Sutton, Gabriel Dos Reis; +Cc: gcc-patches

Just a couple of typos:

On 06/24/2013 11:56 AM, Andrew Sutton wrote:
> +// Returns true if NEWDECL and OLDDEC are member functions with with

"OLDDECL"

> +// different constraints. If NEWDECL and OLDDECL are non-template members
> +// or specializations of non-template members, they overloads are

"the overloads"

> +// differentiated by the template constraints.

Jason

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

* Re: [c++-concepts]: constraint association
  2013-06-24 15:57                     ` Andrew Sutton
@ 2013-06-24 17:16                       ` Gabriel Dos Reis
  2013-06-27 14:38                       ` Jason Merrill
  1 sibling, 0 replies; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-24 17:16 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches, jason

Andrew Sutton <andrew.n.sutton@gmail.com> writes:

| Revisions from previous patch.
| 
| I've taken constraint_info out of lang_decl_min and made it specific
| to TEMPLATE_DECLs by saving it as DECL_SIZE_UNIT. It seems to be
| unused for templates. When I start working on the shorthand notation,
| I'll do something similar for template parameters and auto
| declarations.

That sounds good.

| The handling of non-template member functions also changes a little.
| Here's a history of the revisions:
| 
|   - Current branch: the instantiated constraints are stored in
| TEMPLATE_INFO and then checked in add_function_candidate.
|   - Previous patch: instantiated constraints are associated directly
| with the member functions' FUNCTION_DECL.
|   - Current patch: constraints are only instantiated and checked at
| the point of use.

I think that should be OK for now.  If and when needed, we could
use a bit to say the use is OK based on the argument types.  But, for
the moment, I think we should be fine.  In fact, we may not need that
bit at all if we conduct a careful analysis.

| The current patch will lead to redundant checks. I left a comment in
| call.c explaining that we could use a bit in TEMPLATE_INFO to save
| whether or not an instantiated declaration actually satisfies its
| requirements.

See comment below.

|  /* 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)
|  {

GCC source code base is still strongly Lispy, so when one sees 'cons',
one can't avoid association with the function 'cons' (even though it is
in fact spelled tree_cons.)  I would suggest spelling 'constraints' in full.

| +// Access constraints for the declaration, NODE.
| +//
| +// For TEMPLATE_DECL nodes, the constraints are stored in the
| +// DECL_SIZE 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)))

The comment should say DECL_SIZE_UNIT, not DECL_SIZE (which is
used to store specializations.)


Patch OK with the suggested fixes.  Thanks,

-- Gaby

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

* Re: [c++-concepts]: constraint association
  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
  0 siblings, 2 replies; 19+ messages in thread
From: Andrew Sutton @ 2013-06-24 15:57 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc-patches

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

Revisions from previous patch.

I've taken constraint_info out of lang_decl_min and made it specific
to TEMPLATE_DECLs by saving it as DECL_SIZE_UNIT. It seems to be
unused for templates. When I start working on the shorthand notation,
I'll do something similar for template parameters and auto
declarations.

The handling of non-template member functions also changes a little.
Here's a history of the revisions:

  - Current branch: the instantiated constraints are stored in
TEMPLATE_INFO and then checked in add_function_candidate.
  - Previous patch: instantiated constraints are associated directly
with the member functions' FUNCTION_DECL.
  - Current patch: constraints are only instantiated and checked at
the point of use.

The current patch will lead to redundant checks. I left a comment in
call.c explaining that we could use a bit in TEMPLATE_INFO to save
whether or not an instantiated declaration actually satisfies its
requirements.


Andrew



On Sat, Jun 22, 2013 at 6:43 PM, Gabriel Dos Reis <gdr@axiomatics.org> wrote:
> Andrew Sutton <andrew.n.sutton@gmail.com> writes:
>
> | > | But, I don't think we have a single TEMPLATE_PARM_DECL node. Template
> | > | parameters are either TYPE_DECLs or PARM_DECLs. I think auto
> | > | declarations, get VAR_DECLs, but I haven't looked closely at that
> | > | design. I'd have to look to see if there are any free tree slots all
> | > | of those decl nodes to minimize.
> | >
> | > The individual constraint for a template parameter should probably go
> | > with the TEMPLATE_PARM_INDEX which is the uniform representation of
> | > template parameters.  But, the real cumulative constraints go with the
> | > TEMPLATE_DECLs.  With Jason's patch that creates TEMPLATE_DECLs for
> | > partial instantiations, I believe we have all the bases covered.
> |
> | I have to look through the template parameter creation code, but that
> | sounds about right.
>
> build_template_parm    -- the real (low-level) constructor
> process_template_parm  -- higher-level interface to the parsing
> make_auto_1 -- for type of variables declared with 'auto'.
>
> -- Gaby
>



-- 
Andrew Sutton
andrew.n.sutton@gmail.com

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

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 200331)
+++ 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,7 @@ 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);
-	    
-            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 +10657,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 +10887,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/parser.c
===================================================================
--- cp/parser.c	(revision 200331)
+++ cp/parser.c	(working copy)
@@ -23152,9 +23152,9 @@ 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 = get_constraints (member_function);
 
   /* If the body of the function has not yet been parsed, parse it
      now.  */
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 200331)
+++ 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/constraint.cc
===================================================================
--- cp/constraint.cc	(revision 200331)
+++ cp/constraint.cc	(working copy)
@@ -451,46 +451,29 @@ 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);
-}
+// -------------------------------------------------------------------------- //
+// Get Constraints
 
-inline tree
-get_decl_constraints (tree t)
+// 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)
 {
-  if (TREE_CODE (t) == TEMPLATE_DECL)
+  gcc_assert (DECL_P (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));
+      if (!DECL_TEMPLATE_INFO (t))
+        return NULL_TREE;
       else
-        return get_decl_constraints (d);
+        return DECL_CONSTRAINTS (DECL_TI_TEMPLATE (t));
     }
-  return DECL_TEMPLATE_CONSTRAINT (t);
+  return DECL_CONSTRAINTS (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 +522,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 +545,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 +561,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 +767,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/tree.c
===================================================================
--- cp/tree.c	(revision 200331)
+++ 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/class.c
===================================================================
--- cp/class.c	(revision 200331)
+++ cp/class.c	(working copy)
@@ -934,18 +934,26 @@ modify_vtable_entry (tree t,
     }
 }
 
-// Returns true if NEW_FN and OLD_FN are non-template member functions
-// of a class template with with different constraints. The types of the 
-// functions are assumed to be equivalent.
+// Returns true if NEWDECL and OLDDEC are member functions with with 
+// different constraints. If NEWDECL and OLDDECL are non-template members
+// or specializations of non-template members, they overloads are 
+// differentiated by the template constraints.
+//
+// Note that 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/cxx-pretty-print.c
===================================================================
--- cp/cxx-pretty-print.c	(revision 200331)
+++ 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/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 200331)
+++ 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,15 @@ 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.
+//
+// For TEMPLATE_DECL nodes, the constraints are stored in the
+// DECL_SIZE 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)))
 
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
@@ -5621,7 +5584,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);
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 200331)
+++ cp/call.c	(working copy)
@@ -1820,6 +1820,15 @@ remaining_arguments (tree arg)
   return n;
 }
 
+// Returns true if fn is a non-template member function.
+static bool
+is_non_template_member_fn (tree fn)
+{
+  return DECL_FUNCTION_MEMBER_P (fn) &&
+         DECL_TEMPLATE_INFO (fn) &&
+         !DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn));
+}
+
 /* Create an overload candidate for the function or method FN called
    with the argument list FIRST_ARG/ARGS and add it to CANDIDATES.
    FLAGS is passed on to implicit_conversion.
@@ -1872,15 +1881,23 @@ add_function_candidate (struct z_candida
   //
   // Functions whose constraints are not satisfied are non-viable.
   //
-  // This only happens with constrained non-template members, which
-  // we've currently disabled.
-  if (DECL_USE_TEMPLATE (fn))
-    {
-      tree cons = DECL_TEMPLATE_CONSTRAINT (fn);
-      if (!check_constraints (cons))
+  // For function templates, constraints are checked as part of template
+  // argument deduction. A failure there means that the template is
+  // already added as a non-viable candidate. For non-template member 
+  // functions, however, the declaration declaration has already been
+  // synthesized, but its constraints have not actually been checked.
+  // We should do that now.
+  //
+  // TODO: Consider checking constrained non-template members during
+  // class template instantiation and setting a flag indicating whether
+  // or not the declaration is viable. This could be set as a flag in
+  // TEMPLATE_INFO (there should be a bunch of unused bits there).
+  if (is_non_template_member_fn (fn)) 
         {
           tree tmpl = DECL_TI_TEMPLATE (fn);
           tree args = DECL_TI_ARGS (fn);
+      if (!check_template_constraints (tmpl, args))
+        {
           reason = template_constraint_failure (tmpl, args);
           viable = false;
           goto out;          
@@ -3024,8 +3041,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);
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 200331)
+++ 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));

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

* Re: [c++-concepts]: constraint association
  2013-06-22 23:04                 ` Andrew Sutton
@ 2013-06-22 23:43                   ` Gabriel Dos Reis
  2013-06-24 15:57                     ` Andrew Sutton
  0 siblings, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 23:43 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches

Andrew Sutton <andrew.n.sutton@gmail.com> writes:

| > | But, I don't think we have a single TEMPLATE_PARM_DECL node. Template
| > | parameters are either TYPE_DECLs or PARM_DECLs. I think auto
| > | declarations, get VAR_DECLs, but I haven't looked closely at that
| > | design. I'd have to look to see if there are any free tree slots all
| > | of those decl nodes to minimize.
| >
| > The individual constraint for a template parameter should probably go
| > with the TEMPLATE_PARM_INDEX which is the uniform representation of
| > template parameters.  But, the real cumulative constraints go with the
| > TEMPLATE_DECLs.  With Jason's patch that creates TEMPLATE_DECLs for
| > partial instantiations, I believe we have all the bases covered.
| 
| I have to look through the template parameter creation code, but that
| sounds about right.

build_template_parm    -- the real (low-level) constructor
process_template_parm  -- higher-level interface to the parsing
make_auto_1 -- for type of variables declared with 'auto'.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  2013-06-22 22:55                 ` Andrew Sutton
@ 2013-06-22 23:27                   ` Gabriel Dos Reis
  0 siblings, 0 replies; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 23:27 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches

Andrew Sutton <andrew.n.sutton@gmail.com> writes:

| > | Previous discussion seemed to indicate that saving constraints with
| > | template decls was preferable.
| >
| > Yes; exactly.
| >
| > | The committed version in the branch carries those constraints in
| > | template_info for the temploid.
| >
| > Yes; I think that is good.
| 
| So we should associate constraints with both TEMPLATE_DECLs and TEMPLATE_INFOs?
| 
| Storing constraints with TEMPLATE_INFO could require more memory since
| each instantiation generates a new one. It doesn't look like that
| structure has any free trees anyways, so we'd have to add a field
| (which is what we've done now).

We don't want to unnecessarily duplicate the information...
The constraints have to go with TEMPLATE_DECLs directly or in the
TEMPLATE_INFO.  But, we don't want a "distributed fat."

| Concepts lite shouldn't need to track instantiated constraints,
| anyway. Constraints are either satisfied or they aren't.

Exactly right.  For partial ordering, we use the original form to decide
most specialized -- mirroring what we do for non-constrained templates.
And when we do that we use the constraints from the source-level decls.

| > | > I think we need to remember them for duplicate_decls or other routines
| > | > that either check or use ODR-derived properties.
| > |
| > | This doesn't seem to be a problem. IIRC, the instantiated declarations
| > | are differentiated by their template constraints, not their
| > | instantiated constraints.
| > |
| > | Differentiating by instantiated constraints may not be viable,
| > | anyways. Especially, if the instantiation folds them to only "true" or
| > | "false".
| >
| > Hmm, I am lost here.  Could you clarify with examples?
| 
| template<typename T>
| struct S {
|   void f() requires Input_iterator<T> { }
|   void f() requires Bidirectional_iterator<T> { }
| };
| 
| Probably an unlikely example, but anyways...

Ah, I think last time we discussed this, it was something like

   template<typename T>
    struct vector {
       void push_back(T&&) requires MovableOnly<T>;
       void push_back(const T&) requires CopyConstructible<T>;
    };

but they are already distinguished by the parameter lists so that is not
an issue.

The cases were you can't distinguish the instantiated decls based on their
types correspond to "perfect" (partial) specializations; we should use the
existing  model for those in this specific case.  That means going back
to the abstract form (the associated temploids) and 

| The class S<T> has two declarations of f, "S<T>::f() requires
| Input_iterator<T>" and "S<T>::f() requires Bidirectional_iterator<T>".
| When you instantiate S, say S<int*>, we instantiate the nested
| declarations. They are made distinct on the basis of the dependent
| constrains. If you try to distinguish them on the basis of their
| instantiated constraints you could have:
| 
| template<>
| struct S<int*> {
|   void f() requires true;
|   void f() requires true; // Oops. Not desirable.
| };

They look like partial specializations of member templates
(which they morally are); we should treat them as such.  You have
similar situation if you put them at non-class scope.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  2013-06-22 22:56               ` Gabriel Dos Reis
@ 2013-06-22 23:04                 ` Andrew Sutton
  2013-06-22 23:43                   ` Gabriel Dos Reis
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Sutton @ 2013-06-22 23:04 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc-patches

> | But, I don't think we have a single TEMPLATE_PARM_DECL node. Template
> | parameters are either TYPE_DECLs or PARM_DECLs. I think auto
> | declarations, get VAR_DECLs, but I haven't looked closely at that
> | design. I'd have to look to see if there are any free tree slots all
> | of those decl nodes to minimize.
>
> The individual constraint for a template parameter should probably go
> with the TEMPLATE_PARM_INDEX which is the uniform representation of
> template parameters.  But, the real cumulative constraints go with the
> TEMPLATE_DECLs.  With Jason's patch that creates TEMPLATE_DECLs for
> partial instantiations, I believe we have all the bases covered.

I have to look through the template parameter creation code, but that
sounds about right.

Andrew

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

* Re: [c++-concepts]: constraint association
  2013-06-22 20:11             ` Andrew Sutton
  2013-06-22 22:03               ` Gabriel Dos Reis
@ 2013-06-22 22:56               ` Gabriel Dos Reis
  2013-06-22 23:04                 ` Andrew Sutton
  1 sibling, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 22:56 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches


| But, I don't think we have a single TEMPLATE_PARM_DECL node. Template
| parameters are either TYPE_DECLs or PARM_DECLs. I think auto
| declarations, get VAR_DECLs, but I haven't looked closely at that
| design. I'd have to look to see if there are any free tree slots all
| of those decl nodes to minimize.

The individual constraint for a template parameter should probably go
with the TEMPLATE_PARM_INDEX which is the uniform representation of
template parameters.  But, the real cumulative constraints go with the
TEMPLATE_DECLs.  With Jason's patch that creates TEMPLATE_DECLs for
partial instantiations, I believe we have all the bases covered.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  2013-06-22 22:03               ` Gabriel Dos Reis
@ 2013-06-22 22:55                 ` Andrew Sutton
  2013-06-22 23:27                   ` Gabriel Dos Reis
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Sutton @ 2013-06-22 22:55 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc-patches

> | Previous discussion seemed to indicate that saving constraints with
> | template decls was preferable.
>
> Yes; exactly.
>
> | The committed version in the branch carries those constraints in
> | template_info for the temploid.
>
> Yes; I think that is good.

So we should associate constraints with both TEMPLATE_DECLs and TEMPLATE_INFOs?

Storing constraints with TEMPLATE_INFO could require more memory since
each instantiation generates a new one. It doesn't look like that
structure has any free trees anyways, so we'd have to add a field
(which is what we've done now).

Concepts lite shouldn't need to track instantiated constraints,
anyway. Constraints are either satisfied or they aren't.

> | > I think we need to remember them for duplicate_decls or other routines
> | > that either check or use ODR-derived properties.
> |
> | This doesn't seem to be a problem. IIRC, the instantiated declarations
> | are differentiated by their template constraints, not their
> | instantiated constraints.
> |
> | Differentiating by instantiated constraints may not be viable,
> | anyways. Especially, if the instantiation folds them to only "true" or
> | "false".
>
> Hmm, I am lost here.  Could you clarify with examples?

template<typename T>
struct S {
  void f() requires Input_iterator<T> { }
  void f() requires Bidirectional_iterator<T> { }
};

Probably an unlikely example, but anyways...

The class S<T> has two declarations of f, "S<T>::f() requires
Input_iterator<T>" and "S<T>::f() requires Bidirectional_iterator<T>".
When you instantiate S, say S<int*>, we instantiate the nested
declarations. They are made distinct on the basis of the dependent
constrains. If you try to distinguish them on the basis of their
instantiated constraints you could have:

template<>
struct S<int*> {
  void f() requires true;
  void f() requires true; // Oops. Not desirable.
};

Andrew

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

* Re: [c++-concepts]: constraint association
  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 22:56               ` Gabriel Dos Reis
  1 sibling, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 22:03 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches


* We have to avoid increasing memory consumption for regular C++ codes
  that do not use concepts lite.  This is an important criteria.  We
  have only one front-end that is invoked in C++03, C++11, C++14, and
  C++17 modes.  Almost all existing codes are C++03, C++11, and even
  C++14 only and don't use concepts lite. 

| > | Agreed. But without some source-level annotations in the tree, I don't
| > | think I can generate the diagnostics that programmer's might otherwise
| > | expect. I'd have to emit the internal representation.
| >
| > Do you have examples where we don't do or we can't do the obvious thing
| > in terms of diagnostics?
| 
| I think we'll have this problem anywhere we want to pretty-print a
| template parameter that's declared using the concept shorthand. I'll
| have a better feeling for the issue once I start working the shorthand
| in.

Maybe it will help if we have concrete situations to work from. 

| > | If those constraints are cached, I don't see any other place to put
| > | them except in the template info.
| >
| > Exactly.
| 
| Previous discussion seemed to indicate that saving constraints with
| template decls was preferable.

Yes; exactly.

| > | On the other hand, it seems like the only place we actually need to
| > | worry about is with non-template member functions.
| >
| > Member function of templates are temploids, so no worry there either.
| > (Internally, they act and are represented like templates.)
| 
| There's a difference between when those declarations are instantiated
| and when their constraints really need to be evaluated. Because
| temploids are instantiated with a class definition (prior to use), we
| (may) need to carry some information with those instances.

Yes, member *declarations* are almost always instantiated as part of the
class instantiation.

| The committed version in the branch carries those constraints in
| template_info for the temploid.

Yes; I think that is good.

| The submitted patch carries the
| instantiated constraints with the member declaration. The most recent
| version on my work computer doesn't carry any constraints with
| temploids -- it instantiates the requirements directly from the
| template/args in the declarations' template_info.
| 
| > | I think I can just grab the requirements and arguments and check them
| > | without caching them in the template_info.
| >
| > I think we need to remember them for duplicate_decls or other routines
| > that either check or use ODR-derived properties.
| 
| This doesn't seem to be a problem. IIRC, the instantiated declarations
| are differentiated by their template constraints, not their
| instantiated constraints.
| 
| Differentiating by instantiated constraints may not be viable,
| anyways. Especially, if the instantiation folds them to only "true" or
| "false".

Hmm, I am lost here.  Could you clarify with examples?

| > | We still don't have nodes specific to TEMPLTAE_DECL or
| > | TEMPLATE_PARM_DECL though.
| >
| > A tree with TREE_CODE equal to TEMPLATE_DECL or TEMPLATE_PARM_DECL is
| > just that.  What we do is to use all unused- tree slots.  Or are you
| > suggesting we have exhausted all available pre-defined slots on such nodes?
| 
| Unknown. I'll have to look.
| 
| But, I don't think we have a single TEMPLATE_PARM_DECL node. 
| Template parameters are either TYPE_DECLs or PARM_DECLs. I think auto
| declarations, get VAR_DECLs, but I haven't looked closely at that
| design. I'd have to look to see if there are any free tree slots all
| of those decl nodes to minimize.

the type specifier 'auto' is represented by a fresh TEMPLATE_TYPE_PARM,
therefore has a TEMPLATE_TYPE_DECL.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  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:56               ` Gabriel Dos Reis
  0 siblings, 2 replies; 19+ messages in thread
From: Andrew Sutton @ 2013-06-22 20:11 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: gcc-patches

> | Agreed. But without some source-level annotations in the tree, I don't
> | think I can generate the diagnostics that programmer's might otherwise
> | expect. I'd have to emit the internal representation.
>
> Do you have examples where we don't do or we can't do the obvious thing
> in terms of diagnostics?

I think we'll have this problem anywhere we want to pretty-print a
template parameter that's declared using the concept shorthand. I'll
have a better feeling for the issue once I start working the shorthand
in.

> | If those constraints are cached, I don't see any other place to put
> | them except in the template info.
>
> Exactly.

Previous discussion seemed to indicate that saving constraints with
template decls was preferable.

> | On the other hand, it seems like the only place we actually need to
> | worry about is with non-template member functions.
>
> Member function of templates are temploids, so no worry there either.
> (Internally, they act and are represented like templates.)

There's a difference between when those declarations are instantiated
and when their constraints really need to be evaluated. Because
temploids are instantiated with a class definition (prior to use), we
(may) need to carry some information with those instances.

The committed version in the branch carries those constraints in
template_info for the temploid. The submitted patch carries the
instantiated constraints with the member declaration. The most recent
version on my work computer doesn't carry any constraints with
temploids -- it instantiates the requirements directly from the
template/args in the declarations' template_info.

> | I think I can just grab the requirements and arguments and check them
> | without caching them in the template_info.
>
> I think we need to remember them for duplicate_decls or other routines
> that either check or use ODR-derived properties.

This doesn't seem to be a problem. IIRC, the instantiated declarations
are differentiated by their template constraints, not their
instantiated constraints.

Differentiating by instantiated constraints may not be viable,
anyways. Especially, if the instantiation folds them to only "true" or
"false".

> | We still don't have nodes specific to TEMPLTAE_DECL or
> | TEMPLATE_PARM_DECL though.
>
> A tree with TREE_CODE equal to TEMPLATE_DECL or TEMPLATE_PARM_DECL is
> just that.  What we do is to use all unused- tree slots.  Or are you
> suggesting we have exhausted all available pre-defined slots on such nodes?

Unknown. I'll have to look.

But, I don't think we have a single TEMPLATE_PARM_DECL node. Template
parameters are either TYPE_DECLs or PARM_DECLs. I think auto
declarations, get VAR_DECLs, but I haven't looked closely at that
design. I'd have to look to see if there are any free tree slots all
of those decl nodes to minimize.

Andrew

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

* Re: [c++-concepts]: constraint association
  2013-06-22 18:05         ` Andrew Sutton
@ 2013-06-22 18:27           ` Gabriel Dos Reis
  2013-06-22 20:11             ` Andrew Sutton
  0 siblings, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 18:27 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches

Andrew Sutton <andrew.n.sutton@gmail.com> writes:

| > Internally, we want to always store the canonical form of a decl, not the
| > source-level form -- the current g++ AST isn't prepared for that (I wish
| > it was, but it isn't.)  This allows for simple comparison and other
| > semantics processing.
| 
| Agreed. But without some source-level annotations in the tree, I don't
| think I can generate the diagnostics that programmer's might otherwise
| expect. I'd have to emit the internal representation.

Do you have examples where we don't do or we can't do the obvious thing
in terms of diagnostics?

The source-level information has to sit above the current AST
representation; not mixed with it -- it doesn't expect and isn't
prepared for redundancy.

| >> I think we want constraints for:
| >>
| >>   * FUNCTION_DECL
| >>   * TEMPLATE_DECL
| >>   * TYPE_DECL
| >>   * TEMPLATE_PARM_DECL
| >
| > Well, thinking more about it, I believe we want it only for
| >    * TEMPLATE_DECL
| >    * TEMPLATE_PARM_DECL.
| >
| > The FUNCTION_DECL and the TYPE_DECL gets their constraints
| > from the abstract instantiation of the associated TEMPLATE_DECL.
| 
| If those constraints are cached, I don't see any other place to put
| them except in the template info.

Exactly.

| On the other hand, it seems like the only place we actually need to
| worry about is with non-template member functions.

Member function of templates are temploids, so no worry there either.
(Internally, they act and are represented like templates.)

| I think I can just grab the requirements and arguments and check them
| without caching them in the template_info.

I think we need to remember them for duplicate_decls or other routines
that either check or use ODR-derived properties.

| I'll have to experiment.
| 
| We still don't have nodes specific to TEMPLTAE_DECL or
| TEMPLATE_PARM_DECL though.

A tree with TREE_CODE equal to TEMPLATE_DECL or TEMPLATE_PARM_DECL is
just that.  What we do is to use all unused- tree slots.  Or are you
suggesting we have exhausted all available pre-defined slots on such nodes?

| It seems like lang_decl_min is the only
| place to put this where it will be avilable to both.

We have to try hard to avoid growing lang_decl_min.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  2013-06-22 17:24       ` Gabriel Dos Reis
@ 2013-06-22 18:05         ` Andrew Sutton
  2013-06-22 18:27           ` Gabriel Dos Reis
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Sutton @ 2013-06-22 18:05 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Gabriel Dos Reis, gcc-patches

> Internally, we want to always store the canonical form of a decl, not the
> source-level form -- the current g++ AST isn't prepared for that (I wish
> it was, but it isn't.)  This allows for simple comparison and other
> semantics processing.

Agreed. But without some source-level annotations in the tree, I don't
think I can generate the diagnostics that programmer's might otherwise
expect. I'd have to emit the internal representation.


>> I think we want constraints for:
>>
>>   * FUNCTION_DECL
>>   * TEMPLATE_DECL
>>   * TYPE_DECL
>>   * TEMPLATE_PARM_DECL
>
> Well, thinking more about it, I believe we want it only for
>    * TEMPLATE_DECL
>    * TEMPLATE_PARM_DECL.
>
> The FUNCTION_DECL and the TYPE_DECL gets their constraints
> from the abstract instantiation of the associated TEMPLATE_DECL.

If those constraints are cached, I don't see any other place to put
them except in the template info.

On the other hand, it seems like the only place we actually need to
worry about is with non-template member functions. I think I can just
grab the requirements and arguments and check them without caching
them in the template_info.

I'll have to experiment.

We still don't have nodes specific to TEMPLTAE_DECL or
TEMPLATE_PARM_DECL though. It seems like lang_decl_min is the only
place to put this where it will be avilable to both.

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

* Re: [c++-concepts]: constraint association
  2013-06-22 17:11     ` Gabriel Dos Reis
@ 2013-06-22 17:24       ` Gabriel Dos Reis
  2013-06-22 18:05         ` Andrew Sutton
  0 siblings, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 17:24 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Andrew Sutton, gcc-patches

On Sat, Jun 22, 2013 at 12:11 PM, Gabriel Dos Reis <gdr@axiomatics.org> wrote:
> Andrew Sutton <andrew.n.sutton@gmail.com> writes:
>
> | I the long term, I think we'll end up having constraints attached to
> | declarations wherever we constrain auto (PARM_DECL, VAR_DECL, etc).
> | Although now that I'm looking, it seems that lang_decl_parm does not
> | inherit lang_min. Hmm...
> |
> | Mostly, though, I'm not sure where I could put it where both
> | TEMPLATE_DECL and FUNCTION_DECL would have constraints.
>
> I think we want constraints for:
>
>   * FUNCTION_DECL
>   * TEMPLATE_DECL
>   * TYPE_DECL
>   * TEMPLATE_PARM_DECL

Well, thinking more about it, I believe we want it only for
   * TEMPLATE_DECL
   * TEMPLATE_PARM_DECL.

The FUNCTION_DECL and the TYPE_DECL gets their constraints
from the abstract instantiation of the associated TEMPLATE_DECL.

The comment for PARM_DECL extends to VAR_DECL -- only temploids
get constraints and non-temploid vars declared 'auto' at the source
level have types
that are TEMPLATE_TYPE_PARM, hence should get their constraints properly set.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  2013-06-22 16:56   ` Andrew Sutton
@ 2013-06-22 17:11     ` Gabriel Dos Reis
  2013-06-22 17:24       ` Gabriel Dos Reis
  0 siblings, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 17:11 UTC (permalink / raw)
  To: Andrew Sutton; +Cc: gcc-patches

Andrew Sutton <andrew.n.sutton@gmail.com> writes:

| I the long term, I think we'll end up having constraints attached to
| declarations wherever we constrain auto (PARM_DECL, VAR_DECL, etc).
| Although now that I'm looking, it seems that lang_decl_parm does not
| inherit lang_min. Hmm...
| 
| Mostly, though, I'm not sure where I could put it where both
| TEMPLATE_DECL and FUNCTION_DECL would have constraints.

I think we want constraints for:

  * FUNCTION_DECL
  * TEMPLATE_DECL
  * TYPE_DECL
  * TEMPLATE_PARM_DECL


Internally, we want to always store the canonical form of a decl, not the
source-level form -- the current g++ AST isn't prepared for that (I wish
it was, but it isn't.)  This allows for simple comparison and other
semantics processing.

When we have

    void sort(Range& r);

and Range is a unary concept, this make 'sort' a TEMPLATE_DECL.  I am
not sure we actually want to make the PARM_DECL 'r' to have a constraint.
Rather, we want the internal representation to store the canonical form:

    template<typename __T1> requires Range<__T1>
     void sort(__T1& r);

so that the PARM_DECL 'r' never gets a constraint -- it is its type that
is constrained.  This way, duplicate_decls for example won't need extensive
surgery to remain unconfused.

-- Gaby

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

* Re: [c++-concepts]: constraint association
  2013-06-22 16:41 ` Gabriel Dos Reis
@ 2013-06-22 16:56   ` Andrew Sutton
  2013-06-22 17:11     ` Gabriel Dos Reis
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Sutton @ 2013-06-22 16:56 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Gabriel Dos Reis, gcc-patches

I the long term, I think we'll end up having constraints attached to
declarations wherever we constrain auto (PARM_DECL, VAR_DECL, etc).
Although now that I'm looking, it seems that lang_decl_parm does not
inherit lang_min. Hmm...

Mostly, though, I'm not sure where I could put it where both
TEMPLATE_DECL and FUNCTION_DECL would have constraints.

On Sat, Jun 22, 2013 at 11:41 AM, Gabriel Dos Reis
<gdr@integrable-solutions.net> wrote:
> On Sat, Jun 22, 2013 at 10:57 AM, Andrew Sutton
> <andrew.n.sutton@gmail.com> wrote:
>> I changed the implementation to associate constraints with template
>> decls (actually lang_decl_min) rather than template_info.
>
> Hmm, why move it to lang_decl_min?  Now, every C++ declaration will
> have a constraint, instead of just temploids?
>
> -- Gaby



-- 
Andrew Sutton
andrew.n.sutton@gmail.com

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

* Re: [c++-concepts]: constraint association
  2013-06-22 15:57 [c++-concepts]: " Andrew Sutton
@ 2013-06-22 16:41 ` Gabriel Dos Reis
  2013-06-22 16:56   ` Andrew Sutton
  0 siblings, 1 reply; 19+ messages in thread
From: Gabriel Dos Reis @ 2013-06-22 16:41 UTC (permalink / raw)
  To: Andrew Sutton, Gabriel Dos Reis; +Cc: gcc-patches

On Sat, Jun 22, 2013 at 10:57 AM, Andrew Sutton
<andrew.n.sutton@gmail.com> wrote:
> I changed the implementation to associate constraints with template
> decls (actually lang_decl_min) rather than template_info.

Hmm, why move it to lang_decl_min?  Now, every C++ declaration will
have a constraint, instead of just temploids?

-- Gaby

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

* [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

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 --
2014-06-28 14:57 [c++-concepts] constraint association Andrew Sutton
  -- strict thread matches above, loose matches on Subject: below --
2013-06-22 15:57 [c++-concepts]: " 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

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