--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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
+}
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 } */
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");
;
/* 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))
}
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;
}