c.opt (-Wframe-address): New warning option.
authorMartin Sebor <msebor@redhat.com>
Sun, 2 Aug 2015 23:14:18 +0000 (23:14 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Sun, 2 Aug 2015 23:14:18 +0000 (17:14 -0600)
gcc/ChangeLog
2015-07-28  Martin Sebor  <msebor@redhat.com>

    * c-family/c.opt (-Wframe-address): New warning option.
    * doc/invoke.texi (Wframe-address): Document it.
    * doc/extend.texi (__builtin_frame_address, __builtin_return_address):
    Clarify possible effects of calling the functions with non-zero
    arguments and mention -Wframe-address.
    * builtins.c (expand_builtin_frame_address): Handle -Wframe-address.

gcc/testsuite/ChangeLog
2015-07-28  Martin Sebor  <msebor@redhat.com>

    * g++.dg/Wframe-address-in-Wall.C: New test.
    * g++.dg/Wframe-address.C: New test.
    * g++.dg/Wno-frame-address.C: New test.
    * gcc.dg/Wframe-address-in-Wall.c: New test.
    * gcc.dg/Wframe-address.c: New test.
    * gcc.dg/Wno-frame-address.c: New test.

From-SVN: r226480

12 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/c-family/c.opt
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/Wframe-address-in-Wall.C [new file with mode: 0644]
gcc/testsuite/g++.dg/Wframe-address.C [new file with mode: 0644]
gcc/testsuite/g++.dg/Wno-frame-address.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wframe-address-in-Wall.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wframe-address.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wno-frame-address.c [new file with mode: 0644]

index c565bfc1b41e8b4a4c9c30fdc9eb1dae15b35b80..25cb049708e4dd469f9e47082b4caa4a782cec10 100644 (file)
@@ -1,3 +1,12 @@
+2015-08-02  Martin Sebor  <msebor@redhat.com>
+
+       * c-family/c.opt (-Wframe-address): New warning option.
+       * doc/invoke.texi (Wframe-address): Document it.
+       * doc/extend.texi (__builtin_frame_address, __builtin_return_address):
+       Clarify possible effects of calling the functions with non-zero
+       arguments and mention -Wframe-address.
+       * builtins.c (expand_builtin_frame_address): Handle -Wframe-address.
+
 2015-08-01  Michael Collison  <michael.collison@linaro.org
            Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
index d7eb65f930beab0a5593a164ccfcc9b5edba4f76..eb7b7b2bbacff325ad1ad67760dc2208e6a795eb 100644 (file)
@@ -4551,34 +4551,38 @@ expand_builtin_frame_address (tree fndecl, tree exp)
 {
   /* The argument must be a nonnegative integer constant.
      It counts the number of frames to scan up the stack.
-     The value is the return address saved in that frame.  */
+     The value is either the frame pointer value or the return
+     address saved in that frame.  */
   if (call_expr_nargs (exp) == 0)
     /* Warning about missing arg was already issued.  */
     return const0_rtx;
   else if (! tree_fits_uhwi_p (CALL_EXPR_ARG (exp, 0)))
     {
-      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
-       error ("invalid argument to %<__builtin_frame_address%>");
-      else
-       error ("invalid argument to %<__builtin_return_address%>");
+      error ("invalid argument to %qD", fndecl);
       return const0_rtx;
     }
   else
     {
-      rtx tem
-       = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
-                                     tree_to_uhwi (CALL_EXPR_ARG (exp, 0)));
+      /* Number of frames to scan up the stack.  */
+      unsigned HOST_WIDE_INT count = tree_to_uhwi (CALL_EXPR_ARG (exp, 0));
+
+      rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl), count);
 
       /* Some ports cannot access arbitrary stack frames.  */
       if (tem == NULL)
        {
-         if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
-           warning (0, "unsupported argument to %<__builtin_frame_address%>");
-         else
-           warning (0, "unsupported argument to %<__builtin_return_address%>");
+         warning (0, "unsupported argument to %qD", fndecl);
          return const0_rtx;
        }
 
