[PATCH v6] c-family: honor explicit -Wstrict-aliasing under -fno-strict-aliasing

Sammy Al Hashemi <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
The front-end strict aliasing warning was gated on flag_strict_aliasing,
so -fno-strict-aliasing silenced it even when -Wstrict-aliasing was
requested explicitly.  The front-end check is type-based and does not
need the optimization to be active, so honor an explicit -Wstrict-aliasing
regardless of -fstrict-aliasing.

strict_aliasing_warning temporarily forces flag_strict_aliasing around
the alias set queries so they return meaningful results, but only when
OPTION_SET_P (warn_strict_aliasing) is true.  When the warning is only
implied (for example by -Wall), the previous behavior of staying quiet
under -fno-strict-aliasing is preserved.

This affects only the front-end, type-based diagnostic.  The additional
back-end checking, which uses flow-sensitive points-to information for
multiple-statement cases, still runs only when optimization is enabled.

temp_override and make_temp_override are moved from cp/cp-tree.h to
c-family/c-common.h so the front-end warning code can use them;
in_consteval_if_p_temp_override stays in cp-tree.h as it depends on the
C++-only saved_scope.

gcc/c-family/ChangeLog:

	* c-common.h (class temp_override): Move from cp-tree.h.
	(type_identity_t): Likewise.
	(make_temp_override): Likewise.
	* c-warn.cc (strict_aliasing_warning): Do not gate on
	flag_strict_aliasing.  Temporarily enable it around the alias
	set queries when -Wstrict-aliasing was requested explicitly.

gcc/cp/ChangeLog:

	* cp-tree.h (class temp_override): Move to c-common.h.
	(type_identity_t): Likewise.
	(make_temp_override): Likewise.

gcc/ChangeLog:

	* doc/invoke.texi (-Wstrict-aliasing): Document that the
	front-end type-based checking runs without -fstrict-aliasing
	when the warning is requested explicitly.
	(-Wstrict-aliasing=n): Likewise.

gcc/testsuite/ChangeLog:

	* c-c++-common/Wstrict-aliasing2-with-fno.c: New test.
	* c-c++-common/Wstrict-aliasing3-with-fno.c: New test.

Signed-off-by: Sammy Al Hashemi <[email protected]>
---
v6:
  - Only bypass the -fstrict-aliasing gate when -Wstrict-aliasing was
    requested explicitly (OPTION_SET_P (warn_strict_aliasing)); an
    implicit -Wall no longer triggers it under -fno-strict-aliasing.
  - Fix the temp_override to span the whole function (v5 scoped it to
    an if-block, so it had no effect on the alias-set queries).
  - Soften the -Wstrict-aliasing documentation: scope the claim to the
    front-end type-based check and restore the note about the back-end
    flow-sensitive pass that runs under optimization.
  - Also move make_temp_override to c-common.h alongside temp_override;
    drop the now-redundant per-file c-family/c-common.h includes.
  - ChangeLog: use present tense and trailing periods.

 gcc/c-family/c-common.h                       | 51 +++++++++++++++++++
 gcc/c-family/c-warn.cc                        | 11 +++-
 gcc/cp/cp-tree.h                              | 51 -------------------
 gcc/doc/invoke.texi                           | 24 ++++++---
 .../c-c++-common/Wstrict-aliasing2-with-fno.c | 12 +++++
 .../c-c++-common/Wstrict-aliasing3-with-fno.c | 12 +++++
 6 files changed, 100 insertions(+), 61 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wstrict-aliasing2-with-fno.c
 create mode 100644 gcc/testsuite/c-c++-common/Wstrict-aliasing3-with-fno.c

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d9ed2b070f5..82d61dbc575 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1750,4 +1750,55 @@ namespace selftest {
 } // namespace selftest
 #endif /* #if CHECKING_P */
 
