Re: C++ PATCH for c++/56973 (DR 696), lambda capture of const variables

2017-11-13 Thread Jason Merrill
On Tue, Oct 10, 2017 at 1:59 PM, Jason Merrill  wrote:
> On Thu, Sep 28, 2017 at 3:38 PM, Jason Merrill  wrote:
>> The G++ lambda implementation previously implemented an early
>> tentative resolution of DR 696, whereby mentions of an outer constant
>> variable would immediately decay to the constant value of that
>> variable.  But the final resolution specified that we should capture
>> or not depending on how the variable is used: if we use it as an
>> lvalue, it's captured; if we use it as an rvalue, it isn't.
>>
>> The first patch is some minor fixes discovered during this work.
>> The second patch reworks how we find capture proxies to use
>> local_specializations instead of name lookup.
>> The third patch delays capture of constant variables until
>> mark_rvalue_use/mark_lvalue_use.
>>
>> The third patch also adds calls to mark_*_use in a couple of places
>> that needed it; I expect more will be necessary as well.
>
> I tested using delayed capture for all variables, and these fixes are
> the result.
>
> The first two patches are fixes for generic issues that I came across
> while looking at the capture issues.  The first adds checking within a
> template definition for non-dependent return statements.  The second
> fixes a few small issues.  The third patch implements generic lambda
> capture in dependent full-expressions, and the fourth adds some
> missing mark_*_use calls and fixes other issues with delayed capture.

P0588, voted in at the Albuquerque meeting last week, simplifies
implicit capture such that we can immediately capture named variables
and remove all the special generic lambda capture machinery.
mark_*_use are kept largely intact, but will never cause a capture;
they are now used for looking through capture proxies for constant
variables, and for diagnostics about odr-use of un-captured outer
variables.

Tested x86_64-pc-linux-gnu, applying to trunk.

Jason
commit d1730186f54ebc3fa82fe801cd3c500a9b8235af
Author: Jason Merrill 
Date:   Thu Nov 9 16:32:58 2017 -0500

Capture adjustments for P0588R1.

* semantics.c (process_outer_var_ref): Capture variables when
they are named; complain about non-capture uses when odr-used.
* expr.c (mark_use): Rvalue use looks through capture proxy.
* constexpr.c (potential_constant_expression_1): Improve error about
use of captured variable.
* lambda.c (need_generic_capture, dependent_capture_r)
(do_dependent_capture, processing_nonlambda_template): Remove.
* call.c (build_this): Remove uses of the above.
* decl.c (cp_finish_decl): Likewise.
* semantics.c (maybe_cleanup_point_expr)
(maybe_cleanup_point_expr_void, finish_goto_stmt)
(maybe_convert_cond): Likewise.
* typeck.c (check_return_expr): Likewise.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e18f0770614..e09cf97920b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3365,7 +3365,7 @@ build_this (tree obj)
 {
   /* In a template, we are only concerned about the type of the
  expression, so we can take a shortcut.  */
-  if (processing_nonlambda_template ())
+  if (processing_template_decl)
 return build_address (obj);
 
   return cp_build_addr_expr (obj, tf_warning_or_error);
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 670aae22dd6..d6b6843e804 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1286,8 +1286,6 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, 
tree t,
  && is_dummy_object (x))
{
  x = ctx->object;
- /* We don't use cp_build_addr_expr here because we don't want to
-capture the object argument during constexpr evaluation.  */
  x = build_address (x);
}
   bool lval = false;
