From: Alexandre Oliva <oliva@adacore.com>
To: gcc-patches@gcc.gnu.org
Cc: Jeremy Bennett <jeremy.bennett@embecosm.com>,
Craig Blackmore <craig.blackmore@embecosm.com>,
Graham Markall <graham.markall@embecosm.com>,
Martin Jambor <mjambor@suse.cz>, Jan Hubicka <hubicka@ucw.cz>,
Richard Biener <richard.guenther@gmail.com>,
Jim Wilson <wilson@tuliptree.org>
Subject: [PATCH v2 02/10] Introduce strub: torture tests for C and C++
Date: Fri, 29 Jul 2022 03:25:15 -0300 [thread overview]
Message-ID: <ortu70mo50.fsf_-_@lxoliva.fsfla.org> (raw)
In-Reply-To: <or35eko33q.fsf_-_@lxoliva.fsfla.org> (Alexandre Oliva's message of "Fri, 29 Jul 2022 03:16:41 -0300")
for gcc/testsuite/ChangeLog
* c-c++-common/torture/strub-callable1.c: New.
* c-c++-common/torture/strub-callable2.c: New.
* c-c++-common/torture/strub-const1.c: New.
* c-c++-common/torture/strub-const2.c: New.
* c-c++-common/torture/strub-const3.c: New.
* c-c++-common/torture/strub-const4.c: New.
* c-c++-common/torture/strub-data1.c: New.
* c-c++-common/torture/strub-data2.c: New.
* c-c++-common/torture/strub-data3.c: New.
* c-c++-common/torture/strub-data4.c: New.
* c-c++-common/torture/strub-data5.c: New.
* c-c++-common/torture/strub-indcall1.c: New.
* c-c++-common/torture/strub-indcall2.c: New.
* c-c++-common/torture/strub-indcall3.c: New.
* c-c++-common/torture/strub-inlinable1.c: New.
* c-c++-common/torture/strub-inlinable2.c: New.
* c-c++-common/torture/strub-ptrfn1.c: New.
* c-c++-common/torture/strub-ptrfn2.c: New.
* c-c++-common/torture/strub-ptrfn3.c: New.
* c-c++-common/torture/strub-ptrfn4.c: New.
* c-c++-common/torture/strub-pure1.c: New.
* c-c++-common/torture/strub-pure2.c: New.
* c-c++-common/torture/strub-pure3.c: New.
* c-c++-common/torture/strub-pure4.c: New.
* c-c++-common/torture/strub-run1.c: New.
* c-c++-common/torture/strub-run2.c: New.
* c-c++-common/torture/strub-run3.c: New.
* c-c++-common/torture/strub-run4.c: New.
* c-c++-common/torture/strub-run4c.c: New.
* c-c++-common/torture/strub-run4d.c: New.
* c-c++-common/torture/strub-run4i.c: New.
diff --git a/gcc/testsuite/c-c++-common/torture/strub-callable1.c b/gcc/testsuite/c-c++-common/torture/strub-callable1.c
new file mode 100644
index 0000000000000..b5e45ab0525ad
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-callable1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict" } */
+
+/* Check that strub and non-strub functions can be called from non-strub
+ contexts, and that strub and callable functions can be called from strub
+ contexts. */
+
+#define OMIT_IMPERMISSIBLE_CALLS 1
+#include "strub-callable2.c"
diff --git a/gcc/testsuite/c-c++-common/torture/strub-callable2.c b/gcc/testsuite/c-c++-common/torture/strub-callable2.c
new file mode 100644
index 0000000000000..96aa7fe4b07f7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-callable2.c
@@ -0,0 +1,264 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict" } */
+
+/* Check that impermissible (cross-strub-context) calls are reported. */
+
+extern int __attribute__ ((__strub__ ("callable"))) xcallable (void);
+extern int __attribute__ ((__strub__ ("internal"))) xinternal (void);
+extern int __attribute__ ((__strub__ ("at-calls"))) xat_calls (void);
+extern int __attribute__ ((__strub__ ("disabled"))) xdisabled (void);
+
+int __attribute__ ((__strub__ ("callable"))) callable (void);
+int __attribute__ ((__strub__ ("internal"))) internal (void);
+int __attribute__ ((__strub__ ("at-calls"))) at_calls (void);
+int __attribute__ ((__strub__ ("disabled"))) disabled (void);
+
+int __attribute__ ((__strub__)) var;
+int var_user (void);
+
+static inline int __attribute__ ((__always_inline__, __strub__ ("callable")))
+icallable (void);
+static inline int __attribute__ ((__always_inline__, __strub__ ("internal")))
+iinternal (void);
+static inline int __attribute__ ((__always_inline__, __strub__ ("at-calls")))
+iat_calls (void);
+static inline int __attribute__ ((__always_inline__, __strub__ ("disabled")))
+idisabled (void);
+static inline int __attribute__ ((__always_inline__))
+ivar_user (void);
+
+static inline int __attribute__ ((__always_inline__, __strub__ ("callable")))
+i_callable (void) { return 0; }
+static inline int __attribute__ ((__always_inline__, __strub__ ("internal")))
+i_internal (void) { return var; }
+static inline int __attribute__ ((__always_inline__, __strub__ ("at-calls")))
+i_at_calls (void) { return var; }
+static inline int __attribute__ ((__always_inline__, __strub__ ("disabled")))
+i_disabled (void) { return 0; }
+static inline int __attribute__ ((__always_inline__))
+i_var_user (void) { return var; }
+
+#define CALLS_GOOD_FOR_STRUB_CONTEXT(ISEP) \
+ do { \
+ ret += i ## ISEP ## at_calls (); \
+ ret += i ## ISEP ## internal (); \
+ ret += i ## ISEP ## var_user (); \
+ } while (0)
+
+#define CALLS_GOOD_FOR_NONSTRUB_CONTEXT(ISEP) \
+ do { \
+ ret += internal (); \
+ ret += disabled (); \
+ ret += var_user (); \
+ \
+ ret += i ## ISEP ## disabled (); \
+ \
+ ret += xinternal (); \
+ ret += xdisabled (); \
+ } while (0)
+
+#define CALLS_GOOD_FOR_EITHER_CONTEXT(ISEP) \
+ do { \
+ ret += i ## ISEP ## callable (); \
+ \
+ ret += callable (); \
+ ret += at_calls (); \
+ \
+ ret += xat_calls (); \
+ ret += xcallable (); \
+ } while (0)
+
+/* Not a strub context, so it can call anything.
+ Explicitly declared as callable even from within strub contexts. */
+int __attribute__ ((__strub__ ("callable")))
+callable (void) {
+ int ret = 0;
+
+ /* CALLS_GOOD_FOR_STRUB_CONTEXT(); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += iat_calls (); /* { dg-error "in non-.strub. context" } */
+ ret += iinternal (); /* { dg-error "in non-.strub. context" } */
+ ret += ivar_user (); /* { dg-error "in non-.strub. context" } */
+#endif
+ CALLS_GOOD_FOR_EITHER_CONTEXT();
+ CALLS_GOOD_FOR_NONSTRUB_CONTEXT();
+
+ return ret;
+}
+
+/* Internal strubbing means the body is a strub context, so it can only call
+ strub functions, and it's not itself callable from strub functions. */
+int __attribute__ ((__strub__ ("internal")))
+internal (void) {
+ int ret = var;
+
+ CALLS_GOOD_FOR_STRUB_CONTEXT();
+ CALLS_GOOD_FOR_EITHER_CONTEXT();
+ /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += internal (); /* { dg-error "in .strub. context" } */
+ ret += disabled (); /* { dg-error "in .strub. context" } */
+ ret += var_user (); /* { dg-error "in .strub. context" } */
+
+ ret += idisabled (); /* { dg-error "in .strub. context" } */
+
+ ret += xinternal (); /* { dg-error "in .strub. context" } */
+ ret += xdisabled (); /* { dg-error "in .strub. context" } */
+#endif
+
+ return ret;
+}
+
+int __attribute__ ((__strub__ ("at-calls")))
+at_calls (void) {
+ int ret = var;
+
+ CALLS_GOOD_FOR_STRUB_CONTEXT();
+ CALLS_GOOD_FOR_EITHER_CONTEXT();
+ /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += internal (); /* { dg-error "in .strub. context" } */
+ ret += disabled (); /* { dg-error "in .strub. context" } */
+ ret += var_user (); /* { dg-error "in .strub. context" } */
+
+ ret += idisabled (); /* { dg-error "in .strub. context" } */
+
+ ret += xinternal (); /* { dg-error "in .strub. context" } */
+ ret += xdisabled (); /* { dg-error "in .strub. context" } */
+#endif
+
+ return ret;
+}
+
+int __attribute__ ((__strub__ ("disabled")))
+disabled () {
+ int ret = 0;
+
+ /* CALLS_GOOD_FOR_STRUB_CONTEXT(); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += iat_calls (); /* { dg-error "in non-.strub. context" } */
+ ret += iinternal (); /* { dg-error "in non-.strub. context" } */
+ ret += ivar_user (); /* { dg-error "in non-.strub. context" } */
+#endif
+ CALLS_GOOD_FOR_EITHER_CONTEXT();
+ CALLS_GOOD_FOR_NONSTRUB_CONTEXT();
+
+ return ret;
+}
+
+int
+var_user (void) {
+ int ret = var;
+
+ CALLS_GOOD_FOR_STRUB_CONTEXT();
+ CALLS_GOOD_FOR_EITHER_CONTEXT();
+ /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += internal (); /* { dg-error "in .strub. context" } */
+ ret += disabled (); /* { dg-error "in .strub. context" } */
+ ret += var_user (); /* { dg-error "in .strub. context" } */
+
+ ret += idisabled (); /* { dg-error "in .strub. context" } */
+
+ ret += xinternal (); /* { dg-error "in .strub. context" } */
+ ret += xdisabled (); /* { dg-error "in .strub. context" } */
+#endif
+
+ return ret;
+}
+
+int
+icallable (void)
+{
+ int ret = 0;
+
+ /* CALLS_GOOD_FOR_STRUB_CONTEXT(_); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += i_at_calls (); /* { dg-error "in non-.strub. context" } */
+ ret += i_internal (); /* { dg-error "in non-.strub. context" } */
+ ret += i_var_user (); /* { dg-error "in non-.strub. context" } */
+#endif
+ CALLS_GOOD_FOR_EITHER_CONTEXT(_);
+ CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_);
+
+ return ret;
+}
+
+int
+iinternal (void) {
+ int ret = var;
+
+ CALLS_GOOD_FOR_STRUB_CONTEXT(_);
+ CALLS_GOOD_FOR_EITHER_CONTEXT(_);
+ /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += internal (); /* { dg-error "in .strub. context" } */
+ ret += disabled (); /* { dg-error "in .strub. context" } */
+ ret += var_user (); /* { dg-error "in .strub. context" } */
+
+ ret += i_disabled (); /* { dg-error "in .strub. context" } */
+
+ ret += xinternal (); /* { dg-error "in .strub. context" } */
+ ret += xdisabled (); /* { dg-error "in .strub. context" } */
+#endif
+
+ return ret;
+}
+
+int __attribute__ ((__always_inline__, __strub__ ("at-calls")))
+iat_calls (void) {
+ int ret = var;
+
+ CALLS_GOOD_FOR_STRUB_CONTEXT(_);
+ CALLS_GOOD_FOR_EITHER_CONTEXT(_);
+ /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += internal (); /* { dg-error "in .strub. context" } */
+ ret += disabled (); /* { dg-error "in .strub. context" } */
+ ret += var_user (); /* { dg-error "in .strub. context" } */
+
+ ret += i_disabled (); /* { dg-error "in .strub. context" } */
+
+ ret += xinternal (); /* { dg-error "in .strub. context" } */
+ ret += xdisabled (); /* { dg-error "in .strub. context" } */
+#endif
+
+ return ret;
+}
+
+int
+idisabled () {
+ int ret = 0;
+
+ /* CALLS_GOOD_FOR_STRUB_CONTEXT(_); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += i_at_calls (); /* { dg-error "in non-.strub. context" } */
+ ret += i_internal (); /* { dg-error "in non-.strub. context" } */
+ ret += i_var_user (); /* { dg-error "in non-.strub. context" } */
+#endif
+ CALLS_GOOD_FOR_EITHER_CONTEXT(_);
+ CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_);
+
+ return ret;
+}
+
+int
+ivar_user (void) {
+ int ret = var;
+
+ CALLS_GOOD_FOR_STRUB_CONTEXT(_);
+ CALLS_GOOD_FOR_EITHER_CONTEXT(_);
+ /* CALLS_GOOD_FOR_NONSTRUB_CONTEXT(_); */
+#if !OMIT_IMPERMISSIBLE_CALLS
+ ret += internal (); /* { dg-error "in .strub. context" } */
+ ret += disabled (); /* { dg-error "in .strub. context" } */
+ ret += var_user (); /* { dg-error "in .strub. context" } */
+
+ ret += i_disabled (); /* { dg-error "in .strub. context" } */
+
+ ret += xinternal (); /* { dg-error "in .strub. context" } */
+ ret += xdisabled (); /* { dg-error "in .strub. context" } */
+#endif
+
+ return ret;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-const1.c b/gcc/testsuite/c-c++-common/torture/strub-const1.c
new file mode 100644
index 0000000000000..2857195706ed6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-const1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub const function call, we issue an asm statement
+ to make sure the watermark passed to it is held in memory before the call,
+ and another to make sure it is not assumed to be unchanged. */
+
+int __attribute__ ((__strub__, __const__))
+f() {
+ return 0;
+}
+
+int
+g() {
+ return f();
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-const2.c b/gcc/testsuite/c-c++-common/torture/strub-const2.c
new file mode 100644
index 0000000000000..98a92bc9eac2b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-const2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub implicitly-const function call, we issue an
+ asm statement to make sure the watermark passed to it is held in memory
+ before the call, and another to make sure it is not assumed to be
+ unchanged. */
+
+int __attribute__ ((__strub__))
+#if ! __OPTIMIZE__
+__attribute__ ((__const__))
+#endif
+f() {
+ return 0;
+}
+
+int
+g() {
+ return f();
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-const3.c b/gcc/testsuite/c-c++-common/torture/strub-const3.c
new file mode 100644
index 0000000000000..5511a6e1e71d3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-const3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub const wrapping call, we issue an asm statement
+ to make sure the watermark passed to it is held in memory before the call,
+ and another to make sure it is not assumed to be unchanged. */
+
+int __attribute__ ((__strub__ ("internal"), __const__))
+f() {
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-const4.c b/gcc/testsuite/c-c++-common/torture/strub-const4.c
new file mode 100644
index 0000000000000..47ee927964dff
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-const4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub implicitly-const wrapping call, we issue an
+ asm statement to make sure the watermark passed to it is held in memory
+ before the call, and another to make sure it is not assumed to be
+ unchanged. */
+
+int __attribute__ ((__strub__ ("internal")))
+#if ! __OPTIMIZE__
+__attribute__ ((__const__))
+#endif
+f() {
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 2 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-data1.c b/gcc/testsuite/c-c++-common/torture/strub-data1.c
new file mode 100644
index 0000000000000..7c27a2a1a6dca
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-data1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* The pointed-to data enables strubbing if accessed. */
+int __attribute__ ((__strub__)) var;
+
+int f() {
+ return var;
+}
+
+/* { dg-final { scan-ipa-dump "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-data2.c b/gcc/testsuite/c-c++-common/torture/strub-data2.c
new file mode 100644
index 0000000000000..e66d903780afd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-data2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* The pointer itself is a strub variable, enabling internal strubbing when
+ its value is used. */
+int __attribute__ ((__strub__)) *ptr;
+
+int *f() {
+ return ptr;
+}
+
+/* { dg-final { scan-ipa-dump "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-data3.c b/gcc/testsuite/c-c++-common/torture/strub-data3.c
new file mode 100644
index 0000000000000..5e08e0e58c658
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-data3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* The pointer itself is a strub variable, that would enable internal strubbing
+ if its value was used. Here, it's only overwritten, so no strub. */
+int __attribute__ ((__strub__)) var;
+
+void f() {
+ var = 0;
+}
+
+/* { dg-final { scan-ipa-dump-not "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-data4.c b/gcc/testsuite/c-c++-common/torture/strub-data4.c
new file mode 100644
index 0000000000000..a818e7a38bb5f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-data4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* The pointer itself is a strub variable, that would enable internal strubbing
+ if its value was used. Here, it's only overwritten, so no strub. */
+int __attribute__ ((__strub__)) *ptr;
+
+void f() {
+ ptr = 0;
+}
+
+/* { dg-final { scan-ipa-dump-not "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-data5.c b/gcc/testsuite/c-c++-common/torture/strub-data5.c
new file mode 100644
index 0000000000000..ddb0b5c0543b0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-data5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict" } */
+
+/* It would be desirable to issue at least warnings for these. */
+
+typedef int __attribute__ ((__strub__)) strub_int;
+strub_int *ptr;
+
+int *f () {
+ return ptr; /* { dg-message "incompatible|invalid conversion" } */
+}
+
+strub_int *g () {
+ return f (); /* { dg-message "incompatible|invalid conversion" } */
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-indcall1.c b/gcc/testsuite/c-c++-common/torture/strub-indcall1.c
new file mode 100644
index 0000000000000..c165f312f16de
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-indcall1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+typedef void __attribute__ ((__strub__)) fntype ();
+fntype (*ptr);
+
+void f() {
+ ptr ();
+}
+
+/* { dg-final { scan-ipa-dump "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump "(&\.strub\.watermark\.\[0-9\]\+)" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-indcall2.c b/gcc/testsuite/c-c++-common/torture/strub-indcall2.c
new file mode 100644
index 0000000000000..69fcff8d3763d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-indcall2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+typedef void __attribute__ ((__strub__)) fntype (int, int);
+fntype (*ptr);
+
+void f() {
+ ptr (0, 0);
+}
+
+/* { dg-final { scan-ipa-dump "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump "(0, 0, &\.strub\.watermark\.\[0-9\]\+)" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-indcall3.c b/gcc/testsuite/c-c++-common/torture/strub-indcall3.c
new file mode 100644
index 0000000000000..ff006224909bd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-indcall3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+typedef void __attribute__ ((__strub__)) fntype (int, int, ...);
+fntype (*ptr);
+
+void f() {
+ ptr (0, 0, 1, 1);
+}
+
+/* { dg-final { scan-ipa-dump "strub_enter" "strub" } } */
+/* { dg-final { scan-ipa-dump "(0, 0, &\.strub\.watermark\.\[0-9\]\+, 1, 1)" "strub" } } */
+/* { dg-final { scan-ipa-dump "strub_leave" "strub" } } */
+/* { dg-final { scan-ipa-dump-not "strub_update" "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c b/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c
new file mode 100644
index 0000000000000..614b02228ba29
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=relaxed" } */
+
+inline void __attribute__ ((strub ("internal"), always_inline))
+inl_int_ali (void)
+{
+ /* No internal wrapper, so this body ALWAYS gets inlined,
+ but it cannot be called from non-strub contexts. */
+}
+
+void
+bat (void)
+{
+ /* Not allowed, not a strub context. */
+ inl_int_ali (); /* { dg-error "context" } */
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c b/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c
new file mode 100644
index 0000000000000..f9a6b4a16faf8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=all" } */
+
+#include "strub-inlinable1.c"
+
+/* With -fstrub=all, the caller becomes a strub context, so the strub-inlinable
+ callee is not rejected. */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c
new file mode 100644
index 0000000000000..b4a7f3992bbaa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict" } */
+
+typedef void ft (void);
+typedef void ft2 (int, int);
+extern ft __attribute__ ((__strub__)) fnac;
+
+ft * f (void) {
+ return fnac; /* { dg-message "incompatible|invalid conversion" } */
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c
new file mode 100644
index 0000000000000..d9d2c0caec42d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=relaxed -Wpedantic" } */
+
+/* C++ does not warn about the partial incompatibilities.
+
+ The d_p () calls are actually rejected, even in C++, but they are XFAILed
+ here because we don't get far enough in the compilation as to observe them,
+ because the incompatibilities are errors without -fpermissive.
+ strub-ptrfn3.c uses -fpermissive to check those.
+ */
+
+extern int __attribute__ ((strub ("callable"))) bac (void);
+extern int __attribute__ ((strub ("disabled"))) bad (void);
+extern int __attribute__ ((strub ("internal"))) bar (void);
+extern int __attribute__ ((strub ("at-calls"))) bal (void);
+
+void __attribute__ ((strub))
+bap (void)
+{
+ int __attribute__ ((strub ("disabled"))) (*d_p) (void) = bad;
+ int __attribute__ ((strub ("callable"))) (*c_p) (void) = bac;
+ int __attribute__ ((strub ("at-calls"))) (*a_p) (void) = bal;
+
+ d_p = bac; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bad; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bar; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bal; /* { dg-message "incompatible|invalid conversion" } */
+ a_p = bac; /* { dg-message "incompatible|invalid conversion" } */
+
+ d_p (); /* { dg-error "indirect non-.strub. call in .strub. context" "" { xfail c++ } } */
+ c_p ();
+ a_p ();
+}
+
+void __attribute__ ((strub))
+baP (void)
+{
+ typedef int __attribute__ ((strub ("disabled"))) d_fn_t (void);
+ typedef int __attribute__ ((strub ("callable"))) c_fn_t (void);
+ typedef int __attribute__ ((strub ("at-calls"))) a_fn_t (void);
+
+ d_fn_t *d_p = bad;
+ c_fn_t *c_p = bac;
+ a_fn_t *a_p = bal;
+
+ d_p = bac; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bad; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bar; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bal; /* { dg-message "incompatible|invalid conversion" } */
+ a_p = bac; /* { dg-message "incompatible|invalid conversion" } */
+
+ d_p (); /* { dg-error "indirect non-.strub. call in .strub. context" "" { xfail c++ } } */
+ c_p ();
+ a_p ();
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c
new file mode 100644
index 0000000000000..e1f179e160e5c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=relaxed -Wpedantic -fpermissive" } */
+/* { dg-prune-output "command-line option .-fpermissive." } */
+
+/* See strub-ptrfn2.c. */
+
+extern int __attribute__ ((strub ("callable"))) bac (void);
+extern int __attribute__ ((strub ("disabled"))) bad (void);
+extern int __attribute__ ((strub ("internal"))) bar (void);
+extern int __attribute__ ((strub ("at-calls"))) bal (void);
+
+void __attribute__ ((strub))
+bap (void)
+{
+ int __attribute__ ((strub ("disabled"))) (*d_p) (void) = bad;
+ int __attribute__ ((strub ("callable"))) (*c_p) (void) = bac;
+ int __attribute__ ((strub ("at-calls"))) (*a_p) (void) = bal;
+
+ d_p = bac; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bad; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bar; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bal; /* { dg-message "incompatible|invalid conversion" } */
+ a_p = bac; /* { dg-message "incompatible|invalid conversion" } */
+
+ d_p (); /* { dg-error "indirect non-.strub. call in .strub. context" } */
+ c_p ();
+ a_p ();
+}
+
+void __attribute__ ((strub))
+baP (void)
+{
+ typedef int __attribute__ ((strub ("disabled"))) d_fn_t (void);
+ typedef int __attribute__ ((strub ("callable"))) c_fn_t (void);
+ typedef int __attribute__ ((strub ("at-calls"))) a_fn_t (void);
+
+ d_fn_t *d_p = bad;
+ c_fn_t *c_p = bac;
+ a_fn_t *a_p = bal;
+
+ d_p = bac; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bad; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bar; /* { dg-warning "not quite compatible" "" { xfail c++ } } */
+ c_p = bal; /* { dg-message "incompatible|invalid conversion" } */
+ a_p = bac; /* { dg-message "incompatible|invalid conversion" } */
+
+ d_p (); /* { dg-error "indirect non-.strub. call in .strub. context" } */
+ c_p ();
+ a_p ();
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c
new file mode 100644
index 0000000000000..70b558afad040
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=relaxed" } */
+
+/* This is strub-ptrfn2.c without -Wpedantic.
+
+ Even C doesn't report the (not-quite-)compatible conversions without it. */
+
+extern int __attribute__ ((strub ("callable"))) bac (void);
+extern int __attribute__ ((strub ("disabled"))) bad (void);
+extern int __attribute__ ((strub ("internal"))) bar (void);
+extern int __attribute__ ((strub ("at-calls"))) bal (void);
+
+void __attribute__ ((strub))
+bap (void)
+{
+ int __attribute__ ((strub ("disabled"))) (*d_p) (void) = bad;
+ int __attribute__ ((strub ("callable"))) (*c_p) (void) = bac;
+ int __attribute__ ((strub ("at-calls"))) (*a_p) (void) = bal;
+
+ d_p = bac;
+ c_p = bad;
+ c_p = bar;
+ c_p = bal; /* { dg-message "incompatible|invalid conversion" } */
+ a_p = bac; /* { dg-message "incompatible|invalid conversion" } */
+}
+
+void __attribute__ ((strub))
+baP (void)
+{
+ typedef int __attribute__ ((strub ("disabled"))) d_fn_t (void);
+ typedef int __attribute__ ((strub ("callable"))) c_fn_t (void);
+ typedef int __attribute__ ((strub ("at-calls"))) a_fn_t (void);
+
+ d_fn_t *d_p = bad;
+ c_fn_t *c_p = bac;
+ a_fn_t *a_p = bal;
+
+ d_p = bac;
+ c_p = bad;
+ c_p = bar;
+ c_p = bal; /* { dg-message "incompatible|invalid conversion" } */
+ a_p = bac; /* { dg-message "incompatible|invalid conversion" } */
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure1.c b/gcc/testsuite/c-c++-common/torture/strub-pure1.c
new file mode 100644
index 0000000000000..a262a086837b2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-pure1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub pure function call, we issue an asm statement
+ to make sure the watermark passed to it is not assumed to be unchanged. */
+
+int __attribute__ ((__strub__, __pure__))
+f() {
+ static int i; /* Stop it from being detected as const. */
+ return i;
+}
+
+int
+g() {
+ return f();
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure2.c b/gcc/testsuite/c-c++-common/torture/strub-pure2.c
new file mode 100644
index 0000000000000..4c4bd50c209a0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-pure2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub implicitly-pure function call, we issue an asm
+ statement to make sure the watermark passed to it is not assumed to be
+ unchanged. */
+
+int __attribute__ ((__strub__))
+#if ! __OPTIMIZE__ /* At -O0, implicit pure detection doesn't run. */
+__attribute__ ((__pure__))
+#endif
+f() {
+ static int i; /* Stop it from being detected as const. */
+ return i;
+}
+
+int
+g() {
+ return f();
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure3.c b/gcc/testsuite/c-c++-common/torture/strub-pure3.c
new file mode 100644
index 0000000000000..ce195c6b1f1b6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-pure3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub pure wrapping call, we issue an asm statement
+ to make sure the watermark passed to it is not assumed to be unchanged. */
+
+int __attribute__ ((__strub__ ("internal"), __pure__))
+f() {
+ static int i; /* Stop it from being detected as const. */
+ return i;
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure4.c b/gcc/testsuite/c-c++-common/torture/strub-pure4.c
new file mode 100644
index 0000000000000..75cd54ccb5b5d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-pure4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
+
+/* Check that, along with a strub implicitly-pure wrapping call, we issue an asm
+ statement to make sure the watermark passed to it is not assumed to be
+ unchanged. */
+
+int __attribute__ ((__strub__ ("internal")))
+#if ! __OPTIMIZE__ /* At -O0, implicit pure detection doesn't run. */
+__attribute__ ((__pure__))
+#endif
+f() {
+ static int i; /* Stop it from being detected as const. */
+ return i;
+}
+
+/* { dg-final { scan-ipa-dump-times "__asm__" 1 "strub" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run1.c b/gcc/testsuite/c-c++-common/torture/strub-run1.c
new file mode 100644
index 0000000000000..b24a1c7a345fa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run1.c
@@ -0,0 +1,90 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=strict" } */
+
+/* Check that a non-strub function leaves a string behind in the stack, and that
+ equivalent strub functions don't. Avoid the use of red zones by avoiding
+ leaf functions. */
+
+const char test_string[] = "\x55\xde\xad\xbe\xef\xc0\x1d\xca\xfe\x55\xaa";
+
+/* Pad before and after the string on the stack, so that it's not overwritten by
+ regular stack use. */
+#define PAD 7
+
+static inline __attribute__ ((__always_inline__, __strub__ ("callable")))
+char *
+leak_string (void)
+{
+ /* We use this variable to avoid any stack red zone. Stack scrubbing covers
+ it, but __builtin_stack_address, that we take as a reference, doesn't, so
+ if e.g. callable() were to store the string in the red zone, we wouldn't
+ find it because it would be outside the range we searched. */
+ typedef void __attribute__ ((__strub__ ("callable"))) callable_t (char *);
+ callable_t *f = 0;
+
+ char s[2 * PAD + 1][sizeof (test_string)];
+ __builtin_strcpy (s[PAD], test_string);
+ asm ("" : "+m" (s), "+r" (f));
+
+ if (__builtin_expect (!f, 1))
+ return (char *) __builtin_stack_address ();
+
+ f (s[PAD]);
+ return 0;
+}
+
+static inline __attribute__ ((__always_inline__))
+int
+look_for_string (char *e)
+{
+ char *p = (char *) __builtin_stack_address ();
+
+ if (p == e)
+ __builtin_abort ();
+
+ if (p > e)
+ {
+ char *q = p;
+ p = e;
+ e = q;
+ }
+
+ for (char *re = e - sizeof (test_string); p < re; p++)
+ for (int i = 0; p[i] == test_string[i]; i++)
+ if (i == sizeof (test_string) - 1)
+ return i;
+
+ return 0;
+}
+
+static __attribute__ ((__noinline__, __noclone__))
+char *
+callable ()
+{
+ return leak_string ();
+}
+
+static __attribute__ ((__strub__ ("at-calls")))
+char *
+at_calls ()
+{
+ return leak_string ();
+}
+
+static __attribute__ ((__strub__ ("internal")))
+char *
+internal ()
+{
+ return leak_string ();
+}
+
+int main ()
+{
+ if (!look_for_string (callable ()))
+ __builtin_abort ();
+ if (look_for_string (at_calls ()))
+ __builtin_abort ();
+ if (look_for_string (internal ()))
+ __builtin_abort ();
+ __builtin_exit (0);
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run2.c b/gcc/testsuite/c-c++-common/torture/strub-run2.c
new file mode 100644
index 0000000000000..1df2ffe2fe58c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run2.c
@@ -0,0 +1,79 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=strict" } */
+
+/* Check that a non-strub function leaves a string behind in the stack, and that
+ equivalent strub functions don't. Allow red zones to be used. */
+
+const char test_string[] = "\x55\xde\xad\xbe\xef\xc0\x1d\xca\xfe\x55\xaa";
+
+/* Pad before and after the string on the stack, so that it's not overwritten by
+ regular stack use. */
+#define PAD 7
+
+static inline __attribute__ ((__always_inline__, __strub__ ("callable")))
+char *
+leak_string (void)
+{
+ int len = sizeof (test_string);
+ asm ("" : "+rm" (len));
+ char s[2 * PAD + 1][len];
+ __builtin_strcpy (s[PAD], test_string);
+ asm ("" : "+m" (s));
+ return (char *) __builtin_stack_address ();
+}
+
+static inline __attribute__ ((__always_inline__))
+int
+look_for_string (char *e)
+{
+ char *p = (char *) __builtin_stack_address ();
+
+ if (p == e)
+ __builtin_abort ();
+
+ if (p > e)
+ {
+ char *q = p;
+ p = e;
+ e = q;
+ }
+
+ for (char *re = e - sizeof (test_string); p < re; p++)
+ for (int i = 0; p[i] == test_string[i]; i++)
+ if (i == sizeof (test_string) - 1)
+ return i;
+
+ return 0;
+}
+
+static __attribute__ ((__noinline__, __noclone__))
+char *
+callable ()
+{
+ return leak_string ();
+}
+
+static __attribute__ ((__strub__ ("at-calls")))
+char *
+at_calls ()
+{
+ return leak_string ();
+}
+
+static __attribute__ ((__strub__ ("internal")))
+char *
+internal ()
+{
+ return leak_string ();
+}
+
+int main ()
+{
+ if (!look_for_string (callable ()))
+ __builtin_abort ();
+ if (look_for_string (at_calls ()))
+ __builtin_abort ();
+ if (look_for_string (internal ()))
+ __builtin_abort ();
+ __builtin_exit (0);
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run3.c b/gcc/testsuite/c-c++-common/torture/strub-run3.c
new file mode 100644
index 0000000000000..afbc2cc9ab484
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run3.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=strict" } */
+/* { dg-require-effective-target alloca } */
+
+/* Check that a non-strub function leaves a string behind in the stack, and that
+ equivalent strub functions don't. */
+
+const char test_string[] = "\x55\xde\xad\xbe\xef\xc0\x1d\xca\xfe\x55\xaa";
+
+static inline __attribute__ ((__always_inline__, __strub__ ("callable")))
+char *
+leak_string (void)
+{
+ int len = sizeof (test_string);
+ char *s = (char *) __builtin_alloca (len);
+ __builtin_strcpy (s, test_string);
+ asm ("" : "+m" (s));
+ return (char *) __builtin_stack_address ();
+}
+
+static inline __attribute__ ((__always_inline__))
+int
+look_for_string (char *e)
+{
+ char *p = (char *) __builtin_stack_address ();
+
+ if (p == e)
+ __builtin_abort ();
+
+ if (p > e)
+ {
+ char *q = p;
+ p = e;
+ e = q;
+ }
+
+ for (char *re = e - sizeof (test_string); p < re; p++)
+ for (int i = 0; p[i] == test_string[i]; i++)
+ if (i == sizeof (test_string) - 1)
+ return i;
+
+ return 0;
+}
+
+static __attribute__ ((__noinline__, __noclone__))
+char *
+callable ()
+{
+ return leak_string ();
+}
+
+static __attribute__ ((__strub__ ("at-calls")))
+char *
+at_calls ()
+{
+ return leak_string ();
+}
+
+static __attribute__ ((__strub__ ("internal")))
+char *
+internal ()
+{
+ return leak_string ();
+}
+
+int main ()
+{
+ if (!look_for_string (callable ()))
+ __builtin_abort ();
+ if (look_for_string (at_calls ()))
+ __builtin_abort ();
+ if (look_for_string (internal ()))
+ __builtin_abort ();
+ __builtin_exit (0);
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4.c b/gcc/testsuite/c-c++-common/torture/strub-run4.c
new file mode 100644
index 0000000000000..5300f1d330b87
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run4.c
@@ -0,0 +1,101 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=all" } */
+/* { dg-require-effective-target alloca } */
+
+/* Check that multi-level, multi-inlined functions still get cleaned up as
+ expected, without overwriting temporary stack allocations while they should
+ still be available. */
+
+#ifndef ATTR_STRUB_AT_CALLS
+# define ATTR_STRUB_AT_CALLS /* Defined in strub-run4d.c. */
+#endif
+
+const char test_string[] = "\x55\xde\xad\xbe\xef\xc0\x1d\xca\xfe\x55\xaa";
+
+static inline __attribute__ ((__always_inline__))
+char *
+leak_string (void)
+{
+ int __attribute__ ((__strub__)) len = 512;
+ asm ("" : "+r" (len));
+ char s[len];
+ __builtin_strcpy (s, test_string);
+ __builtin_strcpy (s + len - sizeof (test_string), test_string);
+ asm ("" : "+m" (s));
+ return (char *) __builtin_stack_address ();
+}
+
+static inline __attribute__ ((__always_inline__))
+int
+look_for_string (char *e)
+{
+ char *p = (char *) __builtin_stack_address ();
+
+ if (p == e)
+ __builtin_abort ();
+
+ if (p > e)
+ {
+ char *q = p;
+ p = e;
+ e = q;
+ }
+
+ for (char *re = e - sizeof (test_string); p < re; p++)
+ for (int i = 0; p[i] == test_string[i]; i++)
+ if (i == sizeof (test_string) - 1)
+ return i;
+
+ return 0;
+}
+
+static inline ATTR_STRUB_AT_CALLS
+char *
+innermost ()
+{
+ int __attribute__ ((__strub__)) len = 512;
+ asm ("" : "+r" (len));
+ char s[len];
+ __builtin_strcpy (s, test_string);
+ __builtin_strcpy (s + len - sizeof (test_string), test_string);
+ asm ("" : "+m" (s));
+ char *ret = leak_string ();
+ if (__builtin_strcmp (s, test_string) != 0)
+ __builtin_abort ();
+ if (__builtin_strcmp (s + len - sizeof (test_string), test_string) != 0)
+ __builtin_abort ();
+ return ret;
+}
+
+static inline ATTR_STRUB_AT_CALLS
+char *
+intermediate ()
+{
+ int __attribute__ ((__strub__)) len = 512;
+ asm ("" : "+r" (len));
+ char s[len];
+ __builtin_strcpy (s, test_string);
+ __builtin_strcpy (s + len - sizeof (test_string), test_string);
+ asm ("" : "+m" (s));
+ char *ret = innermost ();
+ if (__builtin_strcmp (s, test_string) != 0)
+ __builtin_abort ();
+ if (__builtin_strcmp (s + len - sizeof (test_string), test_string) != 0)
+ __builtin_abort ();
+ return ret;
+}
+
+static inline __attribute__ ((__strub__ ("internal")))
+char *
+internal ()
+{
+ return intermediate ();
+}
+
+int __attribute__ ((__strub__ ("disabled")))
+main ()
+{
+ if (look_for_string (internal ()))
+ __builtin_abort ();
+ __builtin_exit (0);
+}
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4c.c b/gcc/testsuite/c-c++-common/torture/strub-run4c.c
new file mode 100644
index 0000000000000..57f9baf758ded
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run4c.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=at-calls" } */
+/* { dg-require-effective-target alloca } */
+
+#include "strub-run4.c"
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4d.c b/gcc/testsuite/c-c++-common/torture/strub-run4d.c
new file mode 100644
index 0000000000000..08de3f1c3b17c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run4d.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=strict" } */
+/* { dg-require-effective-target alloca } */
+
+#define ATTR_STRUB_AT_CALLS __attribute__ ((__strub__ ("at-calls")))
+
+#include "strub-run4.c"
diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4i.c b/gcc/testsuite/c-c++-common/torture/strub-run4i.c
new file mode 100644
index 0000000000000..459f6886c5499
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/strub-run4i.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-fstrub=internal" } */
+/* { dg-require-effective-target alloca } */
+
+#include "strub-run4.c"
--
Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/
Free Software Activist GNU Toolchain Engineer
Disinformation flourishes because many people care deeply about injustice
but very few check the facts. Ask me about <https://stallmansupport.org>
next prev parent reply other threads:[~2022-07-29 6:25 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <ormtqpsbuc.fsf@lxoliva.fsfla.org>
2021-09-09 7:11 ` [PATCH] strub: machine-independent stack scrubbing Alexandre Oliva
2022-07-29 6:16 ` [PATCH v2 00/10] Introduce " Alexandre Oliva
2022-07-29 6:24 ` [PATCH v2 01/10] Introduce strub: documentation, and new command-line options Alexandre Oliva
2022-07-29 6:25 ` Alexandre Oliva [this message]
2022-08-09 13:34 ` [PATCH v2 02/10] Introduce strub: torture tests for C and C++ Alexandre Oliva
2022-07-29 6:25 ` [PATCH v2 03/10] Introduce strub: non-torture " Alexandre Oliva
2022-07-29 6:26 ` [PATCH v2 04/10] Introduce strub: tests for C++ and Ada Alexandre Oliva
2022-07-29 6:26 ` [PATCH v2 05/10] Introduce strub: builtins and runtime Alexandre Oliva
2022-07-29 6:27 ` [PATCH v2 06/10] Introduce strub: attributes Alexandre Oliva
2022-07-29 6:28 ` [PATCH v2 07/10] Introduce strub: infrastructure interfaces and adjustments Alexandre Oliva
2022-07-29 6:28 ` [PATCH v2 08/10] Introduce strub: strub modes Alexandre Oliva
2022-07-29 6:30 ` [PATCH v2 09/10] Introduce strub: strubm (mode assignment) pass Alexandre Oliva
2022-07-29 6:34 ` [PATCH v2 10/10] Introduce strub: strub pass Alexandre Oliva
2022-07-29 6:36 ` [PATCH v2 00/10] Introduce strub: machine-independent stack scrubbing Alexandre Oliva
2022-10-10 8:48 ` Richard Biener
2022-10-11 11:57 ` Alexandre Oliva
2022-10-11 11:59 ` Richard Biener
2022-10-11 13:33 ` Alexandre Oliva
2022-10-13 11:38 ` Richard Biener
2022-10-13 13:15 ` Alexandre Oliva
2023-06-16 6:09 ` [PATCH v3] " Alexandre Oliva
2023-06-27 21:28 ` Qing Zhao
2023-06-28 8:20 ` Alexandre Oliva
2023-10-20 6:03 ` [PATCH v4] " Alexandre Oliva
2023-10-26 6:15 ` Alexandre Oliva
2023-11-20 12:40 ` Alexandre Oliva
2023-11-22 14:14 ` Richard Biener
2023-11-23 10:56 ` Alexandre Oliva
2023-11-23 12:05 ` Richard Biener
2023-11-29 8:53 ` Alexandre Oliva
2023-11-29 12:48 ` Richard Biener
2023-11-30 4:13 ` Alexandre Oliva
2023-11-30 12:00 ` Richard Biener
2023-12-02 17:56 ` [PATCH v5] " Alexandre Oliva
2023-12-05 6:25 ` Alexandre Oliva
2023-12-06 1:04 ` Alexandre Oliva
2023-12-05 9:01 ` Richard Biener
2023-12-06 8:36 ` Causes to nvptx bootstrap fail: " Tobias Burnus
2023-12-06 11:32 ` Thomas Schwinge
2023-12-06 22:12 ` Alexandre Oliva
2023-12-07 3:33 ` [PATCH] strub: enable conditional support Alexandre Oliva
2023-12-07 7:24 ` Richard Biener
2023-12-07 16:44 ` Thomas Schwinge
2023-12-07 17:52 ` [PATCH] Alexandre Oliva
2023-12-08 6:46 ` [PATCH] Richard Biener
2023-12-08 9:33 ` [PATCH] strub: skip emutls after strubm errors Thomas Schwinge
2023-12-10 9:16 ` FX Coudert
2023-12-07 7:21 ` Causes to nvptx bootstrap fail: [PATCH v5] Introduce strub: machine-independent stack scrubbing Richard Biener
2023-12-06 10:22 ` Jan Hubicka
2023-12-07 21:19 ` Alexandre Oliva
2023-12-07 21:39 ` Alexandre Oliva
2023-12-09 2:08 ` [PATCH] strub: add note on attribute access Alexandre Oliva
2023-12-11 7:26 ` Richard Biener
2023-12-12 14:21 ` Jan Hubicka
2023-12-11 8:40 ` [PATCH] testsuite: Disable -fstack-protector* for some strub tests Jakub Jelinek
2023-12-11 8:59 ` Richard Biener
2023-12-20 8:15 ` [PATCH FYI] www: new AdaCore-contributed hardening features in gcc 13 and 14 Alexandre Oliva
2023-11-30 5:04 ` [PATCH v4] Introduce strub: machine-independent stack scrubbing Alexandre Oliva
2023-11-30 11:56 ` Richard Biener
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ortu70mo50.fsf_-_@lxoliva.fsfla.org \
--to=oliva@adacore.com \
--cc=craig.blackmore@embecosm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=graham.markall@embecosm.com \
--cc=hubicka@ucw.cz \
--cc=jeremy.bennett@embecosm.com \
--cc=mjambor@suse.cz \
--cc=richard.guenther@gmail.com \
--cc=wilson@tuliptree.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).