]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: source position of lambda captures [PR84471]
authorJason Merrill <jason@redhat.com>
Fri, 2 Dec 2022 03:58:28 +0000 (22:58 -0500)
committerJason Merrill <jason@redhat.com>
Wed, 21 Dec 2022 02:01:44 +0000 (21:01 -0500)
If the DECL_VALUE_EXPR of a VAR_DECL has EXPR_LOCATION set, then any use of
that variable looks like it has that location, which leads to the debugger
jumping back and forth for both lambdas and structured bindings.

Rather than fix all the uses, it seems simplest to remove any EXPR_LOCATION
when setting DECL_VALUE_EXPR.  So the cp/ hunks aren't necessary, but they
avoid the need to unshare to remove the location.

PR c++/84471
PR c++/107504

gcc/cp/ChangeLog:

* coroutines.cc (transform_local_var_uses): Don't
specify a location for DECL_VALUE_EXPR.
* decl.cc (cp_finish_decomp): Likewise.

gcc/ChangeLog:

* fold-const.cc (protected_set_expr_location_unshare): Not static.
* tree.h: Declare it.
* tree.cc (decl_value_expr_insert): Use it.

include/ChangeLog:

* ansidecl.h (ATTRIBUTE_WARN_UNUSED_RESULT): Add __.

gcc/testsuite/ChangeLog:

* g++.dg/tree-ssa/value-expr1.C: New test.
* g++.dg/tree-ssa/value-expr2.C: New test.
* g++.dg/analyzer/pr93212.C: Move warning.

gcc/cp/coroutines.cc
gcc/cp/decl.cc
gcc/fold-const.cc
gcc/testsuite/g++.dg/analyzer/pr93212.C
gcc/testsuite/g++.dg/tree-ssa/value-expr1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/value-expr2.C [new file with mode: 0644]
gcc/tree.cc
gcc/tree.h
include/ansidecl.h

index 88d6c30d8b1b578ce99d027ccdf832131ae5cefb..77e2a90f0f98987412f0301acb02a3729fee34d5 100644 (file)
@@ -2047,8 +2047,8 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
            = lookup_member (lvd->coro_frame_type, local_var.field_id,
                             /*protect=*/1, /*want_type=*/0,
                             tf_warning_or_error);
-         tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
-                                    lvd->actor_frame, fld_ref, NULL_TREE);
+         tree fld_idx = build3 (COMPONENT_REF, TREE_TYPE (lvar),
+                                lvd->actor_frame, fld_ref, NULL_TREE);
          local_var.field_idx = fld_idx;
          SET_DECL_VALUE_EXPR (lvar, fld_idx);
          DECL_HAS_VALUE_EXPR_P (lvar) = true;
index df74d886b281df136db322cfef6c4b55f1e4e63b..3c0355a1c395244752471c2b4bd45d52656c74a8 100644 (file)
@@ -9137,9 +9137,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
          if (processing_template_decl)
            continue;
          tree t = unshare_expr (dexp);
-         t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF,
-                         eltype, t, size_int (i), NULL_TREE,
-                         NULL_TREE);
+         t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE);
          SET_DECL_VALUE_EXPR (v[i], t);
          DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
        }
@@ -9158,9 +9156,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
          if (processing_template_decl)
            continue;
          tree t = unshare_expr (dexp);
-         t = build1_loc (DECL_SOURCE_LOCATION (v[i]),
-                         i ? IMAGPART_EXPR : REALPART_EXPR, eltype,
-                         t);
+         t = build1 (i ? IMAGPART_EXPR : REALPART_EXPR, eltype, t);
          SET_DECL_VALUE_EXPR (v[i], t);
          DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
        }
@@ -9184,9 +9180,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
          tree t = unshare_expr (dexp);
          convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]),
                                                 &t, size_int (i));
-         t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF,
-                         eltype, t, size_int (i), NULL_TREE,
-                         NULL_TREE);
+         t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE);
          SET_DECL_VALUE_EXPR (v[i], t);
          DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
        }