+/* RAII sentinel that saves the value of a variable, optionally
+   overrides it right away, and restores its value when the sentinel
+   id destructed.  */
+
+template <typename T>
+class temp_override
+{
+  T& overridden_variable;
+  T saved_value;
+public:
+  temp_override(T& var) : overridden_variable (var), saved_value (var) {}
+  temp_override(T& var, T overrider)
+    : overridden_variable (var), saved_value (var)
+  {
+    overridden_variable = overrider;
+  }
+  ~temp_override() { overridden_variable = saved_value; }
+};
+
+/* Wrapping a template parameter in type_identity_t hides it from template
+   argument deduction.  */
+#if __cpp_lib_type_identity
+using std::type_identity_t;
+#else
+template <typename T>
+struct type_identity { typedef T type; };
+template <typename T>
+using type_identity_t = typename type_identity<T>::type;
+#endif
+
+/* Object generator function for temp_override, so you don't need to write the
+   type of the object as a template argument.
+
+   Use as auto x = make_temp_override (flag); */
+
+template <typename T>
+inline temp_override<T>
+make_temp_override (T& var)
+{
+  return { var };
+}
+
+/* Likewise, but use as auto x = make_temp_override (flag, value); */
+
+template <typename T>
+inline temp_override<T>
+make_temp_override (T& var, type_identity_t<T> overrider)
+{
+  return { var, overrider };
+}
+
 #endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 1767d2dc090..4374e7e4752 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "langhooks.h"
 #include "gcc-urlifier.h"
+#include "../lto-opts.cc"
 
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
@@ -701,8 +702,7 @@ strict_aliasing_warning (location_t loc, tree type, tree expr)
   STRIP_NOPS (expr);
   tree otype = TREE_TYPE (expr);
 
-  if (!(flag_strict_aliasing
-	&& POINTER_TYPE_P (type)
+  if (!(POINTER_TYPE_P (type)
 	&& POINTER_TYPE_P (otype)
 	&& !VOID_TYPE_P (TREE_TYPE (type)))
       /* If the type we are casting to is a ref-all pointer
@@ -710,6 +710,13 @@ strict_aliasing_warning (location_t loc, tree type, tree expr)
       || TYPE_REF_CAN_ALIAS_ALL (type))
     return false;
 
+  /* Temporarily enable strict aliasing so that the alias set query
+     functions return meaningful results for the warning.
+     Only do this if the user explicitly asked for `-Wstrict-aliasing`  */
+  temp_override<int> save (flag_strict_aliasing,
+			   OPTION_SET_P (warn_strict_aliasing) ?
+			   1 : flag_strict_aliasing);
+
   if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR
       && (DECL_P (TREE_OPERAND (expr, 0))
 	  || handled_component_p (TREE_OPERAND (expr, 0))))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bf477a67a34..9ad4c327e99 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2255,57 +2255,6 @@ public:
   }
 };
 
-/* RAII sentinel that saves the value of a variable, optionally
-   overrides it right away, and restores its value when the sentinel
-   id destructed.  */
-
-template <typename T>
-class temp_override
-{
-  T& overridden_variable;
-  T saved_value;
-public:
-  temp_override(T& var) : overridden_variable (var), saved_value (var) {}
-  temp_override(T& var, T overrider)
-    : overridden_variable (var), saved_value (var)
-  {
-    overridden_variable = overrider;
-  }
-  ~temp_override() { overridden_variable = saved_value; }
-};
-
-/* Wrapping a template parameter in type_identity_t hides it from template
-   argument deduction.  */
-#if __cpp_lib_type_identity
-using std::type_identity_t;
-#else
-template <typename T>
-struct type_identity { typedef T type; };
-template <typename T>
-using type_identity_t = typename type_identity<T>::type;
-#endif
-
-/* Object generator function for temp_override, so you don't need to write the
-   type of the object as a template argument.
-
-   Use as auto x = make_temp_override (flag); */
-
-template <typename T>
-inline temp_override<T>
-make_temp_override (T& var)
-{
-  return { var };
-}
-
-/* Likewise, but use as auto x = make_temp_override (flag, value); */
-
-template <typename T>
-inline temp_override<T>
-make_temp_override (T& var, type_identity_t<T> overrider)
-{
-  return { var, overrider };
-}
-
 /* temp_override for in_consteval_if_p, which can't use make_temp_override
    because it is a bitfield.  */
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 339d1d2c97a..fe18ba24fe6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8674,17 +8674,25 @@ the implementation.
 @opindex Wstrict-aliasing
 @opindex Wno-strict-aliasing
 @item -Wstrict-aliasing
