2018-01-07 Bernd Edlinger * doc/invoke.texi: Document -Wstack-clobber. * common.opt (-Wstack-clobber): New default-enabled warning. * cfgexpand.c (asm_clobber_reg_is_valid): Emit only a warning together with an informative note when the stack pointer is clobbered. testsuite: 2018-07-01 Bernd Edlinger * gcc.target/arm/pr77904.c: Adjust test. * gcc.target/i386/pr52813.c: Adjust test. Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c (revision 267653) +++ gcc/cfgexpand.c (working copy) @@ -2854,6 +2854,7 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_S asm clobber operand. Some HW registers cannot be saved/restored, hence they should not be clobbered by asm statements. */ + static bool asm_clobber_reg_is_valid (int regno, int nregs, const char *regname) { @@ -2872,11 +2873,22 @@ asm_clobber_reg_is_valid (int regno, int nregs, co error ("PIC register clobbered by %qs in %", regname); is_valid = false; } - /* Clobbering the STACK POINTER register is an error. */ + /* Clobbering the STACK POINTER register is likely an error. + However it is useful to force the use of frame pointer and prevent + the use of red zone. Thus without this clobber, pushing temporary + values onto the stack might clobber the red zone or make stack based + memory references invalid. */ if (overlaps_hard_reg_set_p (regset, Pmode, STACK_POINTER_REGNUM)) { - error ("Stack Pointer register clobbered by %qs in %", regname); - is_valid = false; + if (warning (OPT_Wstack_clobber, + "stack pointer register clobbered by %qs in %", + regname)) + inform (input_location, + "This does likely not do what you would expect." + " The stack pointer register still has to be restored to" + " the previous value, however it is safe to push values onto" + " the stack, when they are popped again from the stack" + " before the asm statement terminates"); } return is_valid; Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 267653) +++ gcc/common.opt (working copy) @@ -702,6 +702,10 @@ Warn when one local variable shadows another local Wshadow-compatible-local Common Warning Undocumented Alias(Wshadow=compatible-local) +Wstack-clobber +Common Warning Var(warn_stack_clobber) Init(1) +Warn when asm statements try to clobber the stack pointer register. + Wstack-protector Common Var(warn_stack_protect) Warning Warn when not issuing stack smashing protection for some reason. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 267653) +++ gcc/doc/invoke.texi (working copy) @@ -339,7 +339,7 @@ Objective-C and Objective-C++ Dialects}. -Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol -Wsign-compare -Wsign-conversion -Wfloat-conversion @gol -Wno-scalar-storage-order -Wsizeof-pointer-div @gol --Wsizeof-pointer-memaccess -Wsizeof-array-argument @gol +-Wsizeof-pointer-memaccess -Wsizeof-array-argument -Wstack-clobber @gol -Wstack-protector -Wstack-usage=@var{byte-size} -Wstrict-aliasing @gol -Wstrict-aliasing=n -Wstrict-overflow -Wstrict-overflow=@var{n} @gol -Wstringop-overflow=@var{n} -Wstringop-truncation -Wsubobject-linkage @gol @@ -7560,6 +7560,20 @@ This option is only supported for C and Objective- @option{-Wall} and by @option{-Wpedantic}, which can be disabled with @option{-Wno-pointer-sign}. +@item -Wstack-clobber +@opindex Wstack-clobber +@opindex Wno-stack-clobber +Warn for asm statements that try to clobber the stack pointer. +Prior to gcc-6 this clobber was ignored, but from gcc-6 on +this was changed to force the use of the frame pointer in the +current function even if @option{-fomit-frame-pointer} is in +effect, additionally this clobber prevents the use of a red-zone +on some targets. The stack pointer register still has to be +restored to the previous value, however it is safe to push values +onto the stack, when they are popped again from the stack before +the asm statement terminates. Since this might be unexpected, +the warning is enabled by default. + @item -Wstack-protector @opindex Wstack-protector @opindex Wno-stack-protector Index: gcc/testsuite/gcc.target/arm/pr77904.c =================================================================== --- gcc/testsuite/gcc.target/arm/pr77904.c (revision 267653) +++ gcc/testsuite/gcc.target/arm/pr77904.c (working copy) @@ -4,7 +4,7 @@ __attribute__ ((noinline, noclone)) void clobber_sp (void) { - __asm volatile ("" : : : "sp"); + __asm volatile ("" : : : "sp"); /* { dg-warning "stack pointer register clobbered" } */ } int Index: gcc/testsuite/gcc.target/i386/pr52813.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr52813.c (revision 267653) +++ gcc/testsuite/gcc.target/i386/pr52813.c (working copy) @@ -1,9 +1,10 @@ /* Ensure that stack pointer cannot be an asm clobber. */ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O3 -fomit-frame-pointer" } */ void test1 (void) { - asm volatile ("" : : : "%esp"); /* { dg-error "Stack Pointer register clobbered" } */ + asm volatile ("" : : : "%rsp"); /* { dg-warning "stack pointer register clobbered" } */ } +/* { dg-final { scan-assembler "(?n)pushq.*%rbp" } } */