Fortran: Add !GCC$ attributes NOINLINE,NORETURN,WEAK
gcc/fortran/ChangeLog: * decl.cc: Add EXT_ATTR_NOINLINE, EXT_ATTR_NORETURN, EXT_ATTR_WEAK. * gfortran.h (ext_attr_id_t): Ditto. * gfortran.texi (GCC$ ATTRIBUTES): Document them. * trans-decl.cc (build_function_decl): Apply them. gcc/testsuite/ChangeLog: * gfortran.dg/noinline.f90: New test. * gfortran.dg/noreturn-1.f90: New test. * gfortran.dg/noreturn-2.f90: New test. * gfortran.dg/noreturn-3.f90: New test. * gfortran.dg/noreturn-4.f90: New test. * gfortran.dg/noreturn-5.f90: New test. * gfortran.dg/weak-1.f90: New test. Signed-off-by: Rimvydas Jasinskas <rimvydas.jas@gmail.com>
This commit is contained in:
parent
72ae1e5635
commit
086a1df437
11 changed files with 203 additions and 1 deletions
|
@ -11732,6 +11732,9 @@ const ext_attr_t ext_attr_list[] = {
|
|||
{ "fastcall", EXT_ATTR_FASTCALL, "fastcall" },
|
||||
{ "no_arg_check", EXT_ATTR_NO_ARG_CHECK, NULL },
|
||||
{ "deprecated", EXT_ATTR_DEPRECATED, NULL },
|
||||
{ "noinline", EXT_ATTR_NOINLINE, NULL },
|
||||
{ "noreturn", EXT_ATTR_NORETURN, NULL },
|
||||
{ "weak", EXT_ATTR_WEAK, NULL },
|
||||
{ NULL, EXT_ATTR_LAST, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -838,6 +838,9 @@ typedef enum
|
|||
EXT_ATTR_FASTCALL,
|
||||
EXT_ATTR_NO_ARG_CHECK,
|
||||
EXT_ATTR_DEPRECATED,
|
||||
EXT_ATTR_NOINLINE,
|
||||
EXT_ATTR_NORETURN,
|
||||
EXT_ATTR_WEAK,
|
||||
EXT_ATTR_LAST, EXT_ATTR_NUM = EXT_ATTR_LAST
|
||||
}
|
||||
ext_attr_id_t;
|
||||
|
|
|
@ -3246,6 +3246,13 @@ requires an explicit interface.
|
|||
@item @code{DEPRECATED} -- print a warning when using a such-tagged
|
||||
deprecated procedure, variable or parameter; the warning can be suppressed
|
||||
with @option{-Wno-deprecated-declarations}.
|
||||
@item @code{NOINLINE} -- prevent inlining given function.
|
||||
@item @code{NORETURN} -- add a hint that a given function cannot return.
|
||||
@item @code{WEAK} -- emit the declaration of an external symbol as a weak
|
||||
symbol rather than a global. This is primarily useful in defining library
|
||||
functions that can be overridden in user code, though it can also be used with
|
||||
non-function declarations. The overriding symbol must have the same type as
|
||||
the weak symbol.
|
||||
@end itemize
|
||||
|
||||
|
||||
|
|
|
@ -2338,7 +2338,7 @@ module_sym:
|
|||
}
|
||||
|
||||
/* Mark non-returning functions. */
|
||||
if (sym->attr.noreturn)
|
||||
if (sym->attr.noreturn || sym->attr.ext_attr & (1 << EXT_ATTR_NORETURN))
|
||||
TREE_THIS_VOLATILE(fndecl) = 1;
|
||||
|
||||
sym->backend_decl = fndecl;
|
||||
|
@ -2482,6 +2482,17 @@ build_function_decl (gfc_symbol * sym, bool global)
|
|||
TREE_SIDE_EFFECTS (fndecl) = 0;
|
||||
}
|
||||
|
||||
/* Mark noinline functions. */
|
||||
if (attr.ext_attr & (1 << EXT_ATTR_NOINLINE))
|
||||
DECL_UNINLINABLE (fndecl) = 1;
|
||||
|
||||
/* Mark noreturn functions. */
|
||||
if (attr.ext_attr & (1 << EXT_ATTR_NORETURN))
|
||||
TREE_THIS_VOLATILE (fndecl) = 1;
|
||||
|
||||
/* Mark weak functions. */
|
||||
if (attr.ext_attr & (1 << EXT_ATTR_WEAK))
|
||||
declare_weak (fndecl);
|
||||
|
||||
/* Layout the function declaration and put it in the binding level
|
||||
of the current function. */
|
||||
|
|
23
gcc/testsuite/gfortran.dg/noinline.f90
Normal file
23
gcc/testsuite/gfortran.dg/noinline.f90
Normal file
|
@ -0,0 +1,23 @@
|
|||
! { dg-do compile }
|
||||
! { dg-options "-O2 -fdump-tree-dom2" }
|
||||
|
||||
subroutine bar(n,m,p,s)
|
||||
implicit none
|
||||
integer :: n,m
|
||||
real,intent(inout) :: p(n),s(*)
|
||||
call foo(n,m,p,s)
|
||||
call foo(n,m,p,s)
|
||||
end subroutine bar
|
||||
|
||||
subroutine foo(n,m,p,b)
|
||||
implicit none
|
||||
integer :: n,m,j
|
||||
real,intent(inout) :: p(n),b(*)
|
||||
!GCC$ ATTRIBUTES noinline :: foo
|
||||
do j=1,n
|
||||
b(m+j-1)=p(j)
|
||||
enddo
|
||||
m=m+n
|
||||
end subroutine foo
|
||||
|
||||
! { dg-final { scan-tree-dump-times "foo \\(" 4 "dom2"} }
|
62
gcc/testsuite/gfortran.dg/noreturn-1.f90
Normal file
62
gcc/testsuite/gfortran.dg/noreturn-1.f90
Normal file
|
@ -0,0 +1,62 @@
|
|||
! Check for various valid and erroneous "noreturn" cases.
|
||||
! { dg-do compile }
|
||||
! { dg-options "-O2" }
|
||||
|
||||
module barbar
|
||||
!GCC$ ATTRIBUTES noreturn :: bar1
|
||||
contains
|
||||
subroutine bar1
|
||||
end subroutine bar1 ! { dg-warning "'noreturn' function does return" "detect falling off end of noreturn" }
|
||||
end module
|
||||
|
||||
subroutine foo1
|
||||
!GCC$ ATTRIBUTES noreturn :: foo1
|
||||
end subroutine foo1 ! { dg-warning "'noreturn' function does return" "detect falling off end of noreturn" }
|
||||
|
||||
subroutine foo2
|
||||
!GCC$ ATTRIBUTES noreturn :: foo2
|
||||
call exit(0)
|
||||
end subroutine foo2 ! { dg-bogus "warning:" "this function should not get any warnings" }
|
||||
|
||||
subroutine foo3
|
||||
end subroutine foo3 ! { dg-bogus "warning:" "this function should not get any warnings" }
|
||||
|
||||
subroutine foo4
|
||||
!GCC$ ATTRIBUTES noreturn :: foo4
|
||||
call foo2()
|
||||
end subroutine foo4 ! { dg-bogus "warning:" "this function should not get any warnings" }
|
||||
|
||||
subroutine foo5
|
||||
!GCC$ ATTRIBUTES noreturn :: foo5
|
||||
return ! { dg-warning "'noreturn' function does return" "detect invalid return" }
|
||||
end subroutine foo5
|
||||
|
||||
subroutine foo6
|
||||
return
|
||||
end subroutine foo6 ! { dg-bogus "warning:" "this function should not get any warnings" }
|
||||
|
||||
subroutine foo7
|
||||
call foo6()
|
||||
end subroutine foo7 ! { dg-bogus "warning:" "this function should not get any warnings" }
|
||||
|
||||
subroutine foo8
|
||||
!GCC$ ATTRIBUTES noreturn :: foo8
|
||||
call foo7()
|
||||
end subroutine foo8 ! { dg-warning "'noreturn' function does return" "detect return from tail call" }
|
||||
|
||||
subroutine foo9
|
||||
!GCC$ ATTRIBUTES noreturn :: foo9
|
||||
interface
|
||||
subroutine bar
|
||||
!GCC$ ATTRIBUTES noreturn :: bar
|
||||
end subroutine bar
|
||||
end interface
|
||||
call bar()
|
||||
end subroutine foo9 ! { dg-bogus "warning:" "this function should not get any warnings" }
|
||||
|
||||
function ffo1()
|
||||
implicit none
|
||||
!GCC$ ATTRIBUTES noreturn :: ffo1
|
||||
integer :: ffo1
|
||||
ffo1 = 0
|
||||
end function ffo1 ! { dg-warning "'noreturn' function does return" "detect falling off end of noreturn" }
|
53
gcc/testsuite/gfortran.dg/noreturn-2.f90
Normal file
53
gcc/testsuite/gfortran.dg/noreturn-2.f90
Normal file
|
@ -0,0 +1,53 @@
|
|||
! { dg-do compile }
|
||||
! { dg-options "-O2 -Wuninitialized" }
|
||||
|
||||
subroutine foo1
|
||||
implicit none
|
||||
interface
|
||||
subroutine bar1
|
||||
!GCC$ ATTRIBUTES noreturn :: bar1
|
||||
end subroutine
|
||||
end interface
|
||||
real,allocatable :: d(:) ! { dg-note "declared here" "note" }
|
||||
d = 0. ! { dg-warning "used uninitialized" "uninitialized descriptor" }
|
||||
call bar1()
|
||||
d = 0. ! { dg-bogus "warning:" "not optimized out" }
|
||||
end subroutine foo1
|
||||
|
||||
function foo2()
|
||||
integer :: foo2
|
||||
interface
|
||||
subroutine bar2
|
||||
!GCC$ ATTRIBUTES noreturn :: bar2
|
||||
end subroutine
|
||||
end interface
|
||||
call bar2
|
||||
return ! { dg-bogus "__result_foo2' is used uninitialized" "return" }
|
||||
foo2 = 0
|
||||
end function foo2
|
||||
|
||||
subroutine foo3
|
||||
implicit none
|
||||
integer :: i,j
|
||||
interface
|
||||
subroutine abort2
|
||||
!GCC$ ATTRIBUTES noreturn :: abort2
|
||||
end subroutine
|
||||
end interface
|
||||
call abort2()
|
||||
do i=1,j-1 ; end do ! { dg-bogus "is used uninitialized" "uninitialized" }
|
||||
end subroutine foo3
|
||||
|
||||
function foo4()
|
||||
integer :: foo4
|
||||
!$GCC$ ATTRIBUTES noreturn :: foo4
|
||||
foo4 = 1
|
||||
end function
|
||||
|
||||
subroutine foo5(k)
|
||||
implicit none
|
||||
integer :: i, k
|
||||
!GCC$ ATTRIBUTES noreturn :: mpi_abort
|
||||
call mpi_abort()
|
||||
k = i
|
||||
end subroutine
|
14
gcc/testsuite/gfortran.dg/noreturn-3.f90
Normal file
14
gcc/testsuite/gfortran.dg/noreturn-3.f90
Normal file
|
@ -0,0 +1,14 @@
|
|||
! { dg-do compile }
|
||||
! { dg-additional-options "-Wuninitialized -Wmaybe-uninitialized" }
|
||||
|
||||
subroutine foo
|
||||
implicit none
|
||||
integer :: i
|
||||
!GCC$ ATTRIBUTES noreturn :: mpi_abort
|
||||
if (getpid() == 1) then
|
||||
call mpi_abort()
|
||||
else
|
||||
i = 8
|
||||
endif
|
||||
if (i > 0) print *, i
|
||||
end subroutine
|
11
gcc/testsuite/gfortran.dg/noreturn-4.f90
Normal file
11
gcc/testsuite/gfortran.dg/noreturn-4.f90
Normal file
|
@ -0,0 +1,11 @@
|
|||
! { dg-do run { target { nonpic || pie_enabled } } }
|
||||
! { dg-options "-O2" }
|
||||
|
||||
program bar
|
||||
call foo1()
|
||||
call noreturn_autodetection_failed() ! check if optimized out
|
||||
end program
|
||||
|
||||
subroutine foo1
|
||||
stop 0
|
||||
end subroutine foo1
|
9
gcc/testsuite/gfortran.dg/noreturn-5.f90
Normal file
9
gcc/testsuite/gfortran.dg/noreturn-5.f90
Normal file
|
@ -0,0 +1,9 @@
|
|||
! { dg-do compile }
|
||||
! { dg-options "-O2" }
|
||||
|
||||
subroutine bar
|
||||
!GCC$ ATTRIBUTES noreturn :: foo1
|
||||
call foo1()
|
||||
call noreturn_autodetection_failed()
|
||||
end subroutine
|
||||
! /* { dg-final { scan-assembler-not "noreturn_autodetection_failed" } } */
|
6
gcc/testsuite/gfortran.dg/weak-1.f90
Normal file
6
gcc/testsuite/gfortran.dg/weak-1.f90
Normal file
|
@ -0,0 +1,6 @@
|
|||
! { dg-do compile }
|
||||
! { dg-require-weak "" }
|
||||
! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?impl" } }
|
||||
subroutine impl
|
||||
!GCC$ ATTRIBUTES weak :: impl
|
||||
end subroutine
|
Loading…
Add table
Reference in a new issue