public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* Support for module-wide attributes
@ 2023-02-23 14:27 Rimvydas Jasinskas
  0 siblings, 0 replies; only message in thread
From: Rimvydas Jasinskas @ 2023-02-23 14:27 UTC (permalink / raw)
  To: Rimvydas Jasinskas via Fortran

[-- Attachment #1: Type: text/plain, Size: 1580 bytes --]

Hello everyone,

this patch implements module-wide gcc directive support to apply
attributes to the whole module.  Patch closely follows how plain SAVE
statement is implemented with seen_save/gfc_save_all() by using
"mod_ext_attr" bitfield in a current namespace.

There are certain complications how WEAK attribute could be safely
applied to non local symbols, applying WEAK attribute requires to
delay this until build_function_decl() sets the final attr.access
field.

For a time being I opted out to explicitly reject setting the
NO_ARG_CHECK attribute for the whole module.  There should not be a
legitimate case to apply it for every dummy argument.

One DEPRECATED diagnostic (for deprecated parameter use case inside
the same module) did not carry out from the original
gfortran.dg/attr_deprecated.f90 testcase.  Not sure how to tackle it
yet, parsing order is a bit confusing.  Giving diagnostics for
deprecated symbols inside the whole module marked as deprecated seems
to be a bit excessive.  Only giving diagnostics for the actual use
cases of such marked module components would seem to be more
intuitive.  Also from the original testcase:
use m  ! { dg-warning "Using parameter 'parm' declared at .1. is deprecated" }
shouldn't diagnostic prefer to report "use" location instead of
declaration, since it is more important for the user?  The declaration
location could be additionally reported as dg-note using some helper
function that checks if the symbol is "imported at (1)" versus
"declared at (1)".

Regtested cleanly on x86_64-pc-linux-gnu.

Regards,
Rimvydas

[-- Attachment #2: 0002-Fortran-Add-support-for-module-wide-attributes.patch --]
[-- Type: text/x-patch, Size: 14186 bytes --]

From e5319c1733bca56be710c8cbce763fe459dfae73 Mon Sep 17 00:00:00 2001
From: Rimvydas Jasinskas <rimvydas.jas@gmail.com>
Date: Thu, 23 Feb 2023 12:59:57 +0000
Subject: Fortran: Add support for module-wide attributes

 The WEAK attribute handling needs to be delayed after sym->attr.access is set.

gcc/fortran/ChangeLog:

	* decl.cc (gfc_match_gcc_attributes): Add diagnostic for NO_ARG_CHECK.
	* gfortran.h (gfc_apply_mod_ext_attr): New prototype.
	(gfc_namespace): Add mod_ext_attr bitfield.
	* resolve.cc (resolve_types): Use gfc_apply_mod_ext_attr().
	* symbol.cc (apply_mod_ext_attr): New procedure.
	(gfc_apply_mod_ext_attr): New procedure.
	* trans-decl.cc (build_function_decl): Handle module-wide WEAK
	attribute for public procedures.  Move local 'attr' copy down.
	(gfc_create_module_variable): Handle module-wide WEAK attribute for
	non-private variables.

gcc/testsuite/ChangeLog:

	* gfortran.dg/attr_deprecated-3.f90: New test.
	* gfortran.dg/attr_deprecated-4.f90: New test.
	* gfortran.dg/no_arg_check_4.f90: New test.
	* gfortran.dg/noinline-2.f90: New test.
	* gfortran.dg/noreturn-6.f90: New test.
	* gfortran.dg/weak-10.f90: New test.
	* gfortran.dg/weak-11.f90: New test.
	* gfortran.dg/weak-12.f90: New test.
	* gfortran.dg/weak-9.f90: New test.

Signed-off-by: Rimvydas Jasinskas <rimvydas.jas@gmail.com>
---
 gcc/fortran/decl.cc                           | 11 ++++++
 gcc/fortran/gfortran.h                        |  3 ++
 gcc/fortran/resolve.cc                        |  3 ++
 gcc/fortran/symbol.cc                         | 38 +++++++++++++++++++
 gcc/fortran/trans-decl.cc                     | 16 +++++++-
 .../gfortran.dg/attr_deprecated-3.f90         | 30 +++++++++++++++
 .../gfortran.dg/attr_deprecated-4.f90         | 24 ++++++++++++
 gcc/testsuite/gfortran.dg/no_arg_check_4.f90  | 14 +++++++
 gcc/testsuite/gfortran.dg/noinline-2.f90      | 29 ++++++++++++++
 gcc/testsuite/gfortran.dg/noreturn-6.f90      | 10 +++++
 gcc/testsuite/gfortran.dg/weak-10.f90         | 17 +++++++++
 gcc/testsuite/gfortran.dg/weak-11.f90         | 17 +++++++++
 gcc/testsuite/gfortran.dg/weak-12.f90         | 18 +++++++++
 gcc/testsuite/gfortran.dg/weak-9.f90          | 17 +++++++++
 14 files changed, 245 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/attr_deprecated-3.f90
 create mode 100644 gcc/testsuite/gfortran.dg/attr_deprecated-4.f90
 create mode 100644 gcc/testsuite/gfortran.dg/no_arg_check_4.f90
 create mode 100644 gcc/testsuite/gfortran.dg/noinline-2.f90
 create mode 100644 gcc/testsuite/gfortran.dg/noreturn-6.f90
 create mode 100644 gcc/testsuite/gfortran.dg/weak-10.f90
 create mode 100644 gcc/testsuite/gfortran.dg/weak-11.f90
 create mode 100644 gcc/testsuite/gfortran.dg/weak-12.f90
 create mode 100644 gcc/testsuite/gfortran.dg/weak-9.f90

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index eec0314cf4c..9bc05f5acd8 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -11811,6 +11811,17 @@ gfc_match_gcc_attributes (void)
 
       sym->attr.ext_attr |= attr.ext_attr;
 
+      if (sym->attr.flavor == FL_MODULE)
+	{
+	  if (attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+	    {
+	      gfc_error ("The %<NO_ARG_CHECK%> attribute cannot be applied"
+			 " module-wide at %C");
+	      return MATCH_NO;
+	    }
+	  gfc_current_ns->mod_ext_attr |= attr.ext_attr;
+	}
+
       if (gfc_match_eos () == MATCH_YES)
 	break;
 
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index fea25312cf4..5e06429424b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2160,6 +2160,8 @@ typedef struct gfc_namespace
 
   int save_all, seen_save, seen_implicit_none;
 
+  unsigned mod_ext_attr;
+
   /* Normally we don't need to refcount namespaces.  However when we read
      a module containing a function with multiple entry points, this
      will appear as several functions with the same formal namespace.  */
@@ -3513,6 +3515,7 @@ void gfc_traverse_symtree (gfc_symtree *, void (*)(gfc_symtree *));
 void gfc_traverse_ns (gfc_namespace *, void (*)(gfc_symbol *));
 void gfc_traverse_user_op (gfc_namespace *, void (*)(gfc_user_op *));
 void gfc_save_all (gfc_namespace *);
+void gfc_apply_mod_ext_attr (gfc_namespace *);
 
 void gfc_enforce_clean_symbol_state (void);
 
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 2780c82c798..839b63d1715 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -17600,6 +17600,9 @@ resolve_types (gfc_namespace *ns)
   if (ns->save_all || (!flag_automatic && !recursive))
     gfc_save_all (ns);
 
+  if (ns->mod_ext_attr)
+    gfc_apply_mod_ext_attr (ns);
+
   iter_stack = NULL;
   for (d = ns->data; d; d = d->next)
     resolve_data (d);
diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 2ce0f3e4df7..2e202443b82 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -4284,6 +4284,44 @@ gfc_save_all (gfc_namespace *ns)
   gfc_traverse_ns (ns, save_symbol);
 }
 
+/* Given a symbol, apply module-wide attributes if it is allowed.  */
+
+static void
+apply_mod_ext_attr (gfc_symbol *sym)
+{
+  unsigned ext_mask = (1 << EXT_ATTR_LAST) - 1;
+
+  if (sym->attr.use_assoc)
+    return;
+
+  /* Exclude NO_ARG_CHECK attribute by default, handled in decl.cc.  */
+  ext_mask -= (1 << EXT_ATTR_NO_ARG_CHECK);
+
+  /* Exclude WEAK attribute here, handled once attr.access is fully set.  */
+  ext_mask -= (1 << EXT_ATTR_WEAK);
+
+  /* Ignore all procedure-only module-wide attributes for variables.  */
+  if (sym->attr.flavor != FL_PROCEDURE)
+    {
+      ext_mask -= 1 << EXT_ATTR_STDCALL;
+      ext_mask -= 1 << EXT_ATTR_CDECL;
+      ext_mask -= 1 << EXT_ATTR_FASTCALL;
+      ext_mask -= 1 << EXT_ATTR_NOINLINE;
+      ext_mask -= 1 << EXT_ATTR_NORETURN;
+   }
+
+  sym->attr.ext_attr |= sym->ns->mod_ext_attr & ext_mask;
+}
+
+
+/* Apply module-wide attributes to symbols where possible.  */
+
+void
+gfc_apply_mod_ext_attr (gfc_namespace *ns)
+{
+  gfc_traverse_ns (ns, apply_mod_ext_attr);
+}
+
 
 /* Make sure that no changes to symbols are pending.  */
 
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 24a85cf6043..5f3a75a1524 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -2399,8 +2399,6 @@ build_function_decl (gfc_symbol * sym, bool global)
   fndecl = build_decl (input_location,
 		       FUNCTION_DECL, gfc_sym_identifier (sym), type);
 
-  attr = sym->attr;
-
   /* Initialize DECL_EXTERNAL and TREE_PUBLIC before calling decl_attributes;
      TREE_PUBLIC specifies whether a function is globally addressable (i.e.
      the opposite of declaring a function as static in C).  */
@@ -2421,6 +2419,13 @@ build_function_decl (gfc_symbol * sym, bool global)
   if (sym->attr.referenced || sym->attr.entry_master)
     TREE_USED (fndecl) = 1;
 
+  /* Add module-wide WEAK attribute after attr.access is set.  */
+  if (sym->module && sym->attr.access != ACCESS_PRIVATE
+      && sym->ns->mod_ext_attr & (1 << EXT_ATTR_WEAK))
+    sym->attr.ext_attr |= (1 << EXT_ATTR_WEAK);
+
+  attr = sym->attr;
+
   attributes = add_attributes_to_decl (attr, NULL_TREE);
   decl_attributes (&fndecl, attributes, 0);
 
@@ -5273,6 +5278,13 @@ gfc_create_module_variable (gfc_symbol * sym)
 		 "Unused PRIVATE module variable %qs declared at %L",
 		 sym->name, &sym->declared_at);
 
+  /* Add module-wide WEAK attribute after attr.access is set.  Allow only
+     explicit weak declaration for private variables for now, mainly to avoid
+     unintended complications with hidden/weak symbols.  */
+  if (sym->module && sym->attr.access != ACCESS_PRIVATE
+      && sym->ns->mod_ext_attr & (1 << EXT_ATTR_WEAK))
+    sym->attr.ext_attr |= (1 << EXT_ATTR_WEAK);
+
   /* We always want module variables to be created.  */
   sym->attr.referenced = 1;
   /* Create the decl.  */
diff --git a/gcc/testsuite/gfortran.dg/attr_deprecated-3.f90 b/gcc/testsuite/gfortran.dg/attr_deprecated-3.f90
new file mode 100644
index 00000000000..39bd6c388bd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/attr_deprecated-3.f90
@@ -0,0 +1,30 @@
+! { dg-do compile }
+
+module m
+  implicit none
+  integer :: A
+  integer, parameter :: PARM = 5  ! { dg-warning "Using parameter 'parm' declared at .1. is deprecated" "TODO" { xfail *-*-* } }
+!GCC$ ATTRIBUTES  DEPRECATED :: m
+contains
+subroutine foo
+end
+integer function func()
+  func = 42
+end
+subroutine bar
+  integer :: i
+  call foo    ! { dg-warning "Using subroutine 'foo' at .1. is deprecated" }
+  print *, A  ! { dg-warning "Using variable 'a' at .1. is deprecated" }
+  i = func()  ! { dg-warning "Using function 'func' at .1. is deprecated" }
+  print *, PARM
+end
+
+end module m
+
+use m  ! { dg-warning "Using parameter 'parm' declared at .1. is deprecated" }
+  integer :: i
+  call foo  ! { dg-warning "Using subroutine 'foo' at .1. is deprecated" }
+  print *, A  ! { dg-warning "Using variable 'a' at .1. is deprecated" }
+  i = func()  ! { dg-warning "Using function 'func' at .1. is deprecated" }
+  print *, PARM
+end
diff --git a/gcc/testsuite/gfortran.dg/attr_deprecated-4.f90 b/gcc/testsuite/gfortran.dg/attr_deprecated-4.f90
new file mode 100644
index 00000000000..22237b91c06
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/attr_deprecated-4.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+
+module m
+  implicit none
+!GCC$ ATTRIBUTES  DEPRECATED :: m
+  interface dar
+  procedure :: foo
+  subroutine bar(p)
+    implicit none
+    real :: p
+  end subroutine
+  end interface
+contains
+subroutine foo(n)
+  implicit none
+  integer :: n
+end subroutine
+end module m
+
+use m
+  call foo(1)  ! { dg-warning "Using subroutine 'foo' at .1. is deprecated" }
+  call dar(1)  ! { dg-warning "Using subroutine 'foo' at .1. is deprecated" }
+  call dar(1.) ! { dg-warning "Using subroutine 'bar' at .1. is deprecated" }
+end
diff --git a/gcc/testsuite/gfortran.dg/no_arg_check_4.f90 b/gcc/testsuite/gfortran.dg/no_arg_check_4.f90
new file mode 100644
index 00000000000..097184331e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/no_arg_check_4.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+!
+module mpi_interface
+  implicit none
+!GCC$ attributes NO_ARG_CHECK :: mpi_interface
+! { dg-error "The 'NO_ARG_CHECK' attribute cannot be applied module-wide" "reject" {target *-*-*} .-1 }
+  integer :: i
+contains
+  subroutine foo(n,p)
+    implicit none
+    integer :: n
+    real :: p
+  end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/noinline-2.f90 b/gcc/testsuite/gfortran.dg/noinline-2.f90
new file mode 100644
index 00000000000..96010fa7cf5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/noinline-2.f90
@@ -0,0 +1,29 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-dom2" }
+
+module m
+!GCC$ ATTRIBUTES noinline :: m
+integer :: abc(7)
+contains
+
+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(*)
+do j=1,n
+  b(m+j-1)=p(j)
+enddo
+m=m+n
+end subroutine foo
+
+end module
+
+! { dg-final { scan-tree-dump-times "foo \\(" 4 "dom2"} }
diff --git a/gcc/testsuite/gfortran.dg/noreturn-6.f90 b/gcc/testsuite/gfortran.dg/noreturn-6.f90
new file mode 100644
index 00000000000..4e1de384cfe
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/noreturn-6.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! { dg-options "-Wall -Wextra" }
+
+module m
+!GCC$ ATTRIBUTES noreturn :: m
+integer :: ijk
+contains
+subroutine foo
+end subroutine foo ! { dg-warning "'noreturn' function does return" "" }
+end module
diff --git a/gcc/testsuite/gfortran.dg/weak-10.f90 b/gcc/testsuite/gfortran.dg/weak-10.f90
new file mode 100644
index 00000000000..c382c455d08
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/weak-10.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-require-weak "" }
+! { dg-options "-Wall -Wextra" }
+module foo
+implicit none
+!GCC$ ATTRIBUTES weak :: foo
+integer :: ijk
+private :: ijk,bar
+!GCC$ ATTRIBUTES weak :: bar
+contains
+subroutine bar ! { dg-error "weak declaration of 'bar' must be public" "" }
+ijk = 1
+end subroutine
+subroutine dar
+call bar
+end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/weak-11.f90 b/gcc/testsuite/gfortran.dg/weak-11.f90
new file mode 100644
index 00000000000..e49f13101a2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/weak-11.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-require-weak "" }
+! { dg-skip-if "" { x86_64-*-mingw* } }
+! { dg-skip-if "" { nvptx-*-* } }
+! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?__foo_MOD_abc" } }
+! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?__foo_MOD_bar" } }
+! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?__foo_MOD_dar" } }
+module foo
+implicit none
+!GCC$ ATTRIBUTES weak :: foo
+real :: abc(7)
+contains
+ subroutine bar
+ end subroutine
+ integer function dar()
+ end function
+end module
diff --git a/gcc/testsuite/gfortran.dg/weak-12.f90 b/gcc/testsuite/gfortran.dg/weak-12.f90
new file mode 100644
index 00000000000..39deb1eafbe
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/weak-12.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! { dg-require-weak "" }
+! { dg-skip-if "" { x86_64-*-mingw* } }
+! { dg-skip-if "" { nvptx-*-* } }
+! { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?__foo_MOD_abc" } }
+! { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?__foo_MOD_bar" } }
+! { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?__foo_MOD_dar" } }
+module foo
+implicit none
+private
+!GCC$ ATTRIBUTES weak :: foo
+real :: abc(7)
+contains
+ subroutine bar
+ end subroutine
+ integer function dar()
+ end function
+end module
diff --git a/gcc/testsuite/gfortran.dg/weak-9.f90 b/gcc/testsuite/gfortran.dg/weak-9.f90
new file mode 100644
index 00000000000..b5e92fc09de
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/weak-9.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-require-weak "" }
+! { dg-options "-Wall -Wextra" }
+module foo
+implicit none
+!GCC$ ATTRIBUTES weak :: foo
+integer :: ijk
+private
+public :: dar
+contains
+subroutine bar
+ijk = 1
+end subroutine
+subroutine dar
+call bar
+end subroutine
+end module
-- 
2.39.2


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-23 14:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-23 14:27 Support for module-wide attributes Rimvydas Jasinskas

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).