Bug 51081 - [F03] Proc-pointer assignment: Rejects valid internal proc
Summary: [F03] Proc-pointer assignment: Rejects valid internal proc
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: diagnostic, rejects-valid
Depends on:
Blocks:
 
Reported: 2011-11-10 14:32 UTC by Tobias Burnus
Modified: 2012-07-30 19:59 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-04-16 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2011-11-10 14:32:31 UTC
Trivial diagnostic bug.

Compiling with -std=2003 just prints:

  Error: Internal procedure 'int' is invalid
         in procedure pointer assignment at (1)

Expected: It mentions that it is actually valid in Fortran 2008, e.g.

  Error: Fortran 2008: Internal procedure 'int'
         in procedure pointer assignment at (1)

ptr => int
contains
  subroutine int()
  end subroutine int
end
Comment 1 Tobias Burnus 2011-11-10 14:42:43 UTC
First, my example was incomplete. Secondly, I just realized that gfortran rejects the program although I think it is valid (ifort also compiles it):

  subroutine int2()
                 1
Error: FUNCTION attribute conflicts with SUBROUTINE attribute in 'int2' at (1)

I do not see why gfortran regards "int2" as function. If one uncomments the call line, one even gets:

Error: Interface mismatch in procedure pointer assignment at (1): 'int2' is not a subroutine


procedure(), pointer :: ptr
ptr => int2
! call ptr()
contains
  subroutine int2()
  end subroutine int2
end
Comment 2 Tobias Burnus 2011-11-10 14:47:42 UTC
(In reply to comment #1)
>   subroutine int2()
>                  1
> Error: FUNCTION attribute conflicts with SUBROUTINE attribute in 'int2' at (1)

Seemingly both INT and INT2 have some special meaning as for instance INT44 works. (Answer: INT2 is a GNU intrinsic to convert the argument to INTEGER(2).)

Nevertheless, the code should be valid, unless one has used an explicit "intrinsic int" or "intrinsic int2".
Comment 3 janus 2012-04-16 12:01:46 UTC
(In reply to comment #1)
> First, my example was incomplete. Secondly, I just realized that gfortran
> rejects the program although I think it is valid (ifort also compiles it):
> 
>   subroutine int2()
>                  1
> Error: FUNCTION attribute conflicts with SUBROUTINE attribute in 'int2' at (1)

I only get this with 4.6.3, but with 4.7 and trunk I get:

  subroutine int2()
                 1
Error: 'int2' declared INTRINSIC at (1) does not exist


This error message even appears three times and is just as wrong as the other one.
Comment 4 janus 2012-04-16 12:37:26 UTC
(In reply to comment #0)
> Compiling with -std=2003 just prints:
> 
>   Error: Internal procedure 'int' is invalid
>          in procedure pointer assignment at (1)

This is of course easily fixed:

Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 186485)
+++ gcc/fortran/expr.c	(working copy)
@@ -3444,9 +3444,10 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_ex
 	      return FAILURE;
 	    }
 	  if (attr.proc == PROC_INTERNAL &&
-	      gfc_notify_std (GFC_STD_F2008, "Internal procedure '%s' is "
-			      "invalid in procedure pointer assignment at %L",
-			      rvalue->symtree->name, &rvalue->where) == FAILURE)
+	      gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Internal procedure "
+			      "'%s' is invalid in procedure pointer assignment "
+			      "at %L", rvalue->symtree->name, &rvalue->where)
+			      == FAILURE)
 	    return FAILURE;
 	}
       /* Check for F08:C730.  */



An alternative would be to add the correct label automatically inside 'gfc_notify_std', based on the value of 'GFC_STD_*' passed.
Comment 5 janus 2012-07-17 21:51:25 UTC
Author: janus
Date: Tue Jul 17 21:51:20 2012
New Revision: 189589

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=189589
Log:
2012-07-17  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/51081
	* error.c (gfc_notify_std): Automatically print the relevant Fortran
	standard version.
	* arith.c (arith_power): Remove explicit standard reference string.
	* array.c (gfc_match_array_spec, gfc_match_array_constructor): Ditto.
	* check.c (gfc_check_a_p, gfc_check_besn, gfc_check_count,
	gfc_check_float, gfc_check_fn_rc2008, gfc_check_iand,
	gfc_check_ichar_iachar, gfc_check_ieor, gfc_check_index, gfc_check_ior,
	gfc_check_lbound, gfc_check_len_lentrim, check_rest, gfc_check_min_max,
	gfc_check_null, gfc_check_scan, gfc_check_selected_real_kind,
	gfc_check_shape, gfc_check_size, gfc_check_sngl, gfc_check_ubound,
	gfc_check_verify): Ditto.
	* data.c (gfc_assign_data_value): Ditto.
	* decl.c (var_element, char_len_param_value, match_char_length,
	gfc_verify_c_interop_param, match_pointer_init, variable_decl,
	gfc_match_decl_type_spec, gfc_match_import, match_attr_spec, 
	gfc_match_prefix, gfc_match_suffix, match_ppc_decl,
	match_procedure_in_interface, gfc_match_procedure,gfc_match_entry,
	gfc_match_subroutine, gfc_match_end, gfc_match_codimension,
	gfc_match_protected, gfc_match_value, gfc_match_volatile,
	gfc_match_asynchronous, gfc_match_modproc, gfc_get_type_attr_spec,
	gfc_match_enum, match_procedure_in_type): Ditto.
	* expr.c (check_elemental, gfc_check_assign, gfc_check_pointer_assign):
	Ditto.
	* interface.c (gfc_match_abstract_interface, check_interface0): Ditto.
	* intrinsic.c (gfc_intrinsic_func_interface): Ditto.
	* io.c (format_lex, resolve_tag_format, resolve_tag,
	compare_to_allowed_values, gfc_match_open, gfc_match_rewind,
	gfc_resolve_dt, gfc_match_wait): Ditto.
	* match.c (match_arithmetic_if, gfc_match_if, gfc_match_critical,
	gfc_match_do, match_exit_cycle, gfc_match_pause, gfc_match_stop,
	gfc_match_lock, sync_statement, gfc_match_assign, gfc_match_goto,
	gfc_match_allocate, gfc_match_return, gfc_match_st_function): Ditto.
	* module.c (gfc_match_use, gfc_use_module): Ditto.
	* parse.c (parse_derived_contains, parse_block_construct,
	parse_associate, parse_contained): Ditto.
	* primary.c (match_hollerith_constant, match_boz_constant,
	match_real_constant, match_sym_complex_part, match_arg_list_function,
	build_actual_constructor, gfc_convert_to_structure_constructor): Ditto.
	* resolve.c (resolve_formal_arglist, resolve_entries,
	resolve_common_blocks, resolve_actual_arglist, gfc_resolve_index_1,
	gfc_resolve_iterator_expr, resolve_ordinary_assign,
	resolve_fl_var_and_proc, resolve_fl_variable_derived,
	resolve_fl_procedure, resolve_fl_derived0, resolve_fl_derived,
	resolve_fl_namelist, resolve_symbol, resolve_fntype): Ditto.
	* symbol.c (check_conflict, conflict, gfc_add_is_bind_c,
	gfc_add_extension, gfc_check_symbol_typed): Ditto.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/arith.c
    trunk/gcc/fortran/array.c
    trunk/gcc/fortran/check.c
    trunk/gcc/fortran/data.c
    trunk/gcc/fortran/decl.c
    trunk/gcc/fortran/error.c
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/intrinsic.c
    trunk/gcc/fortran/io.c
    trunk/gcc/fortran/match.c
    trunk/gcc/fortran/module.c
    trunk/gcc/fortran/parse.c
    trunk/gcc/fortran/primary.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/symbol.c
