On Tue, May 19, 2026 at 11:26:55AM -0400, Patrick Palka wrote:
> On Tue, 19 May 2026, Marek Polacek wrote:
> 
> > On Tue, May 19, 2026 at 08:30:50AM -0400, Patrick Palka wrote:
> > > On Mon, 18 May 2026, Marek Polacek wrote:
> > > 
> > > > On Mon, May 18, 2026 at 09:34:23AM -0400, Patrick Palka wrote:
> > > > > On Fri, 15 May 2026, Marek Polacek wrote:
> > > > > 
> > > > > > On Thu, May 14, 2026 at 09:50:52PM -0400, Patrick Palka wrote:
> > > > > > > On Thu, 14 May 2026, Marek Polacek wrote:
> > > > > > > 
> > > > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for 
> > > > > > > > trunk/16.2?
> > > > > > > > 
> > > > > > > > -- >8 --
> > > > > > > > Thanks to DR 696 (r253266), this works:
> > > > > > > > 
> > > > > > > >   int g;
> > > > > > > >   void fn ()
> > > > > > > >   {
> > > > > > > >     int &c = g;
> > > > > > > >     auto l = [] { c++; };
> > > > > > > >     l();
> > > > > > > >   }
> > > > > > > > 
> > > > > > > > because `c` in the lambda body is not an odr-use because we can
> > > > > > > > evaluate it to a constant and so there's no capture.  But when
> > > > > > > > fn is a template, we reject the code and crash.  This patch 
> > > > > > > > fixes
> > > > > > > > both.
> > > > > > > > 
> > > > > > > > Outside a template, the call to maybe_constant_value in mark_use
> > > > > > > > evaluates `c` to `(int&) &g` but in a template, it remains `c`.
> > > > > > > > Then we emit an error, and crash on the error_mark_node from
> > > > > > > > process_outer_var_ref.  One of the reasons is
> > > > > > > >       else if (TYPE_REF_P (TREE_TYPE (expression)))
> > > > > > > >         /* FIXME cp_finish_decl doesn't fold reference 
> > > > > > > > initializers.  */
> > > > > > > >         return true;
> > > > > > > > in value_dependent_expression_p but even if that changed, we 
> > > > > > > > still
> > > > > > > > wouldn't get the referent because decl_really_constant_value 
> > > > > > > > wouldn't
> > > > > > > > give it to us; the DECL_INITIAL is not a TREE_CONSTANT yet.
> > > > > > > > 
> > > > > > > > So I stopped trying to make this work in a template, and instead
> > > > > > > > I'm delaying the processing to instantiating when we know that
> > > > > > > > maybe_constant_value wouldn't even try to evaluate.
> > > > > > > 
> > > > > > > It seems with this patch we still incorrectly reject the case 
> > > > > > > where the outer
> > > > > > > local variable is initially type-dependent (not a regression):
> > > > > > > 
> > > > > > >     int g;
> > > > > > > 
> > > > > > >     template<class T>
> > > > > > >     void
> > > > > > >     fn1 ()
> > > > > > >     {
> > > > > > >       T c = g;
> > > > > > >       auto l = [] { c++; }; // bogus error: 'c' is not captured
> > > > > > >       l();
> > > > > > >     }
> > > > > > > 
> > > > > > >     void
> > > > > > >     bar ()
> > > > > > >     {
> > > > > > >       fn1<int&> ();
> > > > > > >     }
> > > > > > > 
> > > > > > > via process_outer_var_ref, this time called from 
> > > > > > > finish_id_expression_1.
> > > > > > > Maybe we can make both testcases work if we instead give 
> > > > > > > process_outer_var_ref
> > > > > > > an early exit for when the outer variable is from a template?
> > > > > > 
> > > > > > Thanks for that testcase; I hadn't considered it.
> > > > > > 
> > > > > > What do y'all think about this approach, then?  I think we want the 
> > > > > > new
> > > > > > check only after checking !odr_use && decl_constant_var_p.
> > > > > > 
> > > > > > dg.exp passed thus far.
> > > > > > 
> > > > > > -- >8 --
> > > > > > Thanks to DR 696 (r253266), this works:
> > > > > > 
> > > > > >   int g;
> > > > > >   void fn ()
> > > > > >   {
> > > > > >     int &c = g;
> > > > > >     auto l = [] { c++; };
> > > > > >     l();
> > > > > >   }
> > > > > > 
> > > > > > because `c` in the lambda body is not an odr-use because we can
> > > > > > evaluate it to a constant and so there's no capture.  But when
> > > > > > fn is a template, we reject the code and crash.  This patch fixes
> > > > > > both.
> > > > > > 
> > > > > > Outside a template, the call to maybe_constant_value in mark_use
> > > > > > evaluates `c` to `(int&) &g` but in a template, it remains `c`.
> > > > > > Then we emit an error, and crash on the error_mark_node from
> > > > > > process_outer_var_ref.  One of the reasons is
> > > > > >       else if (TYPE_REF_P (TREE_TYPE (expression)))
> > > > > >         /* FIXME cp_finish_decl doesn't fold reference 
> > > > > > initializers.  */
> > > > > >         return true;
> > > > > > in value_dependent_expression_p but even if that changed, we still
> > > > > > wouldn't get the referent because decl_really_constant_value 
> > > > > > wouldn't
> > > > > > give it to us; the DECL_INITIAL is not a TREE_CONSTANT yet.
> > > > > > 
> > > > > > So I stopped trying to make this work in a template, and instead
> > > > > > I'm deferring the error in process_outer_var_ref to instantiation
> > > > > > when it's instantiation-dependent.
> > > > > > 
> > > > > >     PR c++/123536
> > > > > > 
> > > > > > gcc/cp/ChangeLog:
> > > > > > 
> > > > > >     * semantics.cc (process_outer_var_ref): Return decl when it is
> > > > > >     instantiation-dependent.
> > > > > > 
> > > > > > gcc/testsuite/ChangeLog:
> > > > > > 
> > > > > >     * g++.dg/cpp0x/lambda/lambda-const12.C: New test.
> > > > > >     * g++.dg/cpp0x/lambda/lambda-const13.C: New test.
> > > > > > ---
> > > > > >  gcc/cp/semantics.cc                           |  5 ++
> > > > > >  .../g++.dg/cpp0x/lambda/lambda-const12.C      | 48 
> > > > > > +++++++++++++++++++
> > > > > >  .../g++.dg/cpp0x/lambda/lambda-const13.C      | 19 ++++++++
> > > > > >  3 files changed, 72 insertions(+)
> > > > > >  create mode 100644 
> > > > > > gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C
> > > > > >  create mode 100644 
> > > > > > gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C
> > > > > > 
> > > > > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > > > > > index 6564d9e37a6..201519ef411 100644
> > > > > > --- a/gcc/cp/semantics.cc
> > > > > > +++ b/gcc/cp/semantics.cc
> > > > > > @@ -4699,6 +4699,11 @@ process_outer_var_ref (tree decl, 
> > > > > > tsubst_flags_t complain, bool odr_use)
> > > > > >      return var;
> > > > > >    else if (lambda_expr)
> > > > > >      {
> > > > > > +      /* Don't complain when DECL is dependent, because it can 
> > > > > > turn out to
> > > > > > +    be constant (and therefore needing no capture) when 
> > > > > > instantiating.  */
> > > > > > +      if (instantiation_dependent_expression_p (decl))
> > > > > > +   return decl;
> > > > > > +
> > > > > 
> > > > > Presumably we also want to accept the nested class version of
> > > > > lambda-const13.C:
> > > > > 
> > > > >     int g;
> > > > > 
> > > > >     template<class T>
> > > > >     void
> > > > >     fn1 ()
> > > > >     {
> > > > >       T c = g;
> > > > >       struct A { static void f() { c++; } };
> > > > >       A::f();
> > > > >     }
> > > > > 
> > > > >     void
> > > > >     bar ()
> > > > >     {
> > > > >       fn1<int&> ();
> > > > >     }
> > > > > 
> > > > > 
> > > > > So the early exit should be independent of whether we're inside a
> > > > > lambda.
> > > > 
> > > > Oop, yes.  I moved the check up and also added VAR_P because
> > > > I *think* for PARM_DECLs we don't need/want that i_d_e_p check.
> > > > Without it pr57416.C regresses its diagnostic a bit.
> > > >  
> > > > > Does instantiation_dependent_expression_p work for:
> > > > > 
> > > > >     template<class T>
> > > > >     void
> > > > >     fn2 ()
> > > > >     {
> > > > >       int& c = T::static_data_member;  // not marked constant at 
> > > > > parse time
> > > > >       auto l = [] { c++; };
> > > > >       l();
> > > > >     }
> > > > 
> > > > It does seem to work.  I discovered a crash on invalid when trying
> > > > out this test, thus the mark_use hunk.  Tested in lambda-const14.C.
> > > > 
> > > > > Maybe the early exit test should just be whether the context of the
> > > > > outer variable is dependent.
> > > > 
> > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16.2?
> > > > 
> > > > -- >8 --
> > > > Thanks to DR 696 (r253266), this works:
> > > > 
> > > >   int g;
> > > >   void fn ()
> > > >   {
> > > >     int &c = g;
> > > >     auto l = [] { c++; };
> > > >     l();
> > > >   }
> > > > 
> > > > because `c` in the lambda body is not an odr-use because we can
> > > > evaluate it to a constant and so there's no capture.  But when
> > > > fn is a template, we reject the code and crash.  This patch fixes
> > > > both.
> > > > 
> > > > Outside a template, the call to maybe_constant_value in mark_use
> > > > evaluates `c` to `(int&) &g` but in a template, it remains `c`.
> > > > Then we emit an error, and crash on the error_mark_node from
> > > > process_outer_var_ref.  One of the reasons is
> > > >       else if (TYPE_REF_P (TREE_TYPE (expression)))
> > > >         /* FIXME cp_finish_decl doesn't fold reference initializers.  */
> > > >         return true;
> > > > in value_dependent_expression_p but even if that changed, we still
> > > > wouldn't get the referent because decl_really_constant_value wouldn't
> > > > give it to us; the DECL_INITIAL is not a TREE_CONSTANT yet.
> > > > 
> > > > So I stopped trying to make this work in a template, and instead
> > > > I'm deferring the error in process_outer_var_ref to instantiation
> > > > when it's instantiation-dependent.  The VAR_P check there is not
> > > > to regress the diagnostic in pr57416.C.
> > > > 
> > > > The mark_use hunk is to fix a crash on invalid (lambda-const14.C).
> > > > 
> > > >         PR c++/123536
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > >         * expr.cc (mark_use): Return if mark_rvalue_use returns
> > > >         error_mark_node.
> > > >         * semantics.cc (process_outer_var_ref): Return decl when it is
> > > >         instantiation-dependent.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > >         * g++.dg/cpp0x/lambda/lambda-const12.C: New test.
> > > >         * g++.dg/cpp0x/lambda/lambda-const13.C: New test.
> > > >         * g++.dg/cpp0x/lambda/lambda-const14.C: New test.
> > > >         * g++.dg/template/local11.C: New test.
> > > > ---
> > > >  gcc/cp/expr.cc                                |  2 +
> > > >  gcc/cp/semantics.cc                           |  6 +-
> > > >  .../g++.dg/cpp0x/lambda/lambda-const12.C      | 62 +++++++++++++++++++
> > > >  .../g++.dg/cpp0x/lambda/lambda-const13.C      | 19 ++++++
> > > >  .../g++.dg/cpp0x/lambda/lambda-const14.C      | 16 +++++
> > > >  gcc/testsuite/g++.dg/template/local11.C       | 18 ++++++
> > > >  6 files changed, 122 insertions(+), 1 deletion(-)
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const14.C
> > > >  create mode 100644 gcc/testsuite/g++.dg/template/local11.C
> > > > 
> > > > diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc
> > > > index 4d017d530ef..516cea084a6 100644
> > > > --- a/gcc/cp/expr.cc
> > > > +++ b/gcc/cp/expr.cc
> > > > @@ -182,6 +182,8 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
> > > >                 }
> > > >             }
> > > >           tree r = mark_rvalue_use (ref, loc, reject_builtin);
> > > > +         if (r == error_mark_node)
> > > > +           return error_mark_node;
> > > >           if (r != ref)
> > > >             {
> > > >               if (!rvalue_p)
> > > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > > > index 6564d9e37a6..5e64a220e4f 100644
> > > > --- a/gcc/cp/semantics.cc
> > > > +++ b/gcc/cp/semantics.cc
> > > > @@ -4697,6 +4697,10 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
> > > > complain, bool odr_use)
> > > >       constant without odr-use.  So don't complain yet.  */
> > > >    else if (!odr_use && decl_constant_var_p (var))
> > > >      return var;
> > > > +  /* Don't complain when DECL is dependent, because it can turn out to
> > > > +     be constant (and therefore needing no capture) when 
> > > > instantiating.  */
> > > > +  else if (VAR_P (decl) && instantiation_dependent_expression_p (decl))
> > > > +    return decl;
> > > 
> > > Think we need to look through capture proxies here by using 'var'
> > > instead of 'decl' here for sake of:
> > > 
> > >     struct A { static int x; };
> > > 
> > >     template<class T>
> > >     void
> > >     fn1 ()
> > >     {
> > >       int& c = T::x;
> > >       [&c] {
> > >         [] { c++; }();
> > >       };
> > >     }
> > > 
> > >     void
> > >     bar ()
> > >     {
> > >       fn1<A> ();
> > >     }
> > 
> > Fixed.  I used var and then changed it back to decl, sigh.
> > Thanks for catching that.
> > 
> > Testing this, dg.exp passed.
> > 
> > -- >8 --
> > Thanks to DR 696 (r253266), this works:
> > 
> >   int g;
> >   void fn ()
> >   {
> >     int &c = g;
> >     auto l = [] { c++; };
> >     l();
> >   }
> > 
> > because `c` in the lambda body is not an odr-use because we can
> > evaluate it to a constant and so there's no capture.  But when
> > fn is a template, we reject the code and crash.  This patch fixes
> > both.
> > 
> > Outside a template, the call to maybe_constant_value in mark_use
> > evaluates `c` to `(int&) &g` but in a template, it remains `c`.
> > Then we emit an error, and crash on the error_mark_node from
> > process_outer_var_ref.  One of the reasons is
> >       else if (TYPE_REF_P (TREE_TYPE (expression)))
> >         /* FIXME cp_finish_decl doesn't fold reference initializers.  */
> >         return true;
> > in value_dependent_expression_p but even if that changed, we still
> > wouldn't get the referent because decl_really_constant_value wouldn't
> > give it to us; the DECL_INITIAL is not a TREE_CONSTANT yet.
> > 
> > So I stopped trying to make this work in a template, and instead
> > I'm deferring the error in process_outer_var_ref to instantiation
> > when it's instantiation-dependent.  The VAR_P check there is not
> > to regress the diagnostic in pr57416.C.
> > 
> > The mark_use hunk is to fix a crash on invalid (lambda-const14.C).
> > 
> >     PR c++/123536
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * expr.cc (mark_use): Return if mark_rvalue_use returns
> >     error_mark_node.
> >     * semantics.cc (process_outer_var_ref): Return decl when it is
> >     instantiation-dependent.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * g++.dg/cpp0x/lambda/lambda-const12.C: New test.
> >     * g++.dg/cpp0x/lambda/lambda-const13.C: New test.
> >     * g++.dg/cpp0x/lambda/lambda-const14.C: New test.
> >     * g++.dg/template/local11.C: New test.
> 
> LGTM but I defer to Jason.
> 
> > ---
> >  gcc/cp/expr.cc                                |  2 +
> >  gcc/cp/semantics.cc                           |  6 +-
> >  .../g++.dg/cpp0x/lambda/lambda-const12.C      | 73 +++++++++++++++++++
> >  .../g++.dg/cpp0x/lambda/lambda-const13.C      | 19 +++++
> >  .../g++.dg/cpp0x/lambda/lambda-const14.C      | 16 ++++
> >  gcc/testsuite/g++.dg/template/local11.C       | 18 +++++
> >  6 files changed, 133 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C
> >  create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const14.C
> >  create mode 100644 gcc/testsuite/g++.dg/template/local11.C
> > 
> > diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc
> > index 4d017d530ef..516cea084a6 100644
> > --- a/gcc/cp/expr.cc
> > +++ b/gcc/cp/expr.cc
> > @@ -182,6 +182,8 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
> >             }
> >         }
> >       tree r = mark_rvalue_use (ref, loc, reject_builtin);
> > +     if (r == error_mark_node)
> > +       return error_mark_node;
> >       if (r != ref)
> >         {
> >           if (!rvalue_p)
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 490441dba6c..6dd46b14359 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -4697,6 +4697,10 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
> > complain, bool odr_use)
> 
> While we're modifying process_outer_var_ref could you also document
> odr_use's default argument with /* = false */?

