Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 197414)
+++ cp-tree.h	(working copy)
@@ -43,6 +43,18 @@ c-common.h, not after.
 
 #include "name-lookup.h"
 
+
+// Require that pointer P is non-null before returning.
+template<typename T>
+inline T*
+require (T* p)
+{
+  gcc_assert (p);
+  return p;
+}
+
+
+
 /* Usage of TREE_LANG_FLAG_?:
    0: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
       NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
@@ -770,6 +782,25 @@ struct GTY(()) tree_template_info {
   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
+   (as a list of lists). */
+struct GTY(()) tree_constraint_info {
+  struct tree_base base;
+  tree requirements;
+  tree assumptions;
+};
+
+// Returns true iff T is non-null and represents constraint info.
+inline tree_constraint_info *
+constraint_info_p (tree t)
+{
+  if (TREE_CODE (t) == CONSTRAINT_INFO)
+    return (tree_constraint_info *)t;
+  return NULL;
+}
+
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
   TS_CP_IDENTIFIER,
@@ -786,6 +817,7 @@ enum cp_tree_node_structure_enum {
   TS_CP_TRAIT_EXPR,
   TS_CP_LAMBDA_EXPR,
   TS_CP_TEMPLATE_INFO,
+  TS_CP_CONSTRAINT_INFO,
   TS_CP_USERDEF_LITERAL,
   LAST_TS_CP_ENUM
 };
