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

Reply via email to