Sure.  And the decl in cp-tree.h was using the old name.

> LGTM but wonder what Jason think 

Thanks a lot for the reviews!

-- >8 --
Thanks to DR 696 (r253266), this works:

  int g;
  void fn ()
  {
    int &c = g;
    auto l = [] { c++; };
    l();
  }

because `c` in the lambda body is not an odr-use because we can
evaluate it to a constant and so there's no capture.  But when
fn is a template, we reject the code and crash.  This patch fixes
both.

Outside a template, the call to maybe_constant_value in mark_use
evaluates `c` to `(int&) &g` but in a template, it remains `c`.
Then we emit an error, and crash on the error_mark_node from
process_outer_var_ref.  One of the reasons is
      else if (TYPE_REF_P (TREE_TYPE (expression)))
        /* FIXME cp_finish_decl doesn't fold reference initializers.  */
        return true;
in value_dependent_expression_p but even if that changed, we still
wouldn't get the referent because decl_really_constant_value wouldn't
give it to us; the DECL_INITIAL is not a TREE_CONSTANT yet.

So I stopped trying to make this work in a template, and instead
I'm deferring the error in process_outer_var_ref to instantiation
when it's instantiation-dependent.  The VAR_P check there is not
to regress the diagnostic in pr57416.C.

The mark_use hunk is to fix a crash on invalid (lambda-const14.C).

        PR c++/123536