@@ -812,6 +844,8 @@ union GTY((desc ("cp_tree_node_structure
     lambda_expression;
   struct tree_template_info GTY ((tag ("TS_CP_TEMPLATE_INFO")))
     template_info;
+  struct tree_constraint_info GTY ((tag ("TS_CP_CONSTRAINT_INFO")))
+    constraint_info;
   struct tree_userdef_literal GTY ((tag ("TS_CP_USERDEF_LITERAL")))
     userdef_literal;
 };
@@ -2042,6 +2076,11 @@ struct GTY((variable_size)) lang_decl {
     struct lang_decl_ns GTY((tag ("2"))) ns;
     struct lang_decl_parm GTY((tag ("3"))) parm;
   } u;
+
+  /* A declaration can be constrained. The constraint_info field is
+     a subtree containing data for constraints. This includes 
+     the constraint expression, and decomposed requirements. */
+  tree constraint_info;
 };
 
 /* Looks through a template (if present) to find what it declares.  */
@@ -2866,6 +2905,23 @@ extern void decl_shadowed_for_var_insert
    the class definition is complete.  */
 #define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
 
+
+// Returns true if D is a constrained declaration.
+inline tree
+decl_constrained_p (tree d)
+{
+  if (struct lang_decl *l = DECL_LANG_SPECIFIC (d))
+    return l->constraint_info;
+  return NULL_TREE;
+}
+
+// Returns a reference to D's constraint information.
+inline tree&
+decl_constraints (tree d)
+{
+  return require (DECL_LANG_SPECIFIC (d))->constraint_info;
+}
+
 /* Determine if a parameter (i.e., a PARM_DECL) is a function
    parameter pack.  */
 #define FUNCTION_PARAMETER_PACK_P(NODE) \
@@ -6091,7 +6147,7 @@ extern tree strip_using_decl
 extern tree conjoin_requirements                (tree, tree);
 extern tree disjoin_requirements                (tree, tree);
 extern tree reduce_requirements                 (tree);
-
+extern tree make_constraints                    (tree);
 
 /* -- end of C++ */
 
Index: semantics.c
===================================================================
--- semantics.c	(revision 197414)
+++ semantics.c	(working copy)
@@ -2533,6 +2533,7 @@ finish_template_template_parm (tree aggr
 			  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;
   end_template_decl ();
@@ -9816,13 +9817,18 @@ finish_template_requirements (tree expre
   if (expression == error_mark_node)
     return NULL_TREE;
 
-  tree reduced = reduce_requirements (expression);
-  
-  // TODO: Perform an initial left/right decomposition on the
-  // reduced requirements.
+  // Reduce the requirements into atoms.
+  tree reqs = reduce_requirements (expression);
+  if (reqs == error_mark_node)
+    return error_mark_node;
 
-  sorry ("no template requirements yet");
-  return NULL_TREE;
+  // If there are current constraitns, join them with the 
+  // newly reduced requirements.
+  if (current_template_reqs)
+    if (tree_constraint_info *cinfo = constraint_info_p (current_template_reqs))
+      reqs = conjoin_requirements (cinfo->requirements, reqs);
+
+  return make_constraints (reqs);
 }
 
 #include "gt-cp-semantics.h"
Index: cp-tree.def
===================================================================
--- cp-tree.def	(revision 197414)
+++ cp-tree.def	(working copy)
@@ -472,6 +472,13 @@ DEFTREECODE (BASES, "bases", tcc_type, 0
    instantiation time.  */
 DEFTREECODE (TEMPLATE_INFO, "template_info", tcc_exceptional, 0)
 
+
+/* Concepts. */
+
+/* Used to represent information associated with constrained
+   declarations. */
+DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0)
+
 /*
 Local variables:
 mode:c
Index: pt.c
===================================================================
--- pt.c	(revision 197414)
+++ pt.c	(working copy)
@@ -3948,14 +3948,14 @@ maybe_update_decl_type (tree orig_type,
    a member template.  Used by push_template_decl below.  */
 
 static tree
-build_template_decl (tree decl, tree parms, bool member_template_p)
+build_template_decl (tree decl, tree parms, tree reqs, bool member_template_p)
 {
   tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = parms;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
-
+  decl_constraints (tmpl) = reqs;
   return tmpl;
 }
 
@@ -4708,7 +4708,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;
 
@@ -4752,7 +4754,9 @@ push_template_decl_real (tree decl, bool
 	  args = DECL_TI_ARGS (decl);
 
 	  new_tmpl
-	    = build_template_decl (decl, current_template_parms,
+	    = 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);
@@ -4917,7 +4921,7 @@ 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);
   DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
   TREE_TYPE (tmpl) = TREE_TYPE (fn);
Index: decl.c
===================================================================
--- decl.c	(revision 197414)
+++ decl.c	(working copy)
@@ -14265,6 +14265,7 @@ cp_tree_node_structure (union lang_tree_
     case TRAIT_EXPR:		return TS_CP_TRAIT_EXPR;
     case LAMBDA_EXPR:		return TS_CP_LAMBDA_EXPR;
     case TEMPLATE_INFO:		return TS_CP_TEMPLATE_INFO;
+    case CONSTRAINT_INFO:       return TS_CP_CONSTRAINT_INFO;
     case USERDEF_LITERAL:	return TS_CP_USERDEF_LITERAL;
     default:			return TS_CP_GENERIC;
     }
Index: constraint.cc
===================================================================
--- constraint.cc	(revision 197414)
+++ constraint.cc	(working copy)
@@ -52,14 +52,26 @@ along with GCC; see the file COPYING3.
 // more flexible (i.e., allow some form of overload resolution?).
 
 
+// Create a new logical node joining the subexpressions a and b.
+static inline tree
+join_requirements (tree_code c, tree a, tree b)
+{
+  gcc_assert (a != NULL_TREE && b != NULL_TREE);
+  gcc_assert (c == TRUTH_ANDIF_EXPR || c == TRUTH_ORIF_EXPR);
+  return build_min (c, boolean_type_node, a, b);
+}
+
+
 // Returns the conjunction of two requirements A and B, where A and B are
 // reduced terms in the constraints languaage. Returns NULL_TREE if either A or
 // B are NULL_TREE.
 tree
 conjoin_requirements (tree a, tree b)
 {
-  if (a && b)
-    return build_min (TRUTH_ANDIF_EXPR, boolean_type_node, a, b);
+  if (a)
+    return b ?  join_requirements (TRUTH_ANDIF_EXPR, a, b) : a;
+  else if (b)
+    return b;
   else
     return NULL_TREE;
 }
@@ -70,8 +82,10 @@ conjoin_requirements (tree a, tree b)
 tree
 disjoin_requirements (tree a, tree b)
 {
-  if (a && b)
-    return build_min (TRUTH_ORIF_EXPR, boolean_type_node, a, b);
+  if (a)
+    return b ?  join_requirements (TRUTH_ORIF_EXPR, a, b) : a;
+  else if (b)
+    return b;
   else
     return NULL_TREE;
 }
@@ -448,3 +462,15 @@ reduce_requirements (tree reqs)
 {
   return reduce_node (reqs);
 }
+
+
+// Create a constraint-info node from the specified requirements.
+tree 
+make_constraints (tree reqs)
+{
+  tree_constraint_info *cinfo = 
+    (tree_constraint_info *)make_node (CONSTRAINT_INFO);
+  cinfo->requirements = reqs;
+  cinfo->assumptions = NULL_TREE;
+  return (tree)cinfo;
+}
Index: ptree.c
===================================================================
--- ptree.c	(revision 197414)
+++ ptree.c	(working copy)
@@ -39,6 +39,12 @@ cxx_print_decl (FILE *file, tree node, i
       return;
     }
 
+  if (tree cons = decl_constraints (node))
+    {
+      indent_to (file, indent + 3);
+      cxx_print_xnode (file, cons, indent);
+    }
+
   if (!CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON)
       || !DECL_LANG_SPECIFIC (node))
     return;
@@ -223,6 +229,13 @@ cxx_print_xnode (FILE *file, tree node,
 	  fprintf (file, "pending_template");
 	}
       break;
+    case CONSTRAINT_INFO:
+      {
+        tree_constraint_info *cinfo = (tree_constraint_info *)node;
+        print_node (file, "requirements", cinfo->requirements, indent+4);
+        print_node_brief (file, "assumptions", cinfo->assumptions, indent+4);
+        break;
+      }
     case ARGUMENT_PACK_SELECT:
       print_node (file, "pack", ARGUMENT_PACK_SELECT_FROM_PACK (node),
 		  indent+4);
Index: cp-objcp-common.c
===================================================================
--- cp-objcp-common.c	(revision 197414)
+++ cp-objcp-common.c	(working copy)
@@ -99,6 +99,8 @@ cp_tree_size (enum tree_code code)
 
     case TEMPLATE_INFO:         return sizeof (struct tree_template_info);
 
+    case CONSTRAINT_INFO:       return sizeof (struct tree_constraint_info);
+
     case USERDEF_LITERAL:	return sizeof (struct tree_userdef_literal);
 
     default:
