flang-compiler / f18

F18 is a front-end for Fortran intended to replace the existing front-end in the Flang compiler
229 stars 48 forks source link

Calls to specific intrinsics no longer convert arguments #724

Closed klausler closed 5 years ago

klausler commented 5 years ago
integer(2) :: j
real :: x
x = float(j)

no longer works, and elicits error: Actual argument for 'i=' has bad type or kind 'Integer(2)'. I think it's because the intrinsic table probing code no longer allows for type conversions on calls to specific intrinsic functions.

jeanPerier commented 5 years ago

Are type conversions in calls to specific intrinsic functions standard compliant or is it an extension ? Nag is also refusing the example code telling that the argument has the wrong type, all other compilers (gfortran, pgfortran, xlf, ifort) are silently accepting it. If the code is changed to have j be a real, then all compiler are raising an error but pgfortran that emits a warning about type conversions. Simply removing the error would contradict with #661 .

What should f18 do:

klausler commented 5 years ago

I am fine with having a silent conversion for all cases that don't reduce precision. Compilers should emit warnings only when there's a potential problem that needs attention.

jeanPerier commented 5 years ago

@sscalpone I add you to the discussion because you opened #661, so you may have an opinion. Problem:

I started a branch to convert argument as needed just to find out that it gave different result on edge cases compared with other compilers.... After investigating more, it turns out it is not only a warning/no warning issue. It seems there is at least two ways to handle the problem of specific intrinsic calls with "non-standard" argument types (bad kind), and different compilers make different choices:

Making a type conversion vs selecting the generic can give significantly different numerical results, even in cases where the inserted conversion would not be narrowing... Compilers may not even attribute the same kind to the intrinsic call expressions depending on the choice they make. Attached is a table with numerical discrepancies I could observe on a subset of the specific intrinsic. A few examples:

More in: NonStandardSpecificIntrinsicCalls.xlsx

Proposed solution:

Do you agree with the proposed solution ?

klausler commented 5 years ago

Where an "unrestricted specific intrinsic function" from Table 16.2 or 16.3 has the same name as the generic to which it maps, it would be confusing if it did not work like the generic does, so it should do so. (The generic DPROD is defined (16.9.64) as requiring default real arguments.)

Where an "unrestricted specific intrinsic function" from Table 16.2 does not have same name as the generic, I am okay with requiring strict typing: ALOG, ALOG10, AMOD, CABS, CCOS, CEXP, CLOG, CSQRT, DABS through DEXP, DINT through DNINT, DSIGN through DTANH, IABS, IDIM, IDNINT, & ISIGN.

However, for the cases of intrinsic functions that represent type conversions (these are the numeric "restricted specific intrinsic functions" of Table 16.3, as well as the legacy extensions for double complex), the purpose of the intrinsic is to produce its fixed result type. I don't see a problem allowing other argument types. Specifically, the entire purpose of FLOAT/SNGL is to convert to default REAL; the purpose of IDINT/IFIX is to convert to default INTEGER. It would seem weird to require a program to convert an argument to a type conversion function, especially when modern codes should just be using INT and REAL generic intrinsic functions instead.

(The variants of MAX and MIN in 16.3 are defined as a generic MAX or MIN followed by a conversion and that seems fine to me.)