index e4c43fbe8cb46604b912e623217aacf0c8bbb685..42547f433ed9b093d0eab10bc9f33ea20fe79df7 100644 (file)
@@ -164,7 +164,7 @@ expr_location_or (tree t, location_t loc)
 /* Similar to protected_set_expr_location, but never modify x in place,
    if location can and needs to be set, unshare it.  */
 
-static inline tree
+tree
 protected_set_expr_location_unshare (tree x, location_t loc)
 {
   if (CAN_HAVE_LOCATION_P (x)
index 41507e2b8378e5a36da6429a87f45e2fbb6d167b..1029e8d547ba8354373eb84fc695504c9007ed61 100644 (file)
@@ -4,8 +4,8 @@
 auto lol()
 {
     int aha = 3;
-    return [&aha] { // { dg-warning "dereferencing pointer '.*' to within stale stack frame" }
-        return aha;
+    return [&aha] {
+        return aha; // { dg-warning "dereferencing pointer '.*' to within stale stack frame" }
     };
     /* TODO: may be worth special-casing the reporting of dangling
        references from lambdas, to highlight the declaration, and maybe fix
diff --git a/gcc/testsuite/g++.dg/tree-ssa/value-expr1.C b/gcc/testsuite/g++.dg/tree-ssa/value-expr1.C
new file mode 100644 (file)
index 0000000..946ccc3
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/84471
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fdump-tree-gimple-lineno }
+// { dg-final { scan-tree-dump-not {value-expr: \[} "gimple" } }
+
+int main(int argc, char**)
+{
+  int x = 1;
+  auto f = [&x, &argc](const char* i) {
+    i += x;
+    i -= argc;
+    i += argc - x;
+    return i;
+  };
+  f("          ");
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/value-expr2.C b/gcc/testsuite/g++.dg/tree-ssa/value-expr2.C
new file mode 100644 (file)
index 0000000..4d00498
--- /dev/null
@@ -0,0 +1,26 @@
+// PR c++/107504
+// { dg-do compile { target c++17 } }
+// { dg-additional-options -fdump-tree-gimple-lineno }
+// { dg-final { scan-tree-dump-not {value-expr: \[} "gimple" } }
+
+struct S
+{
+  void* i;
+  int j;
+};
+
+S f(char* p)
+{
+  return {p, 1};
+}
+
+int main()
+{
+  char buf[1];
+  auto [x, y] = f(buf);
+  if (x != buf)
+    throw 1;
+  if (y != 1)
+    throw 2;
+  return 0;
+}
index 92199bb650333a6c58ea45661435ccff15037136..581d4489438e6ed5ee91e38e5af7d7f3c73278ef 100644 (file)
@@ -5862,6 +5862,9 @@ decl_value_expr_insert (tree from, tree to)
 {
   struct tree_decl_map *h;
 
+  /* Uses of FROM shouldn't look like they happen at the location of TO.  */
+  to = protected_set_expr_location_unshare (to, UNKNOWN_LOCATION);
+
   h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
index 31d0dcaf249efdf97ce12824bfd3ea50f67c2834..64a241f51e238458918e14805c48a23c7b640040 100644 (file)
@@ -1289,6 +1289,8 @@ get_expr_source_range (tree expr)
 
 extern void protected_set_expr_location (tree, location_t);
 extern void protected_set_expr_location_if_unset (tree, location_t);
+ATTRIBUTE_WARN_UNUSED_RESULT
+extern tree protected_set_expr_location_unshare (tree, location_t);
 
 WARN_UNUSED_RESULT extern tree maybe_wrap_with_location (tree, location_t);
 
index 056a03ebb6e8cd98dce573a8864ec5bbfd61144f..4da8069f17133a39af586f431c133ad6f636ec7c 100644 (file)
@@ -279,7 +279,7 @@ So instead we use the macro below and test it against specific values.  */
 /* Attribute `warn_unused_result' was valid as of gcc 3.3.  */
 #ifndef ATTRIBUTE_WARN_UNUSED_RESULT
 # if GCC_VERSION >= 3003
-#  define ATTRIBUTE_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+#  define ATTRIBUTE_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
 # else
 #  define ATTRIBUTE_WARN_UNUSED_RESULT
 # endif