-This option is only active when @option{-fstrict-aliasing} is active.
-It warns about code that might break the strict aliasing rules that the
-compiler is using for optimization.  The warning does not catch all
-cases, but does attempt to catch the more common pitfalls.  It is
-included in @option{-Wall}.
+This option warns about code that might break the strict aliasing rules
+that the compiler uses for optimization.  The type-based checking done
+in the front end is performed even when @option{-fstrict-aliasing} is
+not active, provided @option{-Wstrict-aliasing} is requested explicitly;
+it is not performed for @option{-fno-strict-aliasing -Wall} alone.  When
+optimization is enabled, the warning also runs in the back end, where it
+handles multiple-statement cases using flow-sensitive points-to
+information.  The warning does not catch all cases, but does attempt to
+catch the more common pitfalls.  It is included in @option{-Wall}.
 It is equivalent to @option{-Wstrict-aliasing=3}.
 
 @item -Wstrict-aliasing=@var{n}
-This option is only active when @option{-fstrict-aliasing} is active.
-It warns about code that might break the strict aliasing rules that the
-compiler is using for optimization.
+This option warns about code that might break the strict aliasing rules
+that the compiler uses for optimization.  The type-based checking done
+in the front end is performed even when @option{-fstrict-aliasing} is
+not active, provided @option{-Wstrict-aliasing} is requested explicitly.
+When optimization is enabled, the warning also runs in the back end,
+where it handles multiple-statement cases using flow-sensitive points-to
+information.
 Higher levels correspond to higher accuracy (fewer false positives).
 Higher levels also correspond to more effort, similar to the way @option{-O}
 works.
diff --git a/gcc/testsuite/c-c++-common/Wstrict-aliasing2-with-fno.c b/gcc/testsuite/c-c++-common/Wstrict-aliasing2-with-fno.c
new file mode 100644
index 00000000000..c7b223ed91b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wstrict-aliasing2-with-fno.c
@@ -0,0 +1,12 @@
+/* Test the usage of option -Wstrict-aliasing.  */
+/* Make sure it's enabled even when -fno-strict-aliasing.  */
+/* Set -Wstrict-aliasing=2 so it warns on casts */
+/* { dg-do compile } */
+/* { dg-options "-Wstrict-aliasing=2 -fno-strict-aliasing" } */
+
+int main(int argc, char *argv[])
+{
+    int x;
+    float *q = (float*) &x; /* { dg-warning "strict-aliasing" } */
+    return x;
+}
diff --git a/gcc/testsuite/c-c++-common/Wstrict-aliasing3-with-fno.c b/gcc/testsuite/c-c++-common/Wstrict-aliasing3-with-fno.c
new file mode 100644
index 00000000000..e999b13aec4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wstrict-aliasing3-with-fno.c
@@ -0,0 +1,12 @@
+/* Test the usage of option -Wstrict-aliasing.  */
+/* Make sure it's enabled even when -fno-strict-aliasing.  */
+/* Set -Wstrict-aliasing=3 so that it only warns on dereference */
+/* { dg-do compile } */
+/* { dg-options "-Wstrict-aliasing=3 -fno-strict-aliasing" } */
+
+int main(int argc, char *argv[])
+{
+    int x;
+    *(float*) &x = 42; /* { dg-warning "strict-aliasing" } */
+    return x;
+}
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.