TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
       ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
       ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag)
+      LAMBDA_CAPTURE_EXPLICIT_P (in a TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST)
       CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
       LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
       DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
       CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR)
       OVL_HIDDEN_P (in OVERLOAD)
       SWITCH_STMT_NO_BREAK_P (in SWITCH_STMT)
+      LAMBDA_EXPR_CAPTURE_OPTIMIZED (in LAMBDA_EXPR)
    3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
       ICS_BAD_FLAG (in _CONV)
       FN_TRY_BLOCK_P (in TRY_BLOCK)
 #define LAMBDA_EXPR_MUTABLE_P(NODE) \
   TREE_LANG_FLAG_1 (LAMBDA_EXPR_CHECK (NODE))
 
+/* True iff uses of a const variable capture were optimized away.  */
+#define LAMBDA_EXPR_CAPTURE_OPTIMIZED(NODE) \
+  TREE_LANG_FLAG_2 (LAMBDA_EXPR_CHECK (NODE))
+
+/* True if this TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST is for an explicit
+   capture.  */
+#define LAMBDA_CAPTURE_EXPLICIT_P(NODE) \
+  TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE))
+
 /* The source location of the lambda.  */
 #define LAMBDA_EXPR_LOCATION(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->locus)
 extern void insert_pending_capture_proxies     (void);
 extern bool is_capture_proxy                   (tree);
 extern bool is_normal_capture_proxy             (tree);
+extern bool is_constant_capture_proxy           (tree);
 extern void register_capture_members           (tree);
 extern tree lambda_expr_this_capture            (tree, bool);
 extern void maybe_generic_this_capture         (tree, tree);
 extern tree current_nonlambda_function         (void);
 extern tree nonlambda_method_basetype          (void);
 extern tree current_nonlambda_scope            (void);
+extern tree current_lambda_expr                        (void);
 extern bool generic_lambda_fn_p                        (tree);
 extern tree do_dependent_capture               (tree, bool = false);
 extern bool lambda_fn_in_template_p            (tree);
 
          tree cap = DECL_CAPTURED_VARIABLE (expr);
          if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
              && decl_constant_var_p (cap))
-           return RECUR (cap);
+           {
+             tree val = RECUR (cap);
+             if (!is_capture_proxy (val))
+               {
+                 tree l = current_lambda_expr ();
+                 LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
+               }
+             return val;
+           }
        }
       if (outer_automatic_var_p (expr)
          && decl_constant_var_p (expr))
              tree cap = DECL_CAPTURED_VARIABLE (ref);
              if (TREE_CODE (TREE_TYPE (cap)) != REFERENCE_TYPE
                  && decl_constant_var_p (cap))
-               return RECUR (cap);
+               {
+                 tree val = RECUR (cap);
+                 if (!is_capture_proxy (val))
+                   {
+                     tree l = current_lambda_expr ();
+                     LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
+                   }
+                 return val;
+               }
            }
          tree r = mark_rvalue_use (ref, loc, reject_builtin);
          if (r != ref)
 
   return DECL_NORMAL_CAPTURE_P (val);
 }
 
+/* Returns true iff DECL is a capture proxy for a normal capture
+   of a constant variable.  */
+
+bool
+is_constant_capture_proxy (tree decl)
+{
+  if (is_normal_capture_proxy (decl))
+    return decl_constant_var_p (DECL_CAPTURED_VARIABLE (decl));
+  return false;
+}
+
 /* VAR is a capture proxy created by build_capture_proxy; add it to the
    current function, which is the operator() for the appropriate lambda.  */
 
     return build_capture_proxy (member, initializer);
   /* For explicit captures we haven't started the function yet, so we wait
      and build the proxy from cp_parser_lambda_body.  */
+  LAMBDA_CAPTURE_EXPLICIT_P (LAMBDA_EXPR_CAPTURE_LIST (lambda)) = true;
   return NULL_TREE;
 }
 
   return result;
 }
 
+/* Return the innermost LAMBDA_EXPR we're currently in, if any.  */
+
+tree
+current_lambda_expr (void)
+{
+  tree type = current_class_type;
+  while (type && !LAMBDA_TYPE_P (type))
+    type = decl_type_context (TYPE_NAME (type));
+  if (type)
+    return CLASSTYPE_LAMBDA_EXPR (type);
+  else
+    return NULL_TREE;
+}
+
 /* Return the current LAMBDA_EXPR, if this is a resolvable dummy
    object.  NULL otherwise..  */
 
   return body;
 }
 
