Index: call.c
===================================================================
--- call.c	(revision 200584)
+++ call.c	(working copy)
@@ -8894,11 +8894,32 @@ tourney (struct z_candidate *candidates,
   return champ;
 }
 
-/* Returns nonzero if things of type FROM can be converted to TO.  */
+// Returns true if T is a reference to a function type.
+inline static bool
+is_reference_to_function_type (tree t) 
+{
+  return (TREE_CODE (t) == REFERENCE_TYPE && 
+      TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE);
+}
 
+
+// Returns true if things of type FROM can be implicitly converted to TO.
 bool
 can_convert (tree to, tree from, tsubst_flags_t complain)
 {
+  // Build an expression whose result type is FROM. If either 
+  // TO or FROM are class types, then this will cause the lookup 
+  // of user-defined conversions.
+  tree expr = build_min (CAST_EXPR, from, NULL_TREE);
+  return can_convert_arg (to, from, expr, LOOKUP_IMPLICIT, complain);
+}
+
+/* Returns nonzero if things of type FROM can be converted to TO by
+   way of a standard conversion. */
+
+bool
+can_convert_standard (tree to, tree from, tsubst_flags_t complain)
+{
   return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT, complain);
 }
 
Index: cp-tree.def
===================================================================
--- cp-tree.def	(revision 200584)
+++ cp-tree.def	(working copy)
@@ -477,6 +477,26 @@ DEFTREECODE (TEMPLATE_INFO, "template_in
 /* Used to represent information associated with constrained declarations. */
 DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0)
 
+/* A requires-expr is a binary expression. The first operand is its
+   parameter list. The second is a list of requirements. */
+DEFTREECODE (REQUIRES_EXPR,   "requires_expr", tcc_expression, 2)
+
+/* The REQ expressions are unary expressions that specify individual
+   statements in a requires clause. */
+DEFTREECODE (EXPR_REQ, "expr-req", tcc_expression, 1)
+DEFTREECODE (TYPE_REQ, "type-req", tcc_expression, 1)
+DEFTREECODE (NESTED_REQ, "nested-req", tcc_expression, 1)
+
+/* A unary expression representing a requirement for a valid expression. */
+DEFTREECODE (VALIDEXPR_EXPR, "validexpr_expr", tcc_expression, 1)
+
+/* A unary expression representing a requirement for a valid type. */
+DEFTREECODE (VALIDTYPE_EXPR, "validtype_expr", tcc_expression, 1)
+
+/* A unary expression representing a requirement for an expression that
+   can be evaluated at compile time. */
+DEFTREECODE (CONSTEXPR_EXPR, "contexpr_expr", tcc_expression, 1)
+
 /*
 Local variables:
 mode:c
Index: cp-objcp-common.c
===================================================================
--- cp-objcp-common.c	(revision 200584)
+++ cp-objcp-common.c	(working copy)
@@ -324,6 +324,14 @@ cp_common_init_ts (void)
   MARK_TS_TYPED (LAMBDA_EXPR);
   MARK_TS_TYPED (CTOR_INITIALIZER);
   MARK_TS_TYPED (ARRAY_NOTATION_REF);
+  MARK_TS_TYPED (REQUIRES_EXPR);
+  MARK_TS_TYPED (EXPR_REQ);
+  MARK_TS_TYPED (TYPE_REQ);
+  MARK_TS_TYPED (NESTED_REQ);
+  MARK_TS_TYPED (VALIDEXPR_EXPR);
+  MARK_TS_TYPED (VALIDTYPE_EXPR);
+  MARK_TS_TYPED (CONSTEXPR_EXPR);
+
 }
 
 #include "gt-cp-cp-objcp-common.h"
Index: cvt.c
===================================================================
--- cvt.c	(revision 200584)
+++ cvt.c	(working copy)
@@ -428,7 +428,7 @@ convert_to_reference (tree reftype, tree
 
   intype = TYPE_MAIN_VARIANT (intype);
 
-  can_convert_intype_to_type = can_convert (type, intype, complain);
+  can_convert_intype_to_type = can_convert_standard (type, intype, complain);
 
   if (!can_convert_intype_to_type
       && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
@@ -449,7 +449,8 @@ convert_to_reference (tree reftype, tree
 	}
     }
 
-  if (((convtype & CONV_STATIC) && can_convert (intype, type, complain))
+  if (((convtype & CONV_STATIC) && 
+          can_convert_standard (intype, type, complain))
       || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
     {
       {
Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 200584)
+++ cp-tree.h	(working copy)
@@ -5099,6 +5099,7 @@ extern tree build_op_delete_call		(enum
 						 bool, tree, tree,
 						 tsubst_flags_t);
 extern bool can_convert				(tree, tree, tsubst_flags_t);
+extern bool can_convert_standard                (tree, tree, tsubst_flags_t);
 extern bool can_convert_arg			(tree, tree, tree, int,
 						 tsubst_flags_t);
 extern bool can_convert_arg_bad			(tree, tree, tree, int,
@@ -5801,11 +5802,15 @@ extern vec<tree> cx_error_context (void)
 extern bool is_unary_trait                      (cp_trait_kind);
 extern bool is_binary_trait                     (cp_trait_kind);
 extern tree finish_requires_expr                (tree, tree);
-extern tree finish_syntax_requirement           (tree, tree, tree);
-extern tree finish_syntax_requirement           (tree);
+extern tree finish_expr_requirement             (tree, tree, tree);
+extern tree finish_expr_requirement             (tree);
 extern tree finish_type_requirement             (tree);
+extern tree finish_nested_requirement           (tree);
 extern tree finish_constexpr_requirement        (tree);
 extern tree finish_noexcept_requirement         (tree);
+extern tree finish_validexpr_expr               (tree);
+extern tree finish_validtype_epxr               (tree);
+extern tree finish_constexpr_expr               (tree);
 
 enum {
   BCS_NO_SCOPE = 1,
Index: search.c
===================================================================
--- search.c	(revision 200584)
+++ search.c	(working copy)
@@ -1890,7 +1890,7 @@ check_final_overrider (tree overrider, t
 	    }
 	}
       else if (!pedantic
-	       && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type),
+	       && can_convert_standard (TREE_TYPE (base_type), TREE_TYPE (over_type),
 			       tf_warning_or_error))
 	/* GNU extension, allow trivial pointer conversions such as
 	   converting to void *, or qualification conversion.  */
