aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2021-01-19 15:10:30 -0700
committerMartin Sebor <msebor@redhat.com>2021-01-19 15:10:30 -0700
commit9693e255ee2536c6823640eba5d0163c2b401161 (patch)
tree5f5735deb16a463d71fd69e8fcffe5b131aec478 /gcc
parent29853c653245c37ed31b6abcc9799b534372e938 (diff)
downloadgcc-9693e255ee2536c6823640eba5d0163c2b401161.zip
gcc-9693e255ee2536c6823640eba5d0163c2b401161.tar.gz
gcc-9693e255ee2536c6823640eba5d0163c2b401161.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-5.C129
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c107
-rw-r--r--gcc/testsuite/gcc.dg/Wvla-larger-than-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-inlining-3.c3
-rw-r--r--gcc/tree-ssa-live.c17
-rw-r--r--gcc/tree.c11
6 files changed, 255 insertions, 18 deletions
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 0000000..742dba0
--- /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 0000000..a7d9212
--- /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 de99afb..7d27829 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 e1a4fca..56c9546 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 02a7a56..a2aab25 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -555,20 +555,17 @@ remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block)
;
/* When not generating debug info we can eliminate info on unused
variables. */
- else if (!flag_auto_profile && debug_info_level == DINFO_LEVEL_NONE
+ 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)))
- unused = false;
+ gcc_assert (TREE_CODE (BLOCK_ORIGIN (scope)) == FUNCTION_DECL);
+ unused = false;
}
}
else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope))
diff --git a/gcc/tree.c b/gcc/tree.c
index a25c71f..061fe43 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -12638,10 +12638,13 @@ tree_inlined_location (tree exp, bool system_header /* = true */)
}
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;
}