User account creation filtered due to spam.

Bug 47359 - Recursive functions of intrinsic names generates invalid assembler
Summary: Recursive functions of intrinsic names generates invalid assembler
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2011-01-19 11:24 UTC by Roger Ferrer Ibanez
Modified: 2015-06-06 18:23 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.1.2, 4.2.1, 4.3.4, 4.4.0, 4.5.1, 4.6.0
Last reconfirmed: 2015-05-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roger Ferrer Ibanez 2011-01-19 11:24:20 UTC
I know this is sort of a contrived case but seems that gfortran is getting confused in this case leading to syntactically invalid assembler.

RECURSIVE FUNCTION MAX(A, B) RESULT(K)
  IF (B >= 0) THEN
         K = MAX(A+1, B-1)
  ELSE
     K = A
  END IF
END

$ gfortran -c test.f90 -save-temps
test.s:11: Error: junk at end of line, first unrecognized character is `('
test.s:12: Error: unrecognized symbol type ""
test.s:12: Error: junk at end of line, first unrecognized character is `('
test.s:13: Error: Unrecognized opcode: `__(intrinsic)__max:'
test.s:73: Error: expected comma after name `__' in .size directive
$ cat -n test.s 
  ...
    11		.globl __(intrinsic)__max
    12		.type	__(intrinsic)__max, @function
    13	__(intrinsic)__max:
  ...
    73		.size	__(intrinsic)__max,.-__(intrinsic)__max


My guess is that gfortran is picking the intrinsic 'max' function symbol instead of the one being currently defined (which is recursive and thus is eligible to be called in its same body, isn't it?)

I don't know how much conformant this is to Fortran standard but Intel Fortran and IBM XL Fortran did not complain and successfully generated an object file. 

If this is not valid Fortran, an error message is better than a cryptic assembler syntax error :)
Comment 1 Dominique d'Humieres 2011-01-19 20:44:27 UTC
> I know this is sort of a contrived case but seems that gfortran is getting
> confused in this case leading to syntactically invalid assembler.

I don't see the invalid assembler on x86_64-apple-darwin10 and powerpc-apple-darwin9 for trunk (4.6), 4.50, and 4.4.4. However gfortran is indeed confused by the code as shown by the following modification:

RECURSIVE FUNCTION MAX(A, B, i) RESULT(K)
  real i
  i = i + 1
  IF (B >= 0) THEN
         K = MAX(A+1, B-1, i)
  ELSE
     K = A
  END IF
END
RECURSIVE FUNCTION myMAX(A, B, i) RESULT(K)
  real i
  i = i + 1
  IF (B >= 0) THEN
         K = myMAX(A+1, B-1, i)
  ELSE
     K = A
  END IF
END
external max
a = 0
b = 0
i = max(3.2,0.2, a)
j = mymax(3.2,0.2, b)
print *, i, j, a, b
a = 0
b = 0
i = max(3.2,2.2, a)
j = mymax(3.2,2.2, b)
print *, i, j, a, b
end
[macbook] f90/bug% gfc pr47359_db_3.f90
[macbook] f90/bug% a.out
           4           4   1.0000000       2.0000000    
           4           6   1.0000000       4.0000000    

where I had to declare 'i' REAL in order to avoid a compilation error and clearly the external MAX is called, but only once apparently because the call to MAX in MAX is a call to the intrinsic. g95 gives

 4 4 2. 2.
 6 6 4. 4.
Comment 2 Dominique d'Humieres 2011-05-23 09:58:19 UTC
The test in comment #1 is still nt working at revision 174047.
Comment 3 Francois-Xavier Coudert 2015-05-04 15:21:31 UTC
Still fails. Somewhat reduced/reworked testcase:

program test
  external max
  print *, max(42, 1)
end

recursive function max(a, b) result(k)
  integer a, b, k
  if (b > 0) then
    k = max(a, b-1)
  else
    k = 0
  end if
end function

where you can see that generated code for function "max" does not call itself, as it should. The output of that program is "42", while it should be "0".

Providing an explicit interface for "max" is also not working:

program test
  interface
    recursive function max(a, b) result(k)
      integer a, b, k
    end function
  end interface
  print *, max(42, 1)
end

recursive function max(a, b) result(k)
  integer a, b, k
  if (b > 0) then
    k = max(a, b-1)
  else
    k = 0
  end if
end function
Comment 4 Thomas Koenig 2015-06-06 16:13:11 UTC
Author: tkoenig
Date: Sat Jun  6 16:12:39 2015
New Revision: 224190

URL: https://gcc.gnu.org/viewcvs?rev=224190&root=gcc&view=rev
Log:
2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>

	PR fortran/47359
	* arith.c (eval_intrinsic_op): Set warn flag for
	gfc_type_convert_binary if -Wconversion or -Wconversion-extra
	are set.
	(wprecision_real_real): New function.
	(wprecision_int_real): New function.
	(gfc_int2int): If -fno-range-check and -Wconversion are specified
	and it is a narrowing conversion, warn.
	(gfc_int2real): If there is a change in value for the conversion,
	warn.
	(gfc_int2complex):  Likewise.
	(gfc_real2int): If there is a fractional part to the real number,
	warn with -Wconversion, otherwise warn with -Wconversion-extra.
	(gfc_real2real): Emit warning if the constant was changed by
	conversion with either -Wconversion or -Wconversion-extra.  With
	-Wconversion-extra, warn if no warning was issued earlier.
	(gfc_real2complex):  Likewise.
	(gfc_complex2int): For -Wconversion or -Wconversion-extra, if
	there was an imaginary part, warn; otherwise, warn for change in
	value.  Warn with -Wconversion-extra if no other warning was
	issued.
	(gfc_complex2real): For -Wconversion or -Wconversion-extra, if
	there was an imaginary part, warn; otherwise, warn for change in
	value. Warn with -Wconversion-extra if no other warning was
	issued.
	(gfc_complex2complex):  For -Wconversion, warn if the value of
	either the real or the imaginary part was changed.  Warn for
	-Wconversion-extra if no prior warning was issued.
	* expr.c (gfc_check_assign):  Remove check for change in value.
	* primary.c (match_real_constant): For -Wconversion-extra, check
	against a number in which the last non-zero digit has been
	replaced with a zero.  If the number compares equal, warn.
	* intrinsic.c (gfc_convert_type_warn):  Do not warn about constant
	conversions.

2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>

	PR fortran/47359
	* gfortran.dg/array_constructor_type_17.f03: Adjust error message.
	* gfortran.dg/warn_conversion.f90: Add warning for change in value
	for assignment.
	* gfortran.dg/warn_conversion_3.f90: Add warnings.
	* gfortran.dg/warn_conversion_5.f90: New test.
	* gfortran.dg/warn_conversion_6.f90: New test.
	* gfortran.dg/warn_conversion_7.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/warn_conversion_5.f90
    trunk/gcc/testsuite/gfortran.dg/warn_conversion_6.f90
    trunk/gcc/testsuite/gfortran.dg/warn_conversion_7.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/arith.c
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/intrinsic.c
    trunk/gcc/fortran/primary.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/array_constructor_type_17.f03
    trunk/gcc/testsuite/gfortran.dg/warn_conversion.f90
    trunk/gcc/testsuite/gfortran.dg/warn_conversion_3.f90
Comment 5 Thomas Koenig 2015-06-06 16:16:35 UTC
Author: tkoenig
Date: Sat Jun  6 16:16:03 2015
New Revision: 224191

URL: https://gcc.gnu.org/viewcvs?rev=224191&root=gcc&view=rev
Log:
2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>

	PR fortran/47359
	* ChangeLog: Correct PR number in previous commit.


Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/testsuite/ChangeLog
Comment 6 Thomas Koenig 2015-06-06 18:23:12 UTC
(In reply to Thomas Koenig from comment #5)
> Author: tkoenig
> Date: Sat Jun  6 16:16:03 2015
> New Revision: 224191

Of course, this was a commit for PR 47659.

One day, I will get the PR numbers right... hopefully.