+      if (count)
+       {
+         /* Warn since no effort is made to ensure that any frame
+            beyond the current one exists or can be safely reached.  */
+         warning (OPT_Wframe_address, "calling %qD with "
+                  "a nonzero argument is unsafe", fndecl);
+       }
+
       /* For __builtin_frame_address, return what we've got.  */
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
        return tem;
index cb3af48dc4766b00a0c5d9ed012aaed917e82109..4679038c90bd31292a6e1cc2e930f9286e662d8e 100644 (file)
@@ -295,6 +295,10 @@ Wbool-compare
 C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
 Warn about boolean expression compared with an integer value different from true/false
 
+Wframe-address
+C ObjC C++ ObjC++ Var(warn_frame_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn when __builtin_frame_address or __builtin_return_address is used unsafely
+
 Wbuiltin-macro-redefined
 C ObjC C++ ObjC++ CPP(warn_builtin_macro_redefined) CppReason(CPP_W_BUILTIN_MACRO_REDEFINED) Var(cpp_warn_builtin_macro_redefined) Init(1) Warning
 Warn when a built-in preprocessor macro is undefined or redefined
index b18d8fb11e034d32379c9a90910d2f71f90c99e8..9bf292ecdef1e584891855d14a28e7a40dc1416d 100644 (file)
@@ -8652,8 +8652,11 @@ to determine if the top of the stack has been reached.
 Additional post-processing of the returned value may be needed, see
 @code{__builtin_extract_return_addr}.
 
-This function should only be used with a nonzero argument for debugging
-purposes.
+Calling this function with a nonzero argument can have unpredictable
+effects, including crashing the calling program.  As a result, calls
+that are considered unsafe are diagnosed when the @option{-Wframe-address}
+option is in effect.  Such calls should only be made in debugging
+situations.
 @end deftypefn
 
 @deftypefn {Built-in Function} {void *} __builtin_extract_return_addr (void *@var{addr})
@@ -8691,8 +8694,11 @@ any function other than the current one; in such cases, or when the top
 of the stack has been reached, this function returns @code{0} if
 the first frame pointer is properly initialized by the startup code.
 
-This function should only be used with a nonzero argument for debugging
-purposes.
+Calling this function with a nonzero argument can have unpredictable
+effects, including crashing the calling program.  As a result, calls
+that are considered unsafe are diagnosed when the @option{-Wframe-address}
+option is in effect.  Such calls should only be made in debugging
+situations.
 @end deftypefn
 
 @node Vector Extensions
index 7b5d86b62bb633d7382743d50587187438f06f80..f7daa02d6587cc2a99e27322b41d88cfcbbd10fc 100644 (file)
@@ -241,7 +241,7 @@ Objective-C and Objective-C++ Dialects}.
 -pedantic-errors @gol
 -w  -Wextra  -Wall  -Waddress  -Waggregate-return  @gol
 -Waggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol
--Wbool-compare @gol
+-Wbool-compare -Wframe-address @gol
 -Wno-attributes -Wno-builtin-macro-redefined @gol
 -Wc90-c99-compat -Wc99-c11-compat @gol
 -Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align  -Wcast-qual  @gol
@@ -4462,6 +4462,13 @@ if ((n > 1) == 2) @{ @dots{} @}
 @end smallexample
 This warning is enabled by @option{-Wall}.
 
+@item -Wframe-address
+@opindex Wno-frame-address
+@opindex Wframe-address
+Warn when the @samp{__builtin_frame_address} or @samp{__builtin_return_address}
+is called with an argument greater than 0.  Such calls may return indeterminate
+values or crash the program.  The warning is included in @option{-Wall}.
+
 @item -Wno-discarded-qualifiers @r{(C and Objective-C only)}
 @opindex Wno-discarded-qualifiers
 @opindex Wdiscarded-qualifiers