gcc/cp/ChangeLog:

        * cp-tree.h (process_outer_var_ref): Remove a parameter's name.
        * expr.cc (mark_use): Return if mark_rvalue_use returns
        error_mark_node.
        * semantics.cc (process_outer_var_ref): Return decl when it is
        instantiation-dependent.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/lambda/lambda-const12.C: New test.
        * g++.dg/cpp0x/lambda/lambda-const13.C: New test.
        * g++.dg/cpp0x/lambda/lambda-const14.C: New test.
        * g++.dg/template/local11.C: New test.
---
 gcc/cp/cp-tree.h                              |  3 +-
 gcc/cp/expr.cc                                |  2 +
 gcc/cp/semantics.cc                           |  9 ++-
 .../g++.dg/cpp0x/lambda/lambda-const12.C      | 73 +++++++++++++++++++
 .../g++.dg/cpp0x/lambda/lambda-const13.C      | 19 +++++
 .../g++.dg/cpp0x/lambda/lambda-const14.C      | 16 ++++
 gcc/testsuite/g++.dg/template/local11.C       | 18 +++++
 7 files changed, 137 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const14.C
 create mode 100644 gcc/testsuite/g++.dg/template/local11.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8a168f509d4..6a8adbc18ca 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8584,7 +8584,8 @@ extern tree finish_base_specifier         (tree, tree, 
bool, tree);
 extern void finish_member_declaration          (tree);
 extern bool outer_automatic_var_p              (tree);
 extern bool parsing_lambda_declarator          ();
