public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] keep scope blocks for all inlined functions (PR 98664)
@ 2021-01-14 19:13 Martin Sebor
  2021-01-15  7:44 ` Richard Biener
  0 siblings, 1 reply; 12+ messages in thread
From: Martin Sebor @ 2021-01-14 19:13 UTC (permalink / raw)
  To: Jeff Law, Jakub Jelinek, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 983 bytes --]

One aspect of PR 98465 - Bogus warning stringop-overread for std::string
is the inconsistency between -g and -g0 which turns out to be due to
GCC eliminating apparently unused scope blocks from inlined functions
that aren't explicitly declared inline and artificial.  PR 98664 tracks
just this part of PR 98465.

To resolve just the PR 98664 subset the attached change has
the tree-ssa-live.c pass preserve these blocks for all inlined
functions, not just artificial ones.  Besides avoiding the interaction
between -g and warnings it also seems to improve the inlining context
by including more inlined call sites.  This can be seen in the adjusted
tests.  (Its effect on PR 98465 is that the false positive is issued
consistently, regardless of -g.  Avoiding the false positive is my
next step.)

Jakub, you raised a concern yesterday in PR 98465 c#13 about the memory
footprint of this change.  Can you please comment on whether it's in
line with what you were suggesting?

Martin

[-- Attachment #2: gcc-98664.diff --]
[-- Type: text/x-patch, Size: 9687 bytes --]

PR middle-end/98664 - inconsistent -Wfree-nonheap-object for inlined calls to system headers

gcc/ChangeLog:

	PR middle-end/98664
	* tree-ssa-live.c (remove_unused_scope_block_p): Keep scopes for
	all functions, even if they're not declared artificial or inline.
	* tree.c (tree_inlined_location): Use macro expansion location
	only if scope traversal fails to expose one.

gcc/testsuite/ChangeLog:

	PR middle-end/98664
	* gcc.dg/Wvla-larger-than-4.c: Adjust expected output.
	* gcc.dg/plugin/diagnostic-test-inlining-3.c: Same.
	* g++.dg/warn/Wfree-nonheap-object-5.C: New test.
	* gcc.dg/Wfree-nonheap-object-4.c: New test.

diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C
new file mode 100644
index 00000000000..742dba0cf58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C
@@ -0,0 +1,129 @@
+/* PR middle-end/98664 - inconsistent --Wfree-nonheap-object for inlined
+   calls to system headers
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+# 7 "Wfree-nonheap-object-5.h" 1 3
+
+struct A0
+{
+  void *p;
+
+  void f0 (void *q) { p = q; }
+  void g0 (void) {
+    __builtin_free (p);       // { dg-warning "\\\[-Wfree-nonheap-object" }
+  }
+};
+
+struct A1
+{
+  void *p;
+
+  void f0 (void *q) { p = q; }
+  void f1 (void *q) { f0 (q); }
+
+  void g0 (void) {
+    __builtin_free (p);       // { dg-warning "\\\[-Wfree-nonheap-object" }
+  }
+  void g1 (void) { g0 (); }
+};
+
+struct A2
+{
+  void *p;
+
+  void f0 (void *q) { p = q; }
+  void f1 (void *q) { f0 (q); }
+  void f2 (void *q) { f1 (q); }
+
+  void g0 (void) {
+    __builtin_free (p);       // { dg-warning "\\\[-Wfree-nonheap-object" }
+  }
+  void g1 (void) { g0 (); }
+  void g2 (void) { g1 (); }
+};
+
+# 47 "Wfree-nonheap-object-5.C"
+
+#define NOIPA __attribute__ ((noipa))
+
+extern int array[];
+
+/* Verify the warning is issued even for calls in a system header inlined
+   into a function outside the header.  */
+
+NOIPA void warn_g0 (struct A0 *p)
+{
+  int *q = array + 1;
+
+  p->f0 (q);
+  p->g0 ();
+}
+
+// { dg-message "inlined from 'void warn_g0\\(A0\\*\\)'" "" { target *-*-* } 0 }
+
+
+/* Also verify the warning can be suppressed.  */
+
+NOIPA void nowarn_g0 (struct A0 *p)
+{
+  int *q = array + 2;
+
+  p->f0 (q);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+  p->g0 ();
+#pragma GCC diagnostic pop
+}
+
+
+NOIPA void warn_g1 (struct A1 *p)
+{
+  int *q = array + 3;
+
+  p->f1 (q);
+  p->g1 ();
+}
+
+// { dg-message "inlined from 'void A1::g1\\(\\)'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'void warn_g1\\(A1\\*\\)'" "" { target *-*-* } 0 }
+
+
+NOIPA void nowarn_g1 (struct A2 *p)
+{
+  int *q = array + 4;
+
+  p->f1 (q);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+  p->g1 ();
+#pragma GCC diagnostic pop
+}
+
+
+NOIPA void warn_g2 (struct A2 *p)
+{
+  int *q = array + 5;
+
+  p->f2 (q);
+  p->g2 ();
+}
+
+// { dg-message "inlined from 'void A2::g1\\(\\)'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'void A2::g2\\(\\)'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'void warn_g2\\(A2\\*\\)'" "" { target *-*-* } 0 }
+
+
+NOIPA void nowarn_g2 (struct A2 *p)
+{
+  int *q = array + 6;
+
+  p->f2 (q);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+  p->g2 ();
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
new file mode 100644
index 00000000000..a7d921248c4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
@@ -0,0 +1,107 @@
+/* PR middle-end/98664 - inconsistent --Wfree-nonheap-object for inlined
+   calls to system headers
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+# 7 "Wfree-nonheap-object-4.h" 1 3
+
+struct A
+{
+  void *p;
+};
+
+void f0 (struct A *p, void *q) { p->p = q; }
+void f1 (struct A *p, void *q) { f0 (p, q); }
+void f2 (struct A *p, void *q) { f1 (p, q); }
+
+void g0 (struct A *p)
+{
+  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void g1 (struct A *p) { g0 (p); }
+void g2 (struct A *p) { g1 (p); }
+
+# 26 "Wfree-nonheap-object-4.c"
+
+#define NOIPA __attribute__ ((noipa))
+
+extern int array[];
+
+/* Verify the warning is issued even for calls in a system header inlined
+   into a function outside the header.  */
+
+NOIPA void warn_g0 (struct A *p)
+{
+  int *q = array + 1;
+
+  f0 (p, q);
+  g0 (p);
+}
+
+// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 }
+
+
+/* Also verify the warning can be suppressed.  */
+
+NOIPA void nowarn_g0 (struct A *p)
+{
+  int *q = array + 2;
+
+  f0 (p, q);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+  g0 (p);
+#pragma GCC diagnostic pop
+}
+
+
+NOIPA void warn_g1 (struct A *p)
+{
+  int *q = array + 3;
+
+  f1 (p, q);
+  g1 (p);
+}
+
+// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 }
+
+
+NOIPA void nowarn_g1 (struct A *p)
+{
+  int *q = array + 4;
+
+  f1 (p, q);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+  g1 (p);
+#pragma GCC diagnostic pop
+}
+
+
+NOIPA void warn_g2 (struct A *p)
+{
+  int *q = array + 5;
+
+  f2 (p, q);
+  g2 (p);
+}
+
+// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
+
+
+NOIPA void nowarn_g2 (struct A *p)
+{
+  int *q = array + 6;
+
+  f2 (p, q);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+  g2 (p);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c
index de99afbe56e..7d27829736f 100644
--- a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c
+++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c
@@ -17,14 +17,14 @@ static inline void inline_use_vla (unsigned n)
 static inline void use_inlined_vla (unsigned n)
 {
   inline_use_vla (n);         // this call is okay
-  inline_use_vla (n + 1);     // this one is not
+  inline_use_vla (n + 1);     // this one is not (line 20)
 }
 
 void call_inline (void)
 {
-  use_inlined_vla (31);
+  use_inlined_vla (31);       // line 25
 }
 
 /* Verify that the inlining context is included and that it points
    to the correct line number in the inlined function:
-   { dg-message "function 'inline_use_vla'..*inlined from 'call_inline' .*:20:" "" { target *-*-* } 0 }  */
+   { dg-message "function 'inline_use_vla'.*inlined from 'use_inlined_vla'.*:20:.*inlined from 'call_inline' .*:25:" "" { target *-*-* } 0 }  */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c
index e1a4fca2cb4..b7df063c52c 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c
@@ -35,7 +35,8 @@ int main()
    This test case captures this behavior.  */
 
 /* { dg-regexp "In function 'foo'," "" } */
-/* { dg-regexp "    inlined from 'main' at .+/diagnostic-test-inlining-3.c:15:3:" "" } */
+/* { dg-regexp "    inlined from 'bar' at .+/diagnostic-test-inlining-3.c:15:3:" "" } */
+/* { dg-regexp "    inlined from 'main' at .+/diagnostic-test-inlining-3.c:20:3:" "" } */
 /* { dg-warning "3: message" "" { target *-*-* } 9 } */
 /* { dg-begin-multiline-output "" }
    __emit_warning ("message");
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 02a7a56f0f9..a7464369d73 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -558,16 +558,13 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
    else if (!flag_auto_profile && debug_info_level == DINFO_LEVEL_NONE
 	    && !optinfo_wants_inlining_info_p ())
      {
-       /* Even for -g0 don't prune outer scopes from artificial
-	  functions, otherwise diagnostics using tree_nonartificial_location
-	  will not be emitted properly.  */
+       /* Even for -g0 don't prune outer scopes from inlined functions,
+	  otherwise late diagnostics from such functions will not be
+	  emitted or suppressed properly.  */
        if (inlined_function_outer_scope_p (scope))
 	 {
 	   tree ao = BLOCK_ORIGIN (scope);
-	   if (ao
-	       && TREE_CODE (ao) == FUNCTION_DECL
-	       && DECL_DECLARED_INLINE_P (ao)
-	       && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
+	   if (ao && TREE_CODE (ao) == FUNCTION_DECL)
 	     unused = false;
 	 }
      }
diff --git a/gcc/tree.c b/gcc/tree.c
index e0a1d512019..909551a73f9 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -12626,19 +12626,22 @@ tree_inlined_location (tree exp, bool system_header /* = true */)
 	 && BLOCK_ABSTRACT_ORIGIN (block))
     {
       tree ao = BLOCK_ABSTRACT_ORIGIN (block);
-      if (TREE_CODE (ao) == FUNCTION_DECL)
-	loc = BLOCK_SOURCE_LOCATION (block);
-      else if (TREE_CODE (ao) != BLOCK)
-	break;
+       if (TREE_CODE (ao) == FUNCTION_DECL)
+        loc = BLOCK_SOURCE_LOCATION (block);
+       else if (TREE_CODE (ao) != BLOCK)
+        break;
 
       block = BLOCK_SUPERCONTEXT (block);
     }
 
   if (loc == UNKNOWN_LOCATION)
-    loc = EXPR_LOCATION (exp);
-
-  if (system_header)
-    return expansion_point_location_if_in_system_header (loc);
+    {
+      loc = EXPR_LOCATION (exp);
+      if (system_header)
+	/* Only consider macro expansion when the block traversal failed
+	   to find a location.  Otherwise it's not relevant.  */
+	return expansion_point_location_if_in_system_header (loc);
+    }
 
   return loc;
 }

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-02-08 10:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-14 19:13 [PATCH] keep scope blocks for all inlined functions (PR 98664) Martin Sebor
2021-01-15  7:44 ` Richard Biener
2021-01-17  0:46   ` Martin Sebor
2021-01-18 13:25     ` Richard Biener
2021-01-21 21:52       ` [PATCH] document BLOCK_ABSTRACT_ORIGIN et al Martin Sebor
2021-01-28  0:54         ` Martin Sebor
2021-02-01 16:20           ` Martin Sebor
2021-02-03 12:01             ` Richard Biener
2021-02-03 17:12               ` Martin Sebor
2021-02-04  8:48                 ` Richard Biener
2021-02-06 19:11                   ` Martin Sebor
2021-02-08 10:37                     ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).