A PRIVATE module variable, which is used in the specification expression of a function result variable cannot be TREE_PUBLIC()=0, unless the function itself is PRIVATE and also not accessible via type-bound procedures or a generic name. (The issue is gfortran specific as most compilers do not seem to save the specification expression in the .mod file.)

Build and regtested on x86-64-linux.
OK for the trunk?

Tobias

2012-05-03  Tobias Burnus  <bur...@net-b.de>

	PR fortran/53175
	* resolve.c (resolve_variable): Set public_used
	if a private module variable is used in a (public)
	specification expression.
	* trans-decl.c (gfc_finish_var_decl): Mark those
	TREE_PUBLIC.

2012-05-03  Tobias Burnus  <bur...@net-b.de>

	PR fortran/53175
	gfortran.dg/public_private_module_5.f90: New.

diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 57da577..e15d6e1 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -5124,6 +5124,19 @@ resolve_variable (gfc_expr *e)
   if (check_assumed_size_reference (sym, e))
     return FAILURE;
 
+  /* If a PRIVATE variable is used in the specification expression of the
+     result variable, it might be accessed from outside the module and can
+     thus not be TREE_PUBLIC() = 0.
+     TODO: sym->attr.public_used only has to be set for the result variable's
+     type-parameter expression and not for dummies or automatic variables.
+     Additionally, it only has to be set if the function is either PUBLIC or
+     used in a generic interface or TBP; unfortunately,
+     proc_name->attr.public_used can get set at a later stage.  */
+  if (specification_expr && sym->attr.access == ACCESS_PRIVATE
+      && !sym->attr.function && !sym->attr.use_assoc
+      && gfc_current_ns->proc_name && gfc_current_ns->proc_name->attr.function)
+    sym->attr.public_used = 1;
+
   /* Deal with forward references to entries during resolve_code, to
      satisfy, at least partially, 12.5.2.5.  */
   if (gfc_current_ns->entries
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index d6c090e..9196f0a 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -565,7 +565,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
       /* TODO: Don't set sym->module for result or dummy variables.  */
       gcc_assert (current_function_decl == NULL_TREE || sym->result == sym);
       /* This is the declaration of a module variable.  */
-      if (sym->attr.access != ACCESS_PRIVATE)
+      if (sym->attr.access != ACCESS_PRIVATE || sym->attr.public_used)
 	TREE_PUBLIC (decl) = 1;
       TREE_STATIC (decl) = 1;
     }
--- /dev/null	2012-04-23 08:17:57.683771451 +0200
+++ gcc/gcc/testsuite/gfortran.dg/public_private_module_5.f90	2012-05-03 15:11:54.000000000 +0200
@@ -0,0 +1,40 @@
+! { dg-do compile }
+! { dg-options "-O3" }
+!
+! PR fortran/53175
+!
+
+MODULE ENERGY_FUNCTION
+   IMPLICIT NONE
+
+   TYPE PARAM
+      PRIVATE
+         INTEGER :: WHICH_VECTOR
+   END TYPE PARAM
+
+   INTEGER, PRIVATE :: DIM2
+   INTEGER, PRIVATE :: DIM5
+
+   private :: specific
+   interface gen
+     module procedure  specific
+   end interface gen
+
+   CONTAINS
+
+      FUNCTION ENERGY_FUNCTION_CURRENT_ARGS()
+         INTEGER, DIMENSION(DIM2) :: ENERGY_FUNCTION_CURRENT_ARGS
+      END FUNCTION ENERGY_FUNCTION_CURRENT_ARGS
+
+      FUNCTION ENERGY_FUNCTION_GET_PARAMS()
+         TYPE(PARAM), DIMENSION(DIM2) :: ENERGY_FUNCTION_GET_PARAMS
+      END FUNCTION ENERGY_FUNCTION_GET_PARAMS   
+
+      function specific()
+        character(len=dim5) :: specific
+      end function specific
+END MODULE ENERGY_FUNCTION
+
+! { dg-final { scan-assembler "__energy_function_MOD_dim2" } }
+! { dg-final { scan-assembler "__energy_function_MOD_dim5" } }
+

Reply via email to