[PATCH v7] 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]> --- v7: - Replace bad include of "lto-opts.cc" to "opts.h". 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..f3bbe7da554 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 "../opts.h" /* 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