A 2017 change that propagated call location to GIMPLE statements
had the unexpected (though not incorrect) effect of setting
the location on calls to __builtin_alloca. When such calls are
the result of the expansion of the alloca macro defined in
a system header like <alloca.h>, the change prevents -Walloca and
-Walloca-larger-than
warnings from being issued unless -Wsystem-headers is also used,
effectively defeating the point of the first two warnings in most
code.
The attached patch changes -Walloca to use the location of the point
of the macro expansion rather than that of its definition, restoring
the intended behavior.
In addition, to make the warnings (mainly -Wvla) in inlined code
easier to debug, the patch also arranges for the warnings to include
their inlining context.
Tested on x86_64-linux.
Martin
PR middle-end/94004 - missing -Walloca on calls to alloca due to -Wno-system-headers
gcc/testsuite/ChangeLog:
PR middle-end/94004
* gcc.dg/Walloca-larger-than-3.c: New test.
* gcc.dg/Wvla-larger-than-4.c: New test.
gcc/ChangeLog:
PR middle-end/94004
* gimple-ssa-warn-alloca.c (pass_walloca::execute): Issue warnings
even for alloca calls resulting from system macro expansion.
Include inlining context in all warnings.
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index dfe40c9c02a..9e80e5dbbd9 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -510,11 +510,12 @@ pass_walloca::execute (function *fun)
gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
- location_t loc = gimple_location (stmt);
-
if (!gimple_alloca_call_p (stmt))
continue;
+ location_t loc = gimple_nonartificial_location (stmt);
+ loc = expansion_point_location_if_in_system_header (loc);
+
const bool is_vla
= gimple_call_alloca_for_var_p (as_a <gcall *> (stmt));
@@ -528,7 +529,7 @@ pass_walloca::execute (function *fun)
}
else if (warn_alloca)
{
- warning_at (loc, OPT_Walloca, "use of %<alloca%>");
+ warning_at (loc, OPT_Walloca, "%Guse of %<alloca%>", stmt);
continue;
}
else if (warn_alloca_limit < 0)
@@ -564,10 +565,12 @@ pass_walloca::execute (function *fun)
{
auto_diagnostic_group d;
if (warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length "
- "array may be too large")
- : G_("argument to %<alloca%> may be too "
- "large"))
+ (is_vla
+ ? G_("%Gargument to variable-length "
+ "array may be too large")
+ : G_("%Gargument to %<alloca%> may be too "
+ "large")),
+ stmt)
&& t.limit != 0)
{
print_decu (t.limit, buff);
@@ -582,47 +585,57 @@ pass_walloca::execute (function *fun)
{
auto_diagnostic_group d;
if (warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length"
- " array is too large")
- : G_("argument to %<alloca%> is too large"))
+ (is_vla
+ ? G_("%Gargument to variable-length"
+ " array is too large")
+ : G_("%Gargument to %<alloca%> is too large")),
+ stmt)
&& t.limit != 0)
{
print_decu (t.limit, buff);
inform (loc, "limit is %wu bytes, but argument is %s",
- is_vla ? warn_vla_limit : adjusted_alloca_limit,
- buff);
+ is_vla ? warn_vla_limit : adjusted_alloca_limit,
+ buff);
}
}
break;
case ALLOCA_BOUND_UNKNOWN:
warning_at (loc, wcode,
- is_vla ? G_("variable-length array bound is unknown")
- : G_("%<alloca%> bound is unknown"));
+ (is_vla
+ ? G_("%Gvariable-length array bound is unknown")
+ : G_("%G%<alloca%> bound is unknown")),
+ stmt);
break;
case ALLOCA_UNBOUNDED:
warning_at (loc, wcode,
- is_vla ? G_("unbounded use of variable-length array")
- : G_("unbounded use of %<alloca%>"));
+ (is_vla
+ ? G_("%Gunbounded use of variable-length array")
+ : G_("%Gunbounded use of %<alloca%>")),
+ stmt);
break;
case ALLOCA_IN_LOOP:
gcc_assert (!is_vla);
- warning_at (loc, wcode, "use of %<alloca%> within a loop");
+ warning_at (loc, wcode,
+ "%Guse of %<alloca%> within a loop", stmt);
break;
case ALLOCA_CAST_FROM_SIGNED:
gcc_assert (invalid_casted_type != NULL_TREE);
warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length array "
- "may be too large due to "
- "conversion from %qT to %qT")
- : G_("argument to %<alloca%> may be too large "
- "due to conversion from %qT to %qT"),
- invalid_casted_type, size_type_node);
+ (is_vla
+ ? G_("%Gargument to variable-length array "
+ "may be too large due to "
+ "conversion from %qT to %qT")
+ : G_("%Gargument to %<alloca%> may be too large "
+ "due to conversion from %qT to %qT")),
+ stmt, invalid_casted_type, size_type_node);
break;
case ALLOCA_ARG_IS_ZERO:
warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length array "
- "is zero")
- : G_("argument to %<alloca%> is zero"));
+ (is_vla
+ ? G_("%Gargument to variable-length array "
+ "is zero")
+ : G_("%Gargument to %<alloca%> is zero")),
+ stmt);
break;
default:
gcc_unreachable ();
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than-3.c b/gcc/testsuite/gcc.dg/Walloca-larger-than-3.c
new file mode 100644
index 00000000000..c298d6c4c75
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Walloca-larger-than-3.c
@@ -0,0 +1,48 @@
+/* PR middle-end/94004 - missing -Walloca on calls to alloca due
+ to -Wno-system-headers
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Walloca-larger-than=8 -ftrack-macro-expansion=0" }
+ { dg-require-effective-target alloca } */
+
+#if __has_include (<alloca.h>)
+# include <alloca.h>
+#endif
+
+#ifndef alloca
+// Simulate a definition in a system header.
+# 13 "/usr/include/alloca.h"
+# define alloca(n) __builtin_alloca (n)
+# 15 "Walloca-larger-than-3.c"
+#endif
+
+
+void sink (void*, ...);
+
+void call_builtin_alloca (int n)
+{
+ if (n < 9)
+ n = 9;
+ void *p = __builtin_alloca (n); // { dg-warning "\\\[-Walloca-larger-than" }
+ sink (p, 0);
+}
+
+void call_alloca_sys_hdr (int n)
+{
+ if (n < 9)
+ n = 9;
+ void *p = alloca (n); // { dg-warning "\\\[-Walloca-larger-than" }
+ sink (p, 1);
+}
+
+static inline void inline_call_alloca (int n)
+{
+ if (n > 9)
+ n = 9;
+ void *p = alloca (n); // { dg-warning "\\\[-Walloca-larger-than" }
+ sink (p, 2);
+}
+
+void make_inlined_call (void)
+{
+ inline_call_alloca (10);
+}
diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c
new file mode 100644
index 00000000000..de99afbe56e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-4.c
@@ -0,0 +1,30 @@
+/* PR middle-end/94004 - missing -Walloca on calls to alloca due
+ to -Wno-system-headers
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wvla-larger-than=31 -ftrack-macro-expansion=0" }
+ { dg-require-effective-target alloca } */
+
+void sink (void*, ...);
+
+static inline void inline_use_vla (unsigned n)
+{
+ if (n > 32)
+ n = 32;
+ char a[n]; // { dg-warning "\\\[-Wvla-larger-than" }
+ sink (a, 2);
+}
+
+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
+}
+
+void call_inline (void)
+{
+ use_inlined_vla (31);
+}
+
+/* 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 } */