Comment 6 janus 2012-07-18 08:10:43 UTC
(In reply to comment #4)
> An alternative would be to add the correct label automatically inside
> 'gfc_notify_std', based on the value of 'GFC_STD_*' passed.

This has been implemented with r189589.

ToDo: Fix the bogus errors about INT and INT2, cf. comment 2 and 3.
Comment 7 janus 2012-07-18 12:54:32 UTC
(In reply to comment #6)
> ToDo: Fix the bogus errors about INT and INT2, cf. comment 2 and 3.

The following patch makes the test case in comment #1 work:

Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 189608)
+++ gcc/fortran/primary.c	(working copy)
@@ -2843,9 +2843,6 @@ gfc_match_rvalue (gfc_expr **result)
 	    /* Parse functions returning a procptr.  */
 	    goto function0;
 
-	  if (gfc_is_intrinsic (sym, 0, gfc_current_locus)
-	      || gfc_is_intrinsic (sym, 1, gfc_current_locus))
-	    sym->attr.intrinsic = 1;
 	  e = gfc_get_expr ();
 	  e->expr_type = EXPR_VARIABLE;
 	  e->symtree = symtree;


However, it regresses on proc_ptr_{1,6,11,12,15}.f90 and sizeof_proc.f90.

Surely the setting of attr.intrinsic comes too early in gfc_match_rvalue. It probably should be deferred to resolution stage, where we know about the presence of the internal proc.
Comment 8 janus 2012-07-29 16:55:11 UTC
Related accepts-invalid problem with proc-pointer assignment to an internal proc:

  implicit none
  procedure(real), pointer :: p
  p => scale
  print *,p(1.0,2)
end


/tmp/cc4EkFwV.o: In function `MAIN__':
test.f90:(.text+0xf): undefined reference to `_gfortran_specific__scale_4'
Comment 9 janus 2012-07-29 19:04:25 UTC
The following patch adds diagnostics to reject the invalid test case in comment 8:


Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 189929)
+++ gcc/fortran/expr.c	(working copy)
@@ -3444,6 +3444,13 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_ex
 			      "at %L", rvalue->symtree->name, &rvalue->where)
 			      == FAILURE)
 	    return FAILURE;
+	  if (attr.intrinsic && gfc_intrinsic_actual_ok (rvalue->symtree->name,
+							 attr.subroutine) == 0)
+	    {
+	      gfc_error ("Intrinsic '%s' at %L is invalid in procedure pointer "
+			 "assignment", rvalue->symtree->name, &rvalue->where);
+	      return FAILURE;
+	    }
 	}
       /* Check for F08:C730.  */
       if (attr.elemental && !attr.intrinsic)
Comment 10 janus 2012-07-29 20:15:52 UTC
(In reply to comment #9)
> The following patch adds diagnostics to reject the invalid test case in comment
> 8:

... and regtests cleanly.
Comment 11 janus 2012-07-30 19:55:45 UTC
Author: janus
Date: Mon Jul 30 19:55:41 2012
New Revision: 189985

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=189985
Log:
2012-07-30  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/51081
	* gfortran.h (gfc_resolve_intrinsic): Add prototype.
	* expr.c (gfc_check_pointer_assign): Set INTRINSIC attribute if needed.
	Check for invalid intrinsics.
	* primary.c (gfc_match_rvalue): Check for intrinsics came too early.
	Set procedure flavor if appropriate.
	* resolve.c (resolve_intrinsic): Renamed to gfc_resolve_intrinsic.
	(resolve_procedure_interface,resolve_procedure_expression,
	resolve_function,resolve_fl_derived0,resolve_symbol): Ditto.

2012-07-30  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/51081
	* gfortran.dg/proc_ptr_37.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_37.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/primary.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
Comment 12 janus 2012-07-30 19:59:51 UTC
r189985 fixes the test cases in comment 1 and 8, so that we can close this PR.