hardcfr: make builtin_return tests more portable [PR112334]
Checks
Commit Message
Rework __builtin_return tests to explicitly call __builtin_apply and
use its return value rather than anything else. Also require
untyped_assembly. Avoid the noise out of exceptions escaping the
builtin-applied function, but add a test to cover their effects as
well.
Regstrapped on x86_64-linux-gnu. Also tested on arm-eabi, but it's
*not* enough (or needed) to fix the PR, there's another bug lurking
there, with a separate patch coming up. Regardless, is this ok to
install?
for gcc/testsuite/ChangeLog
PR target/112334
* c-c++-common/torture/harden-cfr-bret.c: Rework for stricter
untyped_return requirements. Require untyped_assembly.
* c-c++-common/torture/harden-cfr-bret-except.c: New.
* c-c++-common/torture/harden-cfr-bret-always.c: Require
untyped_assembly.
* c-c++-common/torture/harden-cfr-bret-never.c: Likewise.
* c-c++-common/torture/harden-cfr-bret-noopt.c: Likewise.
* c-c++-common/torture/harden-cfr-bret-noret.c: Likewise.
* c-c++-common/torture/harden-cfr-bret-no-xthrow.c: Likewise.
* c-c++-common/torture/harden-cfr-bret-nothrow.c: Likewise.
* c-c++-common/torture/harden-cfr-bret-retcl.c: Likewise.
---
.../c-c++-common/torture/harden-cfr-bret-always.c | 3 ++-
.../c-c++-common/torture/harden-cfr-bret-except.c | 17 +++++++++++++++
.../c-c++-common/torture/harden-cfr-bret-never.c | 3 ++-
.../torture/harden-cfr-bret-no-xthrow.c | 3 ++-
.../c-c++-common/torture/harden-cfr-bret-noopt.c | 3 ++-
.../c-c++-common/torture/harden-cfr-bret-noret.c | 3 ++-
.../c-c++-common/torture/harden-cfr-bret-nothrow.c | 3 ++-
.../c-c++-common/torture/harden-cfr-bret-retcl.c | 3 ++-
.../c-c++-common/torture/harden-cfr-bret.c | 23 ++++++++++++++++----
.../c-c++-common/torture/harden-cfr-noret.c | 2 +-
10 files changed, 50 insertions(+), 13 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/torture/harden-cfr-bret-except.c
Comments
On Fri, Dec 1, 2023 at 1:58 PM Alexandre Oliva <oliva@adacore.com> wrote:
>
>
> Rework __builtin_return tests to explicitly call __builtin_apply and
> use its return value rather than anything else. Also require
> untyped_assembly. Avoid the noise out of exceptions escaping the
> builtin-applied function, but add a test to cover their effects as
> well.
>
> Regstrapped on x86_64-linux-gnu. Also tested on arm-eabi, but it's
> *not* enough (or needed) to fix the PR, there's another bug lurking
> there, with a separate patch coming up. Regardless, is this ok to
> install?
OK.
>
> for gcc/testsuite/ChangeLog
>
> PR target/112334
> * c-c++-common/torture/harden-cfr-bret.c: Rework for stricter
> untyped_return requirements. Require untyped_assembly.
> * c-c++-common/torture/harden-cfr-bret-except.c: New.
> * c-c++-common/torture/harden-cfr-bret-always.c: Require
> untyped_assembly.
> * c-c++-common/torture/harden-cfr-bret-never.c: Likewise.
> * c-c++-common/torture/harden-cfr-bret-noopt.c: Likewise.
> * c-c++-common/torture/harden-cfr-bret-noret.c: Likewise.
> * c-c++-common/torture/harden-cfr-bret-no-xthrow.c: Likewise.
> * c-c++-common/torture/harden-cfr-bret-nothrow.c: Likewise.
> * c-c++-common/torture/harden-cfr-bret-retcl.c: Likewise.
> ---
> .../c-c++-common/torture/harden-cfr-bret-always.c | 3 ++-
> .../c-c++-common/torture/harden-cfr-bret-except.c | 17 +++++++++++++++
> .../c-c++-common/torture/harden-cfr-bret-never.c | 3 ++-
> .../torture/harden-cfr-bret-no-xthrow.c | 3 ++-
> .../c-c++-common/torture/harden-cfr-bret-noopt.c | 3 ++-
> .../c-c++-common/torture/harden-cfr-bret-noret.c | 3 ++-
> .../c-c++-common/torture/harden-cfr-bret-nothrow.c | 3 ++-
> .../c-c++-common/torture/harden-cfr-bret-retcl.c | 3 ++-
> .../c-c++-common/torture/harden-cfr-bret.c | 23 ++++++++++++++++----
> .../c-c++-common/torture/harden-cfr-noret.c | 2 +-
> 10 files changed, 50 insertions(+), 13 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/torture/harden-cfr-bret-except.c
>
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-always.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-always.c
> index 779896c60e846..3406c4e6ef9dc 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-always.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-always.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even enabling all checks before noreturn calls (leaving
> returning calls enabled), we get checks before __builtin_return without
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-except.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-except.c
> new file mode 100644
> index 0000000000000..3acb61cb75a77
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-except.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fharden-control-flow-redundancy -fexceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
> +
> +/* Check that, with exceptions enabled, even in C, the calls initiated by
> + builtin_apply are enclosed in cleanup handlers that add extra checks.
> + Unfortunately, declaring foobar as nothrow is not enough to avoid the
> + handler around the builtin_apply call, so the other bret tests all use
> + -fno-exceptions. */
> +
> +#include "harden-cfr-bret.c"
> +
> +/* With exceptions, we get an extra check per function, to check before
> + propagating exceptions, so it's 3 in f and 2 in g. */
> +/* { dg-final { scan-tree-dump-times "__hardcfr_check" 5 "hardcfr" } } */
> +/* The extra check in g also removes the possibility of inlining the check. */
> +/* { dg-final { scan-tree-dump-times "__builtin_trap" 0 "hardcfr" } } */
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-never.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-never.c
> index 49ce17f5b937c..7f8fb64138df1 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-never.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-never.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even enabling checks before never noreturn calls (leaving
> returning calls enabled), we get checks before __builtin_return without
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-no-xthrow.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-no-xthrow.c
> index 78e5bf4143927..07588e8d3c341 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-no-xthrow.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-no-xthrow.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=no-xthrow -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=no-xthrow -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even enabling checks before no-xthrow-throwing noreturn calls
> (leaving returning calls enabled), we get checks before __builtin_return
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noopt.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noopt.c
> index 1512614791ff2..716d9297c8d94 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noopt.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noopt.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-hardcfr-check-returning-calls -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-hardcfr-check-returning-calls -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even disabling checks before both noreturn and returning
> calls, we still get checks before __builtin_return. */
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noret.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noret.c
> index fd95bb7e3e334..c6d2baa312031 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noret.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-noret.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fno-hardcfr-check-returning-calls -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fno-hardcfr-check-returning-calls -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even disabling checks before returning calls (leaving noreturn
> calls enabled), we still get checks before __builtin_return. */
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-nothrow.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-nothrow.c
> index c5c361234c499..2fd0d82c7ea3e 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-nothrow.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-nothrow.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=nothrow -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=nothrow -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even enabling checks before nothrow noreturn calls (leaving
> returning calls enabled), we get checks before __builtin_return without
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-retcl.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-retcl.c
> index 137dfbb95d6bb..b070294fde8ad 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-retcl.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret-retcl.c
> @@ -1,5 +1,6 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> /* Check that, even disabling checks before noreturn calls (leaving returning
> calls enabled), we still get checks before __builtin_return. */
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret.c
> index b459ff6b86491..b6630a6c86695 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-bret.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-bret.c
> @@ -1,14 +1,27 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-require-effective-target untyped_assembly } */
>
> -int f(int i) {
> +extern int foobar (void);
> +
> +#if __cplusplus
> +typedef void (*fnt)(...);
> +#else
> +typedef void (*fnt)();
> +#endif
> +
> +int i;
> +
> +int f(void) {
> if (i)
> - __builtin_return (&i);
> + __builtin_return (__builtin_apply ((fnt)foobar,
> + __builtin_apply_args (), 0));
> return i;
> }
>
> -int g(int i) {
> - __builtin_return (&i);
> +int g(void) {
> + __builtin_return (__builtin_apply ((fnt)foobar,
> + __builtin_apply_args (), 0));
> }
>
> /* Out-of-line checking, before both builtin_return and return in f. */
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c
> index fdd803109a4ae..8c7cc01c0ce68 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
>
> /* Check that we insert checking before all noreturn calls. */
>
>
> --
> Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/
> Free Software Activist GNU Toolchain Engineer
> More tolerance and less prejudice are key for inclusion and diversity
> Excluding neuro-others for not behaving ""normal"" is *not* inclusive
On Dec 1, 2023, Alexandre Oliva <oliva@adacore.com> wrote:
> diff --git a/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c b/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c
> index fdd803109a4ae..8c7cc01c0ce68 100644
> --- a/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c
> +++ b/gcc/testsuite/c-c++-common/torture/harden-cfr-noret.c
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fdump-tree-hardcfr -ffat-lto-objects" } */
> +/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
This one was *not* meant to be modified, it was changed by accident in
my tree and integrated by mistake with the posted patch. Fortunately
the ChangeLog verifier caught the mistake, and I dropped it from the
patch I've just pushed.
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even enabling all checks before noreturn calls (leaving
returning calls enabled), we get checks before __builtin_return without
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fharden-control-flow-redundancy -fexceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
+
+/* Check that, with exceptions enabled, even in C, the calls initiated by
+ builtin_apply are enclosed in cleanup handlers that add extra checks.
+ Unfortunately, declaring foobar as nothrow is not enough to avoid the
+ handler around the builtin_apply call, so the other bret tests all use
+ -fno-exceptions. */
+
+#include "harden-cfr-bret.c"
+
+/* With exceptions, we get an extra check per function, to check before
+ propagating exceptions, so it's 3 in f and 2 in g. */
+/* { dg-final { scan-tree-dump-times "__hardcfr_check" 5 "hardcfr" } } */
+/* The extra check in g also removes the possibility of inlining the check. */
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 0 "hardcfr" } } */
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even enabling checks before never noreturn calls (leaving
returning calls enabled), we get checks before __builtin_return without
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=no-xthrow -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=no-xthrow -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even enabling checks before no-xthrow-throwing noreturn calls
(leaving returning calls enabled), we get checks before __builtin_return
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-hardcfr-check-returning-calls -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-hardcfr-check-returning-calls -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even disabling checks before both noreturn and returning
calls, we still get checks before __builtin_return. */
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fno-hardcfr-check-returning-calls -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fno-hardcfr-check-returning-calls -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even disabling checks before returning calls (leaving noreturn
calls enabled), we still get checks before __builtin_return. */
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=nothrow -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=nothrow -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even enabling checks before nothrow noreturn calls (leaving
returning calls enabled), we get checks before __builtin_return without
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=never -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
/* Check that, even disabling checks before noreturn calls (leaving returning
calls enabled), we still get checks before __builtin_return. */
@@ -1,14 +1,27 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-require-effective-target untyped_assembly } */
-int f(int i) {
+extern int foobar (void);
+
+#if __cplusplus
+typedef void (*fnt)(...);
+#else
+typedef void (*fnt)();
+#endif
+
+int i;
+
+int f(void) {
if (i)
- __builtin_return (&i);
+ __builtin_return (__builtin_apply ((fnt)foobar,
+ __builtin_apply_args (), 0));
return i;
}
-int g(int i) {
- __builtin_return (&i);
+int g(void) {
+ __builtin_return (__builtin_apply ((fnt)foobar,
+ __builtin_apply_args (), 0));
}
/* Out-of-line checking, before both builtin_return and return in f. */
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fdump-tree-hardcfr -ffat-lto-objects" } */
+/* { dg-options "-fharden-control-flow-redundancy -fhardcfr-check-noreturn-calls=always -fno-exceptions -fdump-tree-hardcfr -ffat-lto-objects" } */
/* Check that we insert checking before all noreturn calls. */