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