index 82aa654a8bc54fbec0f9460c768990d5ad96a028..55bfb355cd850e7dba59100e131a2df08b7837f9 100644 (file)
@@ -1,3 +1,12 @@
+2015-08-02  Martin Sebor  <msebor@redhat.com>
+
+        * g++.dg/Wframe-address-in-Wall.C: New test.
+        * g++.dg/Wframe-address.C: New test.
+        * g++.dg/Wno-frame-address.C: New test.
+        * gcc.dg/Wframe-address-in-Wall.c: New test.
+        * gcc.dg/Wframe-address.c: New test.
+        * gcc.dg/Wno-frame-address.c: New test.
+
 2015-08-02  Patrick Palka  <ppalka@gcc.gnu.org>
 
        * c-c++-common/Wmisleading-indentation.c: Add more tests.
diff --git a/gcc/testsuite/g++.dg/Wframe-address-in-Wall.C b/gcc/testsuite/g++.dg/Wframe-address-in-Wall.C
new file mode 100644 (file)
index 0000000..2d945e5
--- /dev/null
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+// Verify that -Wframe-address is included in -Wall.
+
+void* test_builtin_address (unsigned i)
+{
+  void* const ba[] = {
+    __builtin_frame_address (4), // { dg-warning "builtin_frame_address" }
+    __builtin_return_address (4) // { dg-warning "builtin_return_address" }
+  };
+
+  return ba [i];
+}
diff --git a/gcc/testsuite/g++.dg/Wframe-address.C b/gcc/testsuite/g++.dg/Wframe-address.C
new file mode 100644 (file)
index 0000000..229004e
--- /dev/null
@@ -0,0 +1,70 @@
+// { dg-do compile }
+// { dg-options "-Wframe-address" }
+
+static void* const fa[] = {
+  __builtin_frame_address (0),
+  __builtin_frame_address (1), // { dg-warning "builtin_frame_address" }
+  __builtin_frame_address (2), // { dg-warning "builtin_frame_address" }
+  __builtin_frame_address (3), // { dg-warning "builtin_frame_address" }
+  __builtin_frame_address (4)  // { dg-warning "builtin_frame_address" }
+};
+
+
+static void* const ra[] = {
+  __builtin_return_address (0),
+  __builtin_return_address (1), // { dg-warning "builtin_return_address" }
+  __builtin_return_address (2), // { dg-warning "builtin_return_address" }
+  __builtin_return_address (3), // { dg-warning "builtin_return_address" }
+  __builtin_return_address (4)  // { dg-warning "builtin_return_address" }
+};
+
+
+void* __attribute__ ((noclone, noinline))
+test_builtin_frame_address (unsigned i)
+{
+  void* const fa[] = {
+    __builtin_frame_address (0),
+    __builtin_frame_address (1), // { dg-warning "builtin_frame_address" }
+    __builtin_frame_address (2), // { dg-warning "builtin_frame_address" }
+    __builtin_frame_address (3), // { dg-warning "builtin_frame_address" }
+    __builtin_frame_address (4)  // { dg-warning "builtin_frame_address" }
+  };
+
+  return fa [i];
+}
+
+
+void* __attribute__ ((noclone, noinline))
+test_builtin_return_address (unsigned i)
+{
+  void* const ra[] = {
+    __builtin_return_address (0),
+    __builtin_return_address (1), // { dg-warning "builtin_return_address" }
+    __builtin_return_address (2), // { dg-warning "builtin_return_address" }
+    __builtin_return_address (3), // { dg-warning "builtin_return_address" }
+    __builtin_return_address (4)  // { dg-warning "builtin_return_address" }
+  };
+  return ra [i];
+}
+
+
+int main ()
+{
+  test_builtin_frame_address (0);
+
+  test_builtin_return_address (0);
+
+  void* const a[] = {
+    __builtin_frame_address (0),
+    __builtin_frame_address (1), // { dg-warning "builtin_frame_address" }
+    __builtin_frame_address (2), // { dg-warning "builtin_frame_address" }
+    __builtin_frame_address (3), // { dg-warning "builtin_frame_address" }
+    __builtin_frame_address (4), // { dg-warning "builtin_frame_address" }
+
+    __builtin_return_address (0),
+    __builtin_return_address (1), // { dg-warning "builtin_return_address" }
+    __builtin_return_address (2), // { dg-warning "builtin_return_address" }
+    __builtin_return_address (3), // { dg-warning "builtin_return_address" }
+    __builtin_return_address (4)  // { dg-warning "builtin_return_address" }
+  };
+}
diff --git a/gcc/testsuite/g++.dg/Wno-frame-address.C b/gcc/testsuite/g++.dg/Wno-frame-address.C
new file mode 100644 (file)
index 0000000..b19cb43
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-do compile }
+// { dg-options "-Werror" }
+
+// Verify that -Wframe-address is not enabled by default by enabling
+// -Werror and verifying the test still compiles.
+#include "Wframe-address.C"
diff --git a/gcc/testsuite/gcc.dg/Wframe-address-in-Wall.c b/gcc/testsuite/gcc.dg/Wframe-address-in-Wall.c
new file mode 100644 (file)
index 0000000..70da9c8
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+/* Verify that -Wframe-address is included in -Wall.  */
+
+void* test_builtin_address (unsigned i)
+{
+  void* const ba[] = {
+    __builtin_frame_address (4), /* { dg-warning "builtin_frame_address" } */
+    __builtin_return_address (4)  /* { dg-warning "builtin_return_address" } */
+  };
+
+  return ba [i];
+}
diff --git a/gcc/testsuite/gcc.dg/Wframe-address.c b/gcc/testsuite/gcc.dg/Wframe-address.c
new file mode 100644 (file)
index 0000000..7481baf
--- /dev/null
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-Wframe-address" } */
+
+void* __attribute__ ((noclone, noinline))
+test_builtin_frame_address (unsigned i)
+{
+  void* const fa[] = {
+    __builtin_frame_address (0),
+    __builtin_frame_address (1), /* { dg-warning "builtin_frame_address" } */
+    __builtin_frame_address (2), /* { dg-warning "builtin_frame_address" } */
+    __builtin_frame_address (3), /* { dg-warning "builtin_frame_address" } */
+    __builtin_frame_address (4)  /* { dg-warning "builtin_frame_address" } */
+  };
+
+  return fa [i];
+}
+
+
+void* __attribute__ ((noclone, noinline))
+test_builtin_return_address (unsigned i)
+{
+  void* const ra[] = {
+    __builtin_return_address (0),
+    __builtin_return_address (1), /* { dg-warning "builtin_return_address" } */
+    __builtin_return_address (2), /* { dg-warning "builtin_return_address" } */
+    __builtin_return_address (3), /* { dg-warning "builtin_return_address" } */
+    __builtin_return_address (4)  /* { dg-warning "builtin_return_address" } */
+  };
+  return ra [i];
+}
+
+
+int main (void)
+{
+  test_builtin_frame_address (0);
+
+  test_builtin_return_address (0);
+
+  void* const a[] = {
+    __builtin_frame_address (0),
+    __builtin_frame_address (1), /* { dg-warning "builtin_frame_address" } */
+    __builtin_frame_address (2), /* { dg-warning "builtin_frame_address" } */
+    __builtin_frame_address (3), /* { dg-warning "builtin_frame_address" } */
+    __builtin_frame_address (4), /* { dg-warning "builtin_frame_address" } */
+
+    __builtin_return_address (0),
+    __builtin_return_address (1), /* { dg-warning "builtin_return_address" } */
+    __builtin_return_address (2), /* { dg-warning "builtin_return_address" } */
+    __builtin_return_address (3), /* { dg-warning "builtin_return_address" } */
+    __builtin_return_address (4)  /* { dg-warning "builtin_return_address" } */
+  };
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wno-frame-address.c b/gcc/testsuite/gcc.dg/Wno-frame-address.c
new file mode 100644 (file)
index 0000000..f48b91a
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Werror" } */
+
+/* Verify that -Wframe-address is not enabled by default by enabling
+   -Werror and verifying the test still compiles.  */
+#include "Wframe-address.c"