@@ -5289,7 +5287,25 @@ potential_constant_expression_1 (tree t, bool want_rval, 
bool strict, bool now,
 
 case VAR_DECL:
   if (DECL_HAS_VALUE_EXPR_P (t))
-   return RECUR (DECL_VALUE_EXPR (t), rval);
+   {
+ if (now && is_normal_capture_proxy (t))
+   {
+ /* -- in a lambda-expression, a reference to this or to a
+variable with automatic storage duration defined outside that
+lambda-expression, where the reference would be an
+odr-use.  */
+ if (flags & tf_error)
+   {
+ tree cap = DECL_CAPTURED_VARIABLE (t);
+ error ("lambda capture of %qE is not a constant expression",
+cap);
+ if (!want_rval && decl_constant_var_p (cap))
+   inform (input_location, "because it is used as a glvalue");
+   }
+ return false;
+   }
+ return RECUR (DECL_VALUE_EXPR (t), rval);
+   }
   if (want_rval
  && !var_in_maybe_constexpr_fn (t)
  && 

Re: C++ PATCH for c++/56973 (DR 696), lambda capture of const variables

2017-10-10 Thread Jason Merrill
On Thu, Sep 28, 2017 at 3:38 PM, Jason Merrill  wrote:
> The G++ lambda implementation previously implemented an early
> tentative resolution of DR 696, whereby mentions of an outer constant
> variable would immediately decay to the constant value of that
> variable.  But the final resolution specified that we should capture
> or not depending on how the variable is used: if we use it as an
> lvalue, it's captured; if we use it as an rvalue, it isn't.
>
> The first patch is some minor fixes discovered during this work.
> The second patch reworks how we find capture proxies to use
> local_specializations instead of name lookup.
> The third patch delays capture of constant variables until
> mark_rvalue_use/mark_lvalue_use.
>
> The third patch also adds calls to mark_*_use in a couple of places
> that needed it; I expect more will be necessary as well.

I tested using delayed capture for all variables, and these fixes are
the result.

The first two patches are fixes for generic issues that I came across
while looking at the capture issues.  The first adds checking within a
template definition for non-dependent return statements.  The second
fixes a few small issues.  The third patch implements generic lambda
capture in dependent full-expressions, and the fourth adds some
missing mark_*_use calls and fixes other issues with delayed capture.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 06873162a116c6629dea55a36f8b43f71c6c7880
Author: Jason Merrill 
Date:   Tue Oct 10 10:49:07 2017 -0400

Check non-dependent conversion in return from template fn.

* typeck.c (check_return_expr): Check non-dependent conversion in
templates.
* constraint.cc (check_function_concept): Don't complain about an
empty concept if seen_error.

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 64a8ea926d2..8b49455a526 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2504,7 +2504,12 @@ check_function_concept (tree fn)
 {
   location_t loc = DECL_SOURCE_LOCATION (fn);
   if (TREE_CODE (body) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (body))
-error_at (loc, "definition of concept %qD is empty", fn);
+   {
+ if (seen_error ())
+   /* The definition was probably erroneous, not empty.  */;
+ else
+   error_at (loc, "definition of concept %qD is empty", fn);
+   }
   else
 error_at (loc, "definition of concept %qD has multiple statements", 
fn);
 }
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index c3310db7b3b..01647d04bc8 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8957,10 +8957,14 @@ check_return_expr (tree retval, bool *no_warning)
   if (check_for_bare_parameter_packs (retval))
return error_mark_node;
 
-  if (WILDCARD_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl)))
+  /* If one of the types might be void, we can't tell whether we're
+returning a value.  */
+  if ((WILDCARD_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl)))
+  && !current_function_auto_return_pattern)
  || (retval != NULL_TREE
- && type_dependent_expression_p (retval)))
-return retval;
+ && (TREE_TYPE (retval) == NULL_TREE
+ || WILDCARD_TYPE_P (TREE_TYPE (retval)
+   goto dependent;
 }
 
   functype = TREE_TYPE (TREE_TYPE (current_function_decl));
@@ -9098,8 +9102,10 @@ check_return_expr (tree retval, bool *no_warning)
warning (OPT_Weffc__, 

C++ PATCH for c++/56973 (DR 696), lambda capture of const variables

2017-09-28 Thread Jason Merrill
The G++ lambda implementation previously implemented an early
tentative resolution of DR 696, whereby mentions of an outer constant
variable would immediately decay to the constant value of that
variable.  But the final resolution specified that we should capture
or not depending on how the variable is used: if we use it as an
lvalue, it's captured; if we use it as an rvalue, it isn't.

The first patch is some minor fixes discovered during this work.
The second patch reworks how we find capture proxies to use
local_specializations instead of name lookup.
The third patch delays capture of constant variables until
mark_rvalue_use/mark_lvalue_use.

The third patch also adds calls to mark_*_use in a couple of places
that needed it; I expect more will be necessary as well.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit ea50e0c044c8405aa7bc277628e38f838f1e66a7
Author: Jason Merrill 
Date:   Wed Sep 27 17:06:31 2017 -0400

Small lambda fixes.

* call.c (build_special_member_call): Use the return value of
mark_lvalue_use.
* decl.c (compute_array_index_type): Likewise.
* parser.c (cp_parser_oacc_wait_list): Likewise.
* lambda.c (is_normal_capture_proxy): Handle *this capture.
(add_capture): Clarify internal_error message.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e83cf99dc89..99a7b77efb2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8845,7 +8845,7 @@ build_special_member_call (tree instance, tree name, 
vec **args,
  && (flags & LOOKUP_DELEGATING_CONS))
check_self_delegation (arg);
  /* Avoid change of behavior on Wunused-var-2.C.  */
- mark_lvalue_use (instance);
+ instance = mark_lvalue_use (instance);
  return build2 (INIT_EXPR, class_type, instance, arg);
}
 }
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 50fa1ba402e..ce45c1140d6 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9329,7 +9329,7 @@ compute_array_index_type (tree name, tree size, 
tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (size);
 
-  mark_rvalue_use (size);
+  size = mark_rvalue_use (size);
 
   if (cxx_dialect < cxx11 && TREE_CODE (size) == NOP_EXPR
  && TREE_SIDE_EFFECTS (size))
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index e4412569a61..695666abbe3 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -283,6 +283,8 @@ is_normal_capture_proxy (tree decl)
   if (val == error_mark_node)
 return true;
 
+  if (TREE_CODE (val) == ADDR_EXPR)
+val = TREE_OPERAND (val, 0);
   gcc_assert (TREE_CODE (val) == COMPONENT_REF);
   val = TREE_OPERAND (val, 1);
   return DECL_NORMAL_CAPTURE_P (val);
@@ -592,7 +594,8 @@ add_capture (tree lambda, tree id, tree orig_init, bool 
by_reference_p,
   && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
 {
   if (COMPLETE_TYPE_P (current_class_type))
-   internal_error ("trying to capture %qD after closure is complete", id);
+   internal_error ("trying to capture %qD in instantiation of "
+   "generic lambda", id);
   finish_member_declaration (member);
 }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f9b6f278afb..bb2a8774aa0 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -31712,7 +31712,7 @@ cp_parser_oacc_wait_list (cp_parser *parser, location_t 
clause_loc, tree list)
{
  tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
 
- mark_rvalue_use (targ);
+ targ = mark_rvalue_use (targ);
  OMP_CLAUSE_DECL (c) = targ;
  OMP_CLAUSE_CHAIN (c) = list;
  list = c;
commit ea60e04977765a8041e1cba59a8d3028982c55e0
Author: Jason Merrill 
Date:   Wed Sep 27 17:08:56 2017 -0400

Use local_specializations to find capture proxies.

* cp-tree.h (DECL_CAPTURED_VARIABLE): New.
* lambda.c (build_capture_proxy): Set it.
(add_capture): Pass initializer to build_capture_proxy.
(start_lambda_function): Likewise.
(insert_capture_proxy): Use register_local_specialization.
(is_lambda_ignored_entity): Always ignore proxies.
* name-lookup.c (qualify_lookup): Don't check
is_lambda_ignored_entity if LOOKUP_HIDDEN is set.
* semantics.c (process_outer_var_ref): Use
retrieve_local_specialization.
* parser.c (cp_parser_lambda_body): Push local_specializations.
* pt.c (tsubst_expr): Pass LOOKUP_HIDDEN when looking for a proxy.
(tsubst_lambda_expr): Push local_specializations sooner.
(tsubst_copy_and_build): Don't register_local_specialization.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7c1c54c78b5..a6349019543 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2471,10 +2471,12 @@ struct GTY(()) lang_decl_min {
   union