Dear Tomas,

Thank you very much for your feedback. This was really helpful and helped me to 
find a solution. Even if it is not entirely satisfactory to me (in the sense 
that I now create new extra pointers which will take unnecessary space in 
memory), at least the LTO errors are not displayed anymore with Gfortran 8.3.0. 
Hopefully the CRAN team will find it sufficient to allow me to put my package 
back on the CRAN.

I explain below what I did in case someone else faces the same problem.

First originally, I could not display these LTO errors on my system (Debian 10 
Buster, with Gfortran 8.3.0). I thus modified the file /etc/R/Makeconf by 
adding -flto after every -fpic I could find.

Second, I was confused by the warning message below:
myzhpevx.cpp:22:16: warning: type of ‘zhpevx_’ does not match original 
declaration [-Wlto-type-mismatch]
           void F77_NAME(zhpevx)(char *jobz, char *range, char *uplo,
Indeed, I thought that the problem was with the type of the function itself, 
not with the type of one of its arguments. Following your approach of creating 
a minimalist code (and playing with the arguments one by one), I convinced 
myself otherwise.

My new code is pasted below for convenience. I used this instruction:

    double _Complex *Cap;
    memcpy(&ap, &Cap, sizeof(ap));

and then in F77_NAME(zhpevx) I replaced
Rcomplex *ap
with
__complex__ double *Cap
and of course, I used Cap instead of ap in F77_CALL(zhpevx).

This trick removes the LTO warning (at the expense of three extra pointers; I 
had to do it for the three complex pointers ap, z and work).

Thank you once again for your precious help.

Kind regards,
Pierre L.

PS: I CC Professor B. Ripley since he was the one that originally contacted me 
about this problem, and in case this might trigger the need for a modification 
of something in R core or in its documentation (though probably this is just 
the result of my limited knowledge in Fortran and/or C).


#define USE_FC_LEN_T
#include <R.h>
#include "Rmath.h"


#ifdef FC_LEN_T

extern "C" {

  void zhpevxC(char **jobz, char **range, char **uplo, int *n, Rcomplex *ap,
      double *vl, double *vu, int *il, int *iu, double *abstol, int *m,
      double *w, Rcomplex *z, int *ldz, Rcomplex *work, double *rwork,
      int *iwork, int *ifail, int *info) {


    char cjobz[2];
    strncpy(cjobz, jobz[0], 1);
    cjobz[1] = '\0';
    char crange[2];
    strncpy(crange, range[0], 1);
    crange[1] = '\0';
    char cuplo[2];
    strncpy(cuplo, uplo[0], 1);
    cuplo[1] = '\0';

    double _Complex *Cap;
    memcpy(&ap, &Cap, sizeof(ap));
    double _Complex *Cz;
    memcpy(&z, &Cz, sizeof(z));
    double _Complex *Cwork;
    memcpy(&work, &Cwork, sizeof(work));


    void F77_NAME(zhpevx)(const char *jobz, const char *range, const char *uplo,
 const int *n, __complex__ double *Cap, const double *vl,
 const double *vu, const int *il, const int *iu,
 const double *abstol, int *m, double *w,
 __complex__ double *Cz, const int *ldz, __complex__ double *Cwork, double 
*rwork,
 int *iwork, int *ifail, int *info,
 FC_LEN_T jobz_len,  FC_LEN_T range_len,  FC_LEN_T uplo_len);



    F77_CALL(zhpevx)(cjobz, crange, cuplo, &n[0], Cap, &vl[0], &vu[0], &il[0], 
&iu[0], &abstol[0], &m[0],
    w, Cz, &ldz[0], Cwork, rwork, iwork, ifail, &info[0], strlen(cjobz), 
strlen(crange), strlen(cuplo));


    delete[] Cap;
    delete[] Cz;
    delete[] Cwork;

  }

}
#else
extern "C" {

  void zhpevxC(char **jobz, char **range, char **uplo, int *n, Rcomplex *ap,
      double *vl, double *vu, int *il, int *iu, double *abstol, int *m,
      double *w, Rcomplex *z, int *ldz, Rcomplex *work, double *rwork,
      int *iwork, int *ifail, int *info) {

    extern void F77_NAME(zhpevx)(const char *jobz, const char *range, const 
char *uplo,
const int *n, __complex__ double *Cap, const double *vl,
const double *vu, const int *il, const int *iu,
const double *abstol, int *m, double *w,
__complex__ double *Cz, const int *ldz, __complex__ double *Cwork, double 
*rwork,
int *iwork, int *ifail, int *info);

    const char *JOBZ = jobz[0];
    const char *RANGE = range[0];
    const char *UPLO = uplo[0];

    double _Complex *Cap;
    memcpy(&ap, &Cap, sizeof(ap));
    double _Complex *Cz;
    memcpy(&z, &Cz, sizeof(z));
    double _Complex *Cwork;
    memcpy(&work, &Cwork, sizeof(work));

    F77_CALL(zhpevx)(JOBZ, RANGE, UPLO, &n[0], Cap, &vl[0], &vu[0], &il[0], 
&iu[0], &abstol[0], &m[0],
    w, Cz, &ldz[0], Cwork, rwork, iwork, ifail, &info[0]);

    delete[] JOBZ;
    delete[] RANGE;
    delete[] UPLO;

    delete[] Cap;
    delete[] Cz;
    delete[] Cwork;
  }

}
#endif


________________________________
From: Tomas Kalibera <tomas.kalib...@gmail.com>
Sent: Tuesday, 15 December 2020 23:01
To: Pierre Lafaye de Micheaux <laf...@unsw.edu.au>
Cc: r-package-devel@r-project.org <r-package-devel@r-project.org>
Subject: Re: [R-pkg-devel] warning: type of ‘zhpevx_’ does not match original 
declaration [-Wlto-type-mismatch]

Dear Pierre,

your code checks fine on my Ubuntu 20.04 (gcc/gfortran 9.3), but I can 
reproduce what you are seeing on Debian 10 with gcc 8.3.

There seem to be two problems.

The first one is that the hidden character length arguments are signed, they 
are of type "long int" (not "size_t"). This is compiler specific and can (and 
does) change between Fortran compiler versions and I think you can just ignore 
it. R assumes the type is "size_t", which happens to be correct for newer 
compilers. The signedness mismatch in this case is benign. FC_LEN_T is defined 
in R, so if anywhere, this would have to be fixed in R, but we cannot 
realistically know what the type is for each compiler.

The second problem is that gcc/LTO is complaining about incompatibility between 
Rcomplex and "COMPLEX*16" types. This was rather tedious to find, I had to 
minimize the example for that a bit more (remove the Fortran code, just left 
the subroutine taking the same args, and then removing the args one by one - 
this is what I meant by minimizing the example). I don't know why the mismatch 
is reported. Gcc 9.3 is happy.

I would recommend to use a newer compiler, at least for these checks. The 
warnings have improved (become more informative), you can use 
-fc-prototypes-external to see what the types should be exactly for your 
compiler, and perhaps some of the warnings were false positives and have been 
fixed since.

If you want to stick to the FC_LEN_T and similar macros, I would recommend to 
check how R does it so that the code compiles also when the extra hidden length 
arguments are not used by the compiler. Still, a portable way to solve these 
issues would be via iso_c_binding, with FC_LEN_T we are relying on 
undocumented/not-standardized behavior of the compiler.

Best,
Tomas





On 12/15/20 7:56 AM, Pierre Lafaye de Micheaux wrote:
Dear Tomas,

Apologies for the very long delay.

I was able to create a minimal version of the package (attached) that gives the 
same exact warnings:

myzhpevx.cpp:22:16: warning: type of ‘zhpevx_’ does not match original 
declaration [-Wlto-type-mismatch]
           void F77_NAME(zhpevx)(char *jobz, char *range, char *uplo,
                ^
zhpevx.f:232:14: note: type mismatch in parameter 20
       SUBROUTINE zhpevx(JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU,
              ^
zhpevx.f:232:14: note: type ‘long int’ should match type ‘size_t’
zhpevx.f:232:14: note: ‘zhpevx’ was previously declared here
zhpevx.f:232:14: note: code may be misoptimized unless -fno-strict-aliasing is 
used

I am under the impression that I am following quite closely what is written 
here: 
https://cran.csiro.au/doc/manuals/r-patched/R-exts.html#Fortran-character-strings

I tried many different things but I always end up with the same main warning 
(i.e., type of ‘zhpevx_’ does not match original declaration ).

My version of fortran: GNU Fortran (Debian 8.3.0-6) 8.3.0 under Debian 10.

Thank you very much for any further help you could provide so that I could have 
my package back to the CRAN.

Kind regards,
Pierre L.


________________________________
From: Tomas Kalibera <tomas.kalib...@gmail.com><mailto:tomas.kalib...@gmail.com>
Sent: Tuesday, 7 July 2020 15:43
To: Pierre Lafaye de Micheaux <laf...@unsw.edu.au><mailto:laf...@unsw.edu.au>
Cc: r-package-devel@r-project.org<mailto:r-package-devel@r-project.org> 
<r-package-devel@r-project.org><mailto:r-package-devel@r-project.org>
Subject: Re: [R-pkg-devel] warning: type of ‘zhpevx_’ does not match original 
declaration [-Wlto-type-mismatch]

My recommendation would be to try to minimize the example (package) as much as 
possible so that it still has the problem, and then try to investigate why 
exactly/where is the type mismatch. This is what helped me debug similar issues 
- sometimes it was hard to tell from the Fortran warnings where exactly the 
mismatched declarations were and why they were mismatched.

This process of minimization can already reveal the true source of the problem, 
and if not, others may try to debug for you using the minimal example. A useful 
tool is the Fortran option -fc-prototypes-external (see WRE for more details) 
and I've also used dumps of the compiler tree before (-fdump-tree-all, more in 
GCC documentation).

Best
Tomas

On 7/7/20 5:00 AM, Pierre Lafaye de Micheaux wrote:

My file myzhpevx.cpp starts with:

<quote>
#define USE_FC_LEN_T
#include <R.h>
#include "Rmath.h"

#ifdef FC_LEN_T
extern "C" {

  void zhpevxC(char **jobz, char **range, char **uplo, int *n, Rcomplex *ap,
     double *vl, double *vu, int *il, int *iu, double *abstol, int *m,
     double *w, Rcomplex *z, int *ldz, Rcomplex *work, double *rwork,
     int *iwork, int *ifail, int *info) {

          void F77_NAME(zhpevx)(char *jobz, char *range, char *uplo,
      const int *n, Rcomplex *ap, const double *vl,
      const double *vu, const int *il, const int *iu,
      const double *abstol, int *m, double *w,
      Rcomplex *z, const int *ldz, Rcomplex *work, double *rwork,
      int *iwork, int *ifail, int *info,
      FC_LEN_T jobz_len,  FC_LEN_T range_len,  FC_LEN_T uplo_len);
</quote>

So if I understand correctly what you are saying, you suggest that FC_LEN_T was 
not correctly defined by the CRAN team?

Should I just write something like (adding the middle instruction below to my 
existing code above)?:

<quote>
#ifdef FC_LEN_T
typedef long long int FC_LEN_T;
extern "C" {
</quote>

Thank you
Pierre
________________________________
From: William Dunlap <wdun...@tibco.com><mailto:wdun...@tibco.com>
Sent: Tuesday, 7 July 2020 11:46
To: Pierre Lafaye de Micheaux <laf...@unsw.edu.au><mailto:laf...@unsw.edu.au>
Cc: Ivan Krylov <krylov.r...@gmail.com><mailto:krylov.r...@gmail.com>; 
r-package-devel@r-project.org<mailto:r-package-devel@r-project.org> 
<r-package-devel@r-project.org><mailto:r-package-devel@r-project.org>
Subject: Re: [R-pkg-devel] warning: type of �zhpevx_� does not match original 
declaration [-Wlto-type-mismatch]

With gcc 8.3.0, gfortran 8.3.0, and ld 2.33.1 from the mingw64 part of
rtools40 on Windows, if I misdefine the typedef FC_LEN_T and use the
-flto flag I get the sort of error messages that you report.

c:\tmp\fortran>cat main.c
#include <string.h>
#include <stdio.h>

#ifdef USE_INT
typedef int FC_LEN_T;
#endif
#ifdef USE_LONG
typedef long int FC_LEN_T;
#endif
#ifdef USE_LONG_LONG
typedef long long int FC_LEN_T;
#endif

extern void sub_(char* word, double *ret, FC_LEN_T word_len);

int main(int argc, char* argv[])
{
    if (argc == 2) {
        double ret = 3. ;
        FC_LEN_T word_len = strlen(argv[1]);
        sub_(argv[1], &ret, word_len);
        printf("sizeof(FC_LEN_T)=%d, ret=%g\n", (int)(sizeof(FC_LEN_T)), ret);
        return 0;
    } else {
        return -1;
    }
}

c:\tmp\fortran>gcc  -flto -DUSE_INT main.c sub.f -lgfortran
main.c:14:13: warning: type of 'sub_' does not match original
declaration [-Wlto-type-mismatch]
 extern void sub_(char* word, double *ret, FC_LEN_T word_len);
             ^
sub.f:1:1: note: type mismatch in parameter 3
       subroutine sub(word, ret)
 ^
sub.f:1:1: note: type 'long long int' should match type 'FC_LEN_T'
sub.f:1:1: note: 'sub' was previously declared here
sub.f:1:1: note: code may be misoptimized unless -fno-strict-aliasing is used

c:\tmp\fortran>gcc  -flto -DUSE_LONG main.c sub.f -lgfortran
main.c:14:13: warning: type of 'sub_' does not match original
declaration [-Wlto-type-mismatch]
 extern void sub_(char* word, double *ret, FC_LEN_T word_len);
             ^
sub.f:1:1: note: type mismatch in parameter 3
       subroutine sub(word, ret)
 ^
sub.f:1:1: note: type 'long long int' should match type 'FC_LEN_T'
sub.f:1:1: note: 'sub' was previously declared here
sub.f:1:1: note: code may be misoptimized unless -fno-strict-aliasing is used

c:\tmp\fortran>gcc  -flto -DUSE_LONG_LONG main.c sub.f -lgfortran
<no warnings or notes>

Bill Dunlap
TIBCO Software
wdunlap tibco.com

On Mon, Jul 6, 2020 at 4:39 PM Pierre Lafaye de Micheaux
<laf...@unsw.edu.au><mailto:laf...@unsw.edu.au> wrote:


Hello Bill,

Thank you for your insight.

First, my impression, is that the problem comes from how I declare the type of 
the function itself (and not its parameters), since the first (and only warning 
they seen on the CRAN) message is:

<quote>
myzhpevx.cpp:13:16: warning: type of �zhpevx_� does not match original 
declaration [-Wlto-type-mismatch]
           void F77_NAME(zhpevx)(char *jobz, char *range, char *uplo,
</quote>

What I did is the following:

<quote>
void F77_NAME(zhpevx)(char *jobz, char *range, char *uplo,
      const int *n, Rcomplex *ap, const double *vl,
      const double *vu, const int *il, const int *iu,
      const double *abstol, int *m, double *w,
      Rcomplex *z, const int *ldz, Rcomplex *work, double *rwork,
      int *iwork, int *ifail, int *info,
      FC_LEN_T jobz_len,  FC_LEN_T range_len,  FC_LEN_T uplo_len);

 char cjobz[2];
 strncpy(cjobz, jobz[0], 1);
 cjobz[1] = '\0';
 char crange[2];
 strncpy(crange, range[0], 1);
 crange[1] = '\0';
 char cuplo[2];
 strncpy(cuplo, uplo[0], 1);
 cuplo[1] = '\0';

 F77_CALL(zhpevx)(cjobz, crange, cuplo, &n[0], ap, &vl[0], &vu[0], &il[0], 
&iu[0], &abstol[0], &m[0],
  w, z, &ldz[0], work, rwork, iwork, ifail, &info[0], strlen(cjobz), 
strlen(crange), strlen(cuplo));
</quote>

Do you see anything wrong with the above?

Thank you

Best
Pierre

________________________________
From: William Dunlap <wdun...@tibco.com><mailto:wdun...@tibco.com>
Sent: Tuesday, 7 July 2020 08:36
To: Pierre Lafaye de Micheaux <laf...@unsw.edu.au><mailto:laf...@unsw.edu.au>
Cc: Ivan Krylov <krylov.r...@gmail.com><mailto:krylov.r...@gmail.com>; 
r-package-devel@r-project.org<mailto:r-package-devel@r-project.org> 
<r-package-devel@r-project.org><mailto:r-package-devel@r-project.org>
Subject: Re: [R-pkg-devel] warning: type of �zhpevx_� does not match original 
declaration [-Wlto-type-mismatch]

Have you tried what is recommended in
https://gcc.gnu.org/onlinedocs/gfortran/Argument-passing-conventions.html
?

<quote>
For arguments of CHARACTER type, the character length is passed as a
hidden argument at the end of the argument list. For deferred-length
strings, the value is passed by reference, otherwise by value. The
character length has the C type size_t (or INTEGER(kind=C_SIZE_T) in
Fortran). Note that this is different to older versions of the GNU
Fortran compiler, where the type of the hidden character length
argument was a C int. In order to retain compatibility with older
versions, one can e.g. for the following Fortran procedure

subroutine fstrlen (s, a)
   character(len=*) :: s
   integer :: a
   print*, len(s)
end subroutine fstrlen

define the corresponding C prototype as follows:

#if __GNUC__ > 7
typedef size_t fortran_charlen_t;
#else
typedef int fortran_charlen_t;
#endif

void fstrlen_ (char*, int*, fortran_charlen_t);

In order to avoid such compiler-specific details, for new code it is
instead recommended to use the ISO_C_BINDING feature.

Note with C binding, CHARACTER(len=1) result variables are returned
according to the platform ABI and no hidden length argument is used
for dummy arguments; with VALUE, those variables are passed by value.
</quote>

Bill Dunlap
TIBCO Software
wdunlap tibco.com

Bill Dunlap
TIBCO Software
wdunlap tibco.com


On Mon, Jul 6, 2020 at 3:13 PM Pierre Lafaye de Micheaux
<laf...@unsw.edu.au><mailto:laf...@unsw.edu.au> wrote:


Dear Ivan,

Thank you very much for your response.

I do not have more information than the one I gave in my previous email. (And 
on top of that, the computer I was using with Debian SID, a recent version of 
gfortran and the last version of R-devel, just broke.)

My problem is that the CRAN team won't accept to publish my package until this 
WARNING problem is solved. And because I am unable to observe the warning on my 
side (I could not with the desktop that just broke, and I still can't with my 
current laptop with Debian 10), I have no clue on how to suppress this warning.

Thank you in advance for any other advice.

Best regards,
Pierre
________________________________
From: Ivan Krylov <krylov.r...@gmail.com><mailto:krylov.r...@gmail.com>
Sent: Tuesday, 7 July 2020 06:11
To: Pierre Lafaye de Micheaux <laf...@unsw.edu.au><mailto:laf...@unsw.edu.au>
Cc: r-package-devel@r-project.org<mailto:r-package-devel@r-project.org> 
<r-package-devel@r-project.org><mailto:r-package-devel@r-project.org>
Subject: Re: [R-pkg-devel] warning: type of �zhpevx_� does not match original 
declaration [-Wlto-type-mismatch]

On Fri, 3 Jul 2020 00:15:27 +0000
Pierre Lafaye de Micheaux <laf...@unsw.edu.au><mailto:laf...@unsw.edu.au> wrote:



Found the following significant warnings:
   myzhpevx.cpp:13:23: warning: type of _zhpevx__ does not match
original declaration [-Wlto-type-mismatch]


I managed to reproduce the warning on R-devel r78607 built with
--enable-lto using gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1):

myzhpevx.cpp:13:16: warning: type of �zhpevx_� does not match original 
declaration [-Wlto-type-mismatch]
           void F77_NAME(zhpevx)(char *jobz, char *range, char *uplo,
                ^
zhpevx.f:232:7: note: type mismatch in parameter 20
       SUBROUTINE zhpevx( JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU,
       ^
zhpevx.f:232:7: note: type �int� should match type �size_t�
/usr/lib/gcc/x86_64-linux-gnu/6/include/stddef.h:216:23: note: the incompatible 
type is defined here
 typedef __SIZE_TYPE__ size_t;
                       ^
zhpevx.f:232:7: note: �zhpevx� was previously declared here
       SUBROUTINE zhpevx( JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU,
       ^

Do you have access to the notes produced by the compiler in addition
to the warnings? Do they spell the same difference?

If yes, the warning is likely to be safe to ignore. m4/R.m4 notes that,
while gfortran < 8 uses int instead of size_t for hidden size arguments,
it doesn't make a practical difference.

--
Best regards,
Ivan

        [[alternative HTML version deleted]]

______________________________________________
R-package-devel@r-project.org<mailto:R-package-devel@r-project.org> mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


        [[alternative HTML version deleted]]





______________________________________________
R-package-devel@r-project.org<mailto:R-package-devel@r-project.org> mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel




        [[alternative HTML version deleted]]

______________________________________________
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel

Reply via email to