[Patch, Fortran, OOP] PR 45290/45271: pointer initialization / vtab init

Tobias Burnus burnus@net-b.de
Fri Aug 20 13:14:00 GMT 2010


  On 08/20/2010 02:11 PM, Janus Weil wrote:
> well, I have been wondering about this myself. I think what currently
> happens for a module function which is used as an initialization
> target in the header of the module is the following:
>
> 1) When translating the initializer, we create a backend_decl via
> gfc_get_extern_function_decl.
> 2) When generating the function code, we create another one using
> gfc_create_function_decl (overriding the old one).
>
> While the middle end seems to handle this alright

I think the middle end does not handle it correctly - you are just lucky 
that it does not see any optimization possibility for your code. And if 
it does not do some "clever" optimizations it works as the function name 
is the same - which is all what counts on assembler level.

> @@ -1608,9 +1622,11 @@ build_function_decl (gfc_symbol * sym, bool global
>     tree result_decl;
>     gfc_formal_arglist *f;
>
> -  gcc_assert (!sym->backend_decl);
>     gcc_assert (!sym->attr.external);
>
> +  if (sym->backend_decl)
> +    return;

I think that's better - but I wonder whether the generated DECL ends up 
in the wrong scope. Procedure declarations generated through 
gfc_get_extern_function_decl are in the global scope:

           /* By construction, the external function cannot be
              a contained procedure.  */ [...]
           current_function_decl = NULL_TREE;
           push_cfun (cfun);
           gfc_create_function_decl (gsym->ns, true);
where global=true, which hoists the decl into the global namespace:
   if (global)
     pushdecl_top_level (fndecl);

If I now look at gfc_generate_module_code, I see:
   ns->proc_name->backend_decl
     = build_decl (ns->proc_name->declared_at.lb->location,
                   NAMESPACE_DECL, get_identifier (ns->proc_name->name),
                   void_type_node);
[...]
   for (n = ns->contained; n; n = n->sibling)
     {
       gfc_create_function_decl (n, false);
       DECL_CONTEXT (n->proc_name->backend_decl) = 
ns->proc_name->backend_decl;

Thus, I wonder whether this generates them also in global namespace or 
not. I think it works for modules (if one follows current_function_decl) 
- but does it also work in cases like:

subroutine foo()
   type t
      procedure(int), pointer :: p => int
   end type t
   class(t) :: x
...
contains
   subroutine int()
   end
end

Here, "int" has clearly not global scope. (Side note: I think this is 
only valid since F2008 as before internal procedures could not be used 
as actual argument due to some issues which also affect proc pointers, 
cf. PR which is linked from the wiki's F2008 status page.)

I might miss something, but at least I am not convinced that the code 
will be generated in the correct scope. (Actually, in case of such 
procedure initializations, it might be that the current scope is the 
correct one - if the procedure is in the same scope as the generated 
initialization.)

Tobias



More information about the Fortran mailing list