Index: typeck.c
===================================================================
--- typeck.c	(revision 200584)
+++ typeck.c	(working copy)
@@ -6277,7 +6277,7 @@ build_static_cast_1 (tree type, tree exp
       && CLASS_TYPE_P (intype)
       && (TYPE_REF_IS_RVALUE (type) || real_lvalue_p (expr))
       && DERIVED_FROM_P (intype, TREE_TYPE (type))
-      && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
+      && can_convert_standard (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
 		      build_pointer_type (TYPE_MAIN_VARIANT
 					  (TREE_TYPE (type))),
 		      complain)
@@ -6410,7 +6410,7 @@ build_static_cast_1 (tree type, tree exp
   if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
       && CLASS_TYPE_P (TREE_TYPE (type))
       && CLASS_TYPE_P (TREE_TYPE (intype))
-      && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
+      && can_convert_standard (build_pointer_type (TYPE_MAIN_VARIANT
 					  (TREE_TYPE (intype))),
 		      build_pointer_type (TYPE_MAIN_VARIANT
 					  (TREE_TYPE (type))),
@@ -6455,7 +6455,8 @@ build_static_cast_1 (tree type, tree exp
 	  t1 = intype;
 	  t2 = type;
 	}
-      if (can_convert (t1, t2, complain) || can_convert (t2, t1, complain))
+      if ((can_convert_standard (t1, t2, complain) || 
+           can_convert_standard (t2, t1, complain)))
 	{
 	  if (!c_cast_p
 	      && check_for_casting_away_constness (intype, type,
@@ -8904,7 +8905,7 @@ casts_away_constness (tree t1, tree t2,
   t1 = TYPE_MAIN_VARIANT (t1);
   t2 = TYPE_MAIN_VARIANT (t2);
   casts_away_constness_r (&t1, &t2, complain);
-  if (!can_convert (t2, t1, complain))
+  if (!can_convert_standard (t2, t1, complain))
     return true;
 
   return false;
Index: error.c
===================================================================
--- error.c	(revision 200584)
+++ error.c	(working copy)
@@ -2573,6 +2573,22 @@ dump_expr (tree t, int flags)
       pp_cxx_right_paren (cxx_pp);
       break;
 
+    case REQUIRES_EXPR:
+      pp_cxx_requires_expr (cxx_pp, t);
+      break;
+
+    case EXPR_REQ:
+      pp_cxx_expr_requirement (cxx_pp, t);
+      break;
+    
+    case TYPE_REQ:
+      pp_cxx_type_requirement (cxx_pp, t);
+      break;
+
+    case NESTED_REQ:
+      pp_cxx_nested_requirement (cxx_pp, t);
+      break;
+
       /*  This list is incomplete, but should suffice for now.
 	  It is very important that `sorry' does not call
 	  `report_error_function'.  That could cause an infinite loop.  */
Index: cxx-pretty-print.c
===================================================================
--- cxx-pretty-print.c	(revision 200584)
+++ cxx-pretty-print.c	(working copy)
@@ -464,6 +464,22 @@ pp_cxx_primary_expression (cxx_pretty_pr
       pp_cxx_offsetof_expression (pp, t);
       break;
 
+    case REQUIRES_EXPR:
+      pp_cxx_requires_expr (pp, t);
+      break;
+
+    case EXPR_REQ:
+      pp_cxx_expr_requirement (pp, t);
+      break;
+
+    case TYPE_REQ:
+      pp_cxx_type_requirement (pp, t);
+      break;
+
+    case NESTED_REQ:
+      pp_cxx_nested_requirement (pp, t);
+      break;
+
     default:
       pp_c_primary_expression (pp_c_base (pp), t);
       break;
@@ -1073,6 +1089,10 @@ pp_cxx_expression (cxx_pretty_printer *p
     case TEMPLATE_PARM_INDEX:
     case TEMPLATE_TEMPLATE_PARM:
     case STMT_EXPR:
+    case REQUIRES_EXPR:
+    case EXPR_REQ:
+    case TYPE_REQ:
+    case NESTED_REQ:
       pp_cxx_primary_expression (pp, t);
       break;
 
@@ -2437,6 +2457,176 @@ pp_cxx_trait_expression (cxx_pretty_prin
 
   pp_cxx_right_paren (pp);
 }
+
+// requirement-list:
+//    requirement
+//    requirement-list ';' requirement[opt]
+//
+// requirement:
+//    simple-requirement
+//    compound-requirement
+//    type-requirement
+//    nested-requirement
+static void
+pp_cxx_requirement_list (cxx_pretty_printer *pp, tree t)
+{
+  int n = 3;
+  while (t) {
+    pp_newline_and_indent (pp, n);
+    pp_cxx_expression (pp, TREE_VALUE (t));
+    n = 0;
+    t = TREE_CHAIN (t);
+  }
+  pp_newline_and_indent (pp, -3);
+}
+
+// requirement-body:
+//    '{' requirement-list '}'
+static void
+pp_cxx_requirement_body (cxx_pretty_printer *pp, tree t)
+{
+  pp_cxx_left_brace (pp);
+  pp_cxx_requirement_list (pp, TREE_OPERAND (t, 1));
+  pp_cxx_right_brace (pp);
+}
+
+// requirement-parameter-list:
+//    '(' parameter-declaration-clause ')'
+static void
+pp_cxx_requirement_parameter_list (cxx_pretty_printer *pp, tree t)
+{
+  tree p = TREE_OPERAND (t, 0);
+  pp_left_paren (pp);
+  while (p)
+    {
+      tree parm = TREE_VALUE (p);
+      pp_cxx_parameter_declaration (pp, parm);
+      if (!VOID_TYPE_P (TREE_VALUE (TREE_CHAIN (p))))
+        pp_separate_with (pp, ',');
+      else
+        break;
+      p = TREE_CHAIN (p);
+    }
+  pp_right_paren (pp);
+}
+
+// requires-expression:
+//    'requires' requirement-parameter-list requirement-body
+void
+pp_cxx_requires_expr (cxx_pretty_printer *pp, tree t)
+{
+  pp_cxx_ws_string (pp, "requires");
+  pp_space (pp);
+  pp_cxx_requirement_parameter_list (pp, t);
+  pp_space (pp);
+  pp_cxx_requirement_body (pp, t);
+}
+
+// constraint-specifier:
+//    noexcept
+//    constexpr
+static void
+pp_cxx_constraint_specifier (cxx_pretty_printer *pp, tree t)
+{
+  if (TREE_CODE (t) == NOEXCEPT_EXPR)
+    pp_cxx_ws_string (pp, "noexcept");
+  else if (TREE_CODE (t) == CONSTEXPR_EXPR)
+    pp_cxx_ws_string (pp, "constexpr");
+  else
+    gcc_unreachable ();
+}
+
+// compound-requirement:
+//    '{' expression '}' trailing-constraint-specifiers
+//
+// trailing-constraint-specifiers:
+//    constraint-specifiers-seq[opt] result-type-requirement[opt]
+//
+// result-type-requirement:
+//    '->' type-id
+static void
+pp_cxx_compound_requirement (cxx_pretty_printer *pp, tree t)
+{
+  // Get the expression requirement.
+  tree ereq = TREE_OPERAND (t, 0);
+
+  // Find the tree node containing the result type requirement.
+  // Note that validtype requirements are implicit.
+  tree treq = TREE_CHAIN (ereq);
+  if (TREE_CODE (TREE_VALUE (treq)) == VALIDTYPE_EXPR)
+    treq = TREE_CHAIN (treq);
+  
+  // Find tree nodes for any additional constraint specifiers.
+  tree spec1 = TREE_CHAIN (treq);
+  tree spec2 = spec1 ? TREE_CHAIN (spec1) : NULL_TREE;
+
+  // Pretty print the {expr} requirement
+  tree expr = TREE_OPERAND (TREE_VALUE (ereq), 0);
+  pp_cxx_left_brace (pp);
+  pp_cxx_expression (pp, expr);
+  pp_cxx_right_brace (pp);
+
+  // Pretty constraint specifiers, if any.
+  if (spec1)
+    {
+      pp_space (pp);
+      pp_cxx_constraint_specifier (pp, TREE_VALUE (spec1));
+      if (spec2)
+        pp_cxx_constraint_specifier (pp, TREE_VALUE (spec2));
+    }
+
+  // Pretty print the '-> type-id' part of the expression.
+  // Note that treq will contain a TRAIT_EXPR.
+  if (treq)
+    {
+      tree type = TRAIT_EXPR_TYPE2 (TREE_VALUE (treq));
+      pp_space (pp);
+      pp_cxx_arrow (pp);
+      pp_space (pp);
+      pp_cxx_type_id (pp, type);
+    }
+}
+
+// simple-requirement:
+//    expression
+static void
+pp_cxx_simple_requirement (cxx_pretty_printer *pp, tree t)
+{
+  tree req = TREE_OPERAND (t, 0);
+  pp_cxx_expression (pp, TREE_OPERAND (req, 0));
+}
+
+void
+pp_cxx_expr_requirement (cxx_pretty_printer *pp, tree t)
+{
+  tree reqs = TREE_OPERAND (t, 0);
+  if (TREE_CODE (reqs) == TREE_LIST)
+    pp_cxx_compound_requirement (pp, t);
+  else
+    pp_cxx_simple_requirement (pp, t);
+  pp_cxx_semicolon (pp);
+}
+
+// type-requirement:
+//    type-id
+void
+pp_cxx_type_requirement (cxx_pretty_printer *pp, tree t)
+{
+  tree req = TREE_OPERAND (t, 0);
+  pp_cxx_type_id (pp, TREE_OPERAND (req, 0));
+  pp_cxx_semicolon (pp);
+}
+
+// nested requirement:
+//    'requires' logical-or-expression
+void
+pp_cxx_nested_requirement (cxx_pretty_printer *pp, tree t)
+{
+  pp_cxx_ws_string (pp, "requires");
+  pp_cxx_expression (pp, TREE_OPERAND (t, 0));
+  pp_cxx_semicolon (pp);
+}
+
 
 typedef c_pretty_print_fn pp_fun;
 
Index: pt.c
===================================================================
--- pt.c	(revision 200584)
+++ pt.c	(working copy)
@@ -5904,7 +5904,7 @@ convert_nontype_argument (tree type, tre
 		 "because it is of type %qT", expr, type,
 		 TREE_TYPE (expr));
 	  /* If we are just one standard conversion off, explain.  */
-	  if (can_convert (type, TREE_TYPE (expr), complain))
+	  if (can_convert_standard (type, TREE_TYPE (expr), complain))
 	    inform (input_location,
 		    "standard conversions are not allowed in this context");
 	  return NULL_TREE;
Index: cxx-pretty-print.h
===================================================================
--- cxx-pretty-print.h	(revision 200584)
+++ cxx-pretty-print.h	(working copy)
@@ -76,6 +76,10 @@ void pp_cxx_trait_expression (cxx_pretty
 void pp_cxx_va_arg_expression (cxx_pretty_printer *, tree);
 void pp_cxx_offsetof_expression (cxx_pretty_printer *, tree);
 void pp_cxx_userdef_literal (cxx_pretty_printer *, tree);
+void pp_cxx_requires_expr (cxx_pretty_printer *, tree);
+void pp_cxx_expr_requirement (cxx_pretty_printer *, tree);
+void pp_cxx_type_requirement (cxx_pretty_printer *, tree);
+void pp_cxx_nested_requirement (cxx_pretty_printer *, tree);
 
 
 #endif /* GCC_CXX_PRETTY_PRINT_H */
Index: semantics.c
===================================================================
--- semantics.c	(revision 200584)
+++ semantics.c	(working copy)
@@ -5560,6 +5560,18 @@ is_binary_trait (cp_trait_kind k)
   return !is_unary_trait (k);
 }
 
+// Returns a type that suitable to be used as an rvalue of type T.
+// Except for function types, this is the same as T. For function
+// types, this is an rvalue reference to T.
+tree
+rvalue_result_type (tree t) 
+{
+  if (TREE_CODE (t) == FUNCTION_TYPE)
+    return cp_build_reference_type(t, true);
+  else
+    return t;
+}
+
 /* Actually evaluates the trait.  */
 
 static bool
@@ -5635,8 +5647,7 @@ trait_expr_value (cp_trait_kind kind, tr
       return (NON_UNION_CLASS_TYPE_P (type1));
 
     case CPTK_IS_CONVERTIBLE_TO:
-      /* TODO  */
-      return false;
+      return can_convert (type2, rvalue_result_type (type1), tf_none);
 
     case CPTK_IS_EMPTY:
       return (NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1));
@@ -5714,12 +5725,6 @@ finish_trait_expr (cp_trait_kind kind, t
 	      || kind == CPTK_IS_TRIVIAL
 	      || kind == CPTK_IS_UNION);
 
-  if (kind == CPTK_IS_CONVERTIBLE_TO)
-    {
-      sorry ("__is_convertible_to");
-      return error_mark_node;
-    }
-
   if (type1 == error_mark_node 
       || (is_binary_trait (kind) && type2 == error_mark_node))
     return error_mark_node;
@@ -5770,6 +5775,8 @@ finish_trait_expr (cp_trait_kind kind, t
       break;
     
     case CPTK_IS_CONVERTIBLE_TO:
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -10014,41 +10021,118 @@ finish_template_requirements (tree expr)
     return make_constraints (expr);
 }
 
-// TODO: Implement semantics for requires expressions.
+// Finish a requires expression, returning a node wrapping the parameters,
+// PARMS, and the list of requirements REQS.
 tree
-finish_requires_expr (tree, tree)
+finish_requires_expr (tree parms, tree reqs)
 {
-  return NULL_TREE;
+  // Modify the declared parameters by removing their context (so they
+  // don't refer to the enclosing scope), and marking them constant (so
+  // we can actually check constexpr properties).
+  for (tree p = parms; p && !VOID_TYPE_P (TREE_VALUE (p)); p = TREE_CHAIN (p))
+    {
+      tree parm = TREE_VALUE (p);
+      DECL_CONTEXT (parm) = NULL_TREE;
+      TREE_CONSTANT (parm) = true;
+    }
+
+    // Build the node.
+  tree r = build_min (REQUIRES_EXPR, boolean_type_node, parms, reqs);
+  TREE_SIDE_EFFECTS (r) = false;
+  TREE_CONSTANT (r) = true;
+  return r;
 }
 
-// TODO: Implement syntax requirements.
+// Construct a unary expression that evaluates properties of the
+// expression or type T, and has a boolean result type.
+static inline tree
+build_check_expr (tree_code c, tree t)
+{
+  tree r = build_min (c, boolean_type_node, t);
+  TREE_SIDE_EFFECTS (r) = false;
+  TREE_READONLY (r) = true;
+  TREE_CONSTANT (r) = true;
+  return r;
+}
+
+// Finish a syntax requirement, constructing a list embodying a sequence
+// of checks for the validity of EXPR and TYPE, the convertibility of
+// EXPR to TYPE, and the expression properties specified in SPECS.
 tree
-finish_syntax_requirement (tree, tree, tree)
+finish_expr_requirement (tree expr, tree type, tree specs)
 {
-  return NULL_TREE;
+  gcc_assert (processing_template_decl);
+
+  // Build a list of checks, starting with the valid expression.
+  tree result = tree_cons (NULL_TREE, finish_validexpr_expr (expr), NULL_TREE);
+
+  // If a type requirement was provided, build the result type checks.
+  if (type)
+    {
+      // If the type is dependent, ensure that it can be validly
+      // instantiated.
+      //
+      // NOTE: We can also disregard checks that result in the template
+      // parameter.
+      if (dependent_type_p (type))
+        {
+          tree treq = finish_type_requirement (type);
+          result = tree_cons (NULL_TREE, treq, result);
+        }
+
+      // Ensure that the result of the expression can be converted to
+      // the result type.
+      tree decl_type = finish_decltype_type (expr, false, tf_none);
+      tree creq = finish_trait_expr (CPTK_IS_CONVERTIBLE_TO, decl_type, type);
+      result = tree_cons (NULL_TREE, creq, result);
+    }
+
+  // If constraint specifiers are present, make them part of the
+  // list of constraints.
+  if (specs)
+    {
+      TREE_CHAIN (tree_last (specs)) = result;
+      result = specs;
+    }
+
+  // Finally, construct the syntactic requirement.
+  return build_check_expr (EXPR_REQ, nreverse (result));
 }
 
-// Finish the simple syntax requirement by constructing a new
-// syntax requirement that has no result type requirements nor
-// constraint specifiers.
+// Finish a simple syntax requirement, returning a node representing
+// a check that EXPR is a valid expression.
 tree
-finish_syntax_requirement (tree expr)
+finish_expr_requirement (tree expr)
 {
-  return finish_syntax_requirement (expr, NULL_TREE, NULL_TREE);
+  gcc_assert (processing_template_decl);
+  tree req = finish_validexpr_expr (expr);
+  return build_check_expr (EXPR_REQ, req);
 }
 
-// TODO: Implement type requirements.
+// Finish a type requirement, returning a node representing a check
+// that TYPE will result in a valid type when instantiated.
 tree
-finish_type_requirement (tree)
+finish_type_requirement (tree type)
 {
-  return NULL_TREE;
+  gcc_assert (processing_template_decl);
+  tree req = finish_validtype_epxr (type);
+  return build_check_expr (TYPE_REQ, req);
 }
 
-// TODO: Implement constexpr requirements.
 tree
-finish_constexpr_requirement (tree)
+finish_nested_requirement (tree expr)
 {
-  return NULL_TREE;
+  gcc_assert (processing_template_decl);
+  return build_check_expr (NESTED_REQ, expr);
+}
+
+// Finish a constexpr requirement, returning a node representing a
+// check that EXPR, when instantiated, may be evaluated at compile time.
+tree
+finish_constexpr_requirement (tree expr)
+{
+  gcc_assert (processing_template_decl);
+  return finish_constexpr_expr (expr);
 }
 
 // Finish the noexcept requirement by constructing a noexcept 
@@ -10056,9 +10140,63 @@ finish_constexpr_requirement (tree)
 tree
 finish_noexcept_requirement (tree expr)
 {
+  gcc_assert (processing_template_decl);
   return finish_noexcept_expr (expr, tf_none);
 }
 
+// Returns the true or false node depending on the truth value of B.
+static inline tree
+truth_node (bool b)
+{
+  return b ? boolean_true_node : boolean_false_node;
+}
+
+// Returns a finished validexpr-expr. Returns the true or false node
+// depending on whether EXPR denotes a valid expression. This is the case
+// when the expression has been successfully type checked.
+//
+// When processing a template declaration, the result is an expression 
+// representing the check.
+tree
+finish_validexpr_expr (tree expr)
+{
+  if (processing_template_decl)
+    return build_check_expr (VALIDEXPR_EXPR, expr);
+  return truth_node (expr && expr != error_mark_node);
+}
+
+// Returns a finished validtype-expr. Returns the true or false node
+// depending on whether T denotes a valid type name.
+//
+// When processing a template declaration, the result is an expression 
+// representing the check.
+tree
+finish_validtype_epxr (tree type)
+{
+  if (processing_template_decl)
+    return build_check_expr (VALIDTYPE_EXPR, type);
+  return truth_node (type && TYPE_P (type));
+}
+
+// Returns a finished constexpr-expr. Returns the true or false node
+// depending on whether the expression T may be evaluated at compile
+// time.
+//
+// When processing a template declaration, the result is an expression 
+// representing the check.
+tree
+finish_constexpr_expr (tree expr)
+{
+  if (processing_template_decl)
+    return build_check_expr (CONSTEXPR_EXPR, expr);
+
+  // TODO: Actually check that the expression can be constexpr
+  // evaluatd. 
+  // 
+  // return truth_node (potential_constant_expression (expr));
+  sorry ("constexpr requirement");
+  return NULL_TREE;
+}
 
 
 #include "gt-cp-semantics.h"
Index: parser.c
===================================================================
--- parser.c	(revision 200584)
+++ parser.c	(working copy)
@@ -2216,9 +2216,9 @@ static tree cp_parser_requires_clause_op
   (cp_parser *);
 static tree cp_parser_requires_expression
   (cp_parser *);
-static tree cp_parser_requires_expression_parameter_list
+static tree cp_parser_requirement_parameter_list
   (cp_parser *);
-static tree cp_parser_requires_expression_body
+static tree cp_parser_requirement_body
   (cp_parser *);
 static tree cp_parser_requirement_list
   (cp_parser *);
@@ -2226,7 +2226,7 @@ static tree cp_parser_requirement
   (cp_parser *);
 static tree cp_parser_simple_requirement
   (cp_parser *);
-static tree cp_parser_syntax_requirement
+static tree cp_parser_compound_requirement
   (cp_parser *);
 static tree cp_parser_type_requirement
   (cp_parser *);
@@ -21751,10 +21751,30 @@ cp_parser_requires_clause_opt (cp_parser
 // -------------------------------------------------------------------------- //
 // Requires Expression
 
+
+// An RAII helper that provides scoped control for entering and exiting 
+// the local scope defined by a requires expression. Name bindings introduced 
+// within the scope are popped prior to exiting the scope.
+struct cp_parser_requires_expr_scope
+{
+  // Enter a scope of kind K belonging to the decl D. 
+  cp_parser_requires_expr_scope ()
+  {
+    begin_scope (sk_block, NULL_TREE);
+  }
+
+  ~cp_parser_requires_expr_scope ()
+  {
+    for (tree t = current_binding_level->names; t; t = DECL_CHAIN (t))
+      pop_binding (DECL_NAME (t), t);
+    leave_scope ();
+  }
+};
+
 // Parse a requires expression
 //
 //    requirement-expression:
-//        'requires' requirement-parameter-list[opt] requirement-body
+//        'requires' requirement-parameter-list requirement-body
 static tree
 cp_parser_requires_expression (cp_parser *parser)
 {
@@ -21764,13 +21784,16 @@ cp_parser_requires_expression (cp_parser
   // TODO: Check that requires expressions are only written inside of
   // template declarations. They don't need to be concepts, just templates.
 
-  // Parse the optional parameter list.
-  tree parms = cp_parser_requires_expression_parameter_list (parser);
+  // Parse the optional parameter list. Any local parameter declarations
+  // are added to a new scope and are visible within the nested 
+  // requirement list.
+  cp_parser_requires_expr_scope guard;
+  tree parms = cp_parser_requirement_parameter_list (parser);
   if (parms == error_mark_node)
     return error_mark_node;
 
   // Parse the requirement body.
-  tree reqs = cp_parser_requires_expression_body (parser);
+  tree reqs = cp_parser_requirement_body (parser);
   if (reqs == error_mark_node)
     return error_mark_node;
 
@@ -21782,7 +21805,7 @@ cp_parser_requires_expression (cp_parser
 //    requirement-parameter-list:
 //        '(' parameter-declaration-clause ')'
 static tree
-cp_parser_requires_expression_parameter_list (cp_parser *parser)
+cp_parser_requirement_parameter_list (cp_parser *parser)
 {
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return error_mark_node;
@@ -21803,7 +21826,7 @@ cp_parser_requires_expression_parameter_
 //    requirement-body:
 //        '{' requirement-list '}'
 static tree
-cp_parser_requires_expression_body (cp_parser *parser)
+cp_parser_requirement_body (cp_parser *parser)
 {
   if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
     return error_mark_node;
@@ -21820,7 +21843,7 @@ cp_parser_requires_expression_body (cp_p
 //
 //    requirement-list:
 //        requirement
-//        requirement-list ';' requirement[opt]static tree
+//        requirement-list ';' requirement[opt]
 static tree
 cp_parser_requirement_list (cp_parser *parser)
 {
@@ -21852,7 +21875,7 @@ cp_parser_requirement_list (cp_parser *p
 //
 //    requirement:
 //        simple-requirement
-//        syntax-requirement
+//        compound-requirement
 //        type-requirement
 //        nested-requirement
 static tree
@@ -21862,20 +21885,13 @@ cp_parser_requirement (cp_parser *parser
     return cp_parser_nested_requirement (parser);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-    return cp_parser_syntax_requirement (parser);
+    return cp_parser_compound_requirement (parser);
 
   // Try parsing a type requirement first.
   cp_parser_parse_tentatively (parser);
   tree req = cp_parser_type_requirement (parser);
-  if (req == error_mark_node)
-    cp_parser_abort_tentative_parse (parser);
-  else
-    cp_parser_commit_to_tentative_parse (parser);
-
-  // If that failed, then we must have a simple requirement.
-  if (req == error_mark_node)
+  if (!cp_parser_parse_definitely (parser))
     req = cp_parser_simple_requirement (parser);
-
   return req;
 }
 
@@ -21887,7 +21903,10 @@ static tree
 cp_parser_nested_requirement (cp_parser *parser)
 {
   cp_lexer_consume_token (parser->lexer);
-  return cp_parser_requires_clause (parser);
+  tree req = cp_parser_requires_clause (parser);
+  if (req == error_mark_node)
+    return error_mark_node;
+  return finish_nested_requirement (req);
 }
 
 // Parse a simple requirement.
@@ -21900,12 +21919,12 @@ cp_parser_simple_requirement (cp_parser
   tree expr = cp_parser_expression (parser, false, false, NULL);
   if (!expr || expr == error_mark_node)
     return error_mark_node;
-  return finish_syntax_requirement (expr);
+  return finish_expr_requirement (expr);
 }
 
-// Parse a syntax requirement
+// Parse a compound requirement
 //
-//    syntax-requirement:
+//    compound-requirement:
 //        '{' expression '}' trailing-constraint-specifiers
 //
 //    trailing-constraint-specifiers:
@@ -21914,7 +21933,7 @@ cp_parser_simple_requirement (cp_parser
 //    result-type-requirement:
 //       '->' type-id
 static tree
-cp_parser_syntax_requirement (cp_parser *parser)
+cp_parser_compound_requirement (cp_parser *parser)
 {
   // Parse an expression enclosed in '{ }'s.
   if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
@@ -21935,12 +21954,12 @@ cp_parser_syntax_requirement (cp_parser
   if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
     {
       cp_lexer_consume_token (parser->lexer);
-      type = cp_parser_type_id (parser);
+      type = cp_parser_trailing_type_id (parser);
       if (type == error_mark_node)
         return error_mark_node;
     }
 
-  return finish_syntax_requirement (expr, type, cs);
+  return finish_expr_requirement (expr, type, cs);
 }
 
 // Parse a type requirement
@@ -21972,8 +21991,7 @@ static tree
 cp_parser_constexpr_constraint_spec (cp_parser *parser, tree expr)
 {
   cp_lexer_consume_token (parser->lexer);
-  return NULL_TREE;
-  // return finish_constexpr_requirement (expr);
+  return finish_constexpr_requirement (expr);
 }
 
 // Parse an optional noexcept specifier in a constraint expression.
@@ -21981,8 +21999,7 @@ static tree
 cp_parser_noexcept_constraint_spec (cp_parser *parser, tree expr)
 {
   cp_lexer_consume_token (parser->lexer);
-  return NULL_TREE;
-  // return finish_noexcept_requirement (expr);
+  return finish_noexcept_requirement (expr);
 }
 
 static tree