+/* Subroutine of prune_lambda_captures: CAP is a node in
+   LAMBDA_EXPR_CAPTURE_LIST.  Return the variable it captures for which we
+   might optimize away the capture, or NULL_TREE if there is no such
+   variable.  */
+
+static tree
+var_to_maybe_prune (tree cap)
+{
+  if (LAMBDA_CAPTURE_EXPLICIT_P (cap))
+    /* Don't prune explicit captures.  */
+    return NULL_TREE;
+
+  tree mem = TREE_PURPOSE (cap);
+  if (!DECL_P (mem) || !DECL_NORMAL_CAPTURE_P (mem))
+    /* Packs and init-captures aren't captures of constant vars.  */
+    return NULL_TREE;
+
+  tree init = TREE_VALUE (cap);
+  if (is_normal_capture_proxy (init))
+    init = DECL_CAPTURED_VARIABLE (init);
+  if (decl_constant_var_p (init))
+    return init;
+
+  return NULL_TREE;
+}
+
+/* walk_tree helper for prune_lambda_captures: Remember which capture proxies
+   for constant variables are actually used in the lambda body.
+
+   There will always be a DECL_EXPR for the capture proxy; remember it when we
+   see it, but replace it with any other use.  */
+
+static tree
+mark_const_cap_r (tree *t, int *walk_subtrees, void *data)
+{
+  hash_map<tree,tree*> &const_vars = *(hash_map<tree,tree*>*)data;
+
+  tree var = NULL_TREE;
+  if (TREE_CODE (*t) == DECL_EXPR)
+    {
+      tree decl = DECL_EXPR_DECL (*t);
+      if (is_constant_capture_proxy (decl))
+       var = DECL_CAPTURED_VARIABLE (decl);
+      *walk_subtrees = 0;
+    }
+  else if (is_constant_capture_proxy (*t))
+    var = DECL_CAPTURED_VARIABLE (*t);
+
+  if (var)
+    {
+      tree *&slot = const_vars.get_or_insert (var);
+      if (!slot || VAR_P (*t))
+       slot = t;
+    }
+
+  return NULL_TREE;
+}
+
+/* We're at the end of processing a lambda; go back and remove any captures of
+   constant variables for which we've folded away all uses.  */
+
+static void
+prune_lambda_captures (tree body)
+{
+  tree lam = current_lambda_expr ();
+  if (!LAMBDA_EXPR_CAPTURE_OPTIMIZED (lam))
+    /* No uses were optimized away.  */
+    return;
+  if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_NONE)
+    /* No default captures, and we don't prune explicit captures.  */
+    return;
+
+  hash_map<tree,tree*> const_vars;
+
+  cp_walk_tree_without_duplicates (&body, mark_const_cap_r, &const_vars);
+
+  tree *fieldp = &TYPE_FIELDS (LAMBDA_EXPR_CLOSURE (lam));
+  for (tree *capp = &LAMBDA_EXPR_CAPTURE_LIST (lam); *capp; )
+    {
+      tree cap = *capp;
+      if (tree var = var_to_maybe_prune (cap))
+       {
+         tree *use = *const_vars.get (var);
+         if (TREE_CODE (*use) == DECL_EXPR)
+           {
+             /* All uses of this capture were folded away, leaving only the
+                proxy declaration.  */
+
+             /* Splice the capture out of LAMBDA_EXPR_CAPTURE_LIST.  */
+             *capp = TREE_CHAIN (cap);
+
+             /* And out of TYPE_FIELDS.  */
+             tree field = TREE_PURPOSE (cap);
+             while (*fieldp != field)
+               fieldp = &DECL_CHAIN (*fieldp);
+             *fieldp = DECL_CHAIN (*fieldp);
+
+             /* And remove the capture proxy declaration.  */
+             *use = void_node;
+             continue;
+           }
+       }
+
+      capp = &TREE_CHAIN (cap);
+    }
+}
+
 void
 finish_lambda_function (tree body)
 {
   finish_function_body (body);
 
+  prune_lambda_captures (body);
+
   /* Finish the function and generate code for it if necessary.  */
   tree fn = finish_function (/*inline_p=*/true);