-extern tree process_outer_var_ref              (tree, tsubst_flags_t, bool 
force_use = false);
+extern tree process_outer_var_ref              (tree, tsubst_flags_t,
+                                                bool = false);
 extern cp_expr finish_id_expression            (tree, tree, tree,
                                                 cp_id_kind *,
                                                 bool, bool, bool *,
diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc
index 4d017d530ef..516cea084a6 100644
--- a/gcc/cp/expr.cc
+++ b/gcc/cp/expr.cc
@@ -182,6 +182,8 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
                }
            }
          tree r = mark_rvalue_use (ref, loc, reject_builtin);
+         if (r == error_mark_node)
+           return error_mark_node;
          if (r != ref)
            {
              if (!rvalue_p)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 490441dba6c..0d47b20fb3c 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4595,7 +4595,8 @@ set_contract_capture_flag (tree d, bool val)
    id-expression, and we do lambda capture.  */
 
 tree
-process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
+process_outer_var_ref (tree decl, tsubst_flags_t complain,
+                      bool odr_use/*=false*/)
 {
   if (cp_unevaluated_operand)
     {
@@ -4697,6 +4698,10 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
complain, bool odr_use)
      constant without odr-use.  So don't complain yet.  */
   else if (!odr_use && decl_constant_var_p (var))
     return var;
+  /* Don't complain when DECL is dependent, because it can turn out to
+     be constant (and therefore needing no capture) when instantiating.  */
+  else if (VAR_P (var) && instantiation_dependent_expression_p (var))
+    return var;
   else if (lambda_expr)
     {
       if (complain & tf_error)
@@ -4715,7 +4720,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
complain, bool odr_use)
        }
       return error_mark_node;
     }
-  else if (processing_contract_condition && (TREE_CODE (decl) == PARM_DECL))
+  else if (processing_contract_condition && TREE_CODE (decl) == PARM_DECL)
     /* Use of a parameter in a contract condition is fine.  */
     return decl;
   else
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C 
b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C
new file mode 100644
index 00000000000..fc18b63f9b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const12.C
@@ -0,0 +1,73 @@
+// PR c++/123536
+// { dg-do compile { target c++11 } }
+
+int g;
+
+struct S {
+  static int static_data_member;
+};
+
+template<int = 1>
+void
+fn1 ()
+{
+  int &c = g;
+  auto l = [] { c++; };
+  l();
+}
+
+template<int N = 1>
+void
+fn2 ()
+{
+  const int &c = N;
+  auto l = [] { int i = c; (void) i; }; // { dg-error ".c. is not captured" }
+  l();
+}
+
+void
+fn3 ()
+{
+  int &c = g;
+  auto l = [] { c++; };
+  l();
+}
+
+void
+fn4 ()
+{
+  int n = 42;
+  const int &c = n;
+  auto l = [] { int i = c; (void) i; }; // { dg-error ".c. is not captured" }
+  l();
+}
+
+template<class T>
+void
+fn5 ()
+{
+  int& c = T::static_data_member;
+  auto l = [] { c++; };
+  l();
+}
+
+template<class T>
+void
+fn6 ()
+{
+  int& c = T::static_data_member;
+  [&c] {
+    [] { c++; }();
+  };
+}
+
+void
+bar ()
+{
+  fn1 ();
+  fn2 ();
+  fn3 ();
+  fn4 ();
+  fn5<S>();
+  fn6<S>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C 
b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C
new file mode 100644
index 00000000000..a6044c52e7e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const13.C
@@ -0,0 +1,19 @@
+// PR c++/123536
+// { dg-do compile { target c++11 } }
+
+int g;
+
+template<class T>
+void
+fn1 ()
+{
+  T c = g;
+  auto l = [] { c++; };
+  l();
+}
+
+void
+bar ()
+{
+  fn1<int&> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const14.C 
b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const14.C
new file mode 100644
index 00000000000..2299556a4e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const14.C
@@ -0,0 +1,16 @@
+// PR c++/123536
+// { dg-do compile { target c++11 } }
+
+template<class T>
+void
+f ()
+{
+  int& c = T::x;       // { dg-error ".x. is not a member of .int." }
+  auto l = [] { c++; };        // { dg-error ".c. is not captured" }
+}
+
+void
+g ()
+{
+  f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/template/local11.C 
b/gcc/testsuite/g++.dg/template/local11.C
new file mode 100644
index 00000000000..f75b748caa8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/local11.C
@@ -0,0 +1,18 @@
+// PR c++/123536
+
+int g;
+
+template<class T>
+void
+fn1 ()
+{
+  T c = g;
+  struct A { static void f() { c++; } };
+  A::f();
+}
+
+void
+bar ()
+{
+  fn1<int&> ();
+}

base-commit: 085b7cf00c5269f7e4e76b022faf00b7fc5ab16b
-- 
2.54.0

Reply via email to