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" } }
+