Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Annoying warning #8753

goetti
Beginner
3,525 Views

Since I use the 2013 Fortran compiler I get an annoying warning:

warning #8753: A CHARACTER component of an interoperable derived type must have length 1.

It is caused by following type which is an equivalent to a simple C data structure of a DLL:

type, bind(C) :: MDSLConfigA
    character(MDSL_APPNAME_LEN, C_CHAR) :: szAppName    
    character(MDSL_MAXPATH_LEN, C_CHAR) :: szLocalPath  
    character(MDSL_MAXPATH_LEN, C_CHAR) :: szGlobalPath 
    character(MDSL_MAXPATH_LEN, C_CHAR) :: szHelpFile   
    integer(C_INT)                      :: iLangID      
end type MDSLConfigA
typedef struct MDSLConfigA_ {
    char    szAppName[MDSL_APPNAME_LEN];
    char    szLocalPath[_MAX_PATH];     
    char    szGlobalPath[_MAX_PATH];    
    char    szHelpFile[_MAX_PATH];      
    int     iLangID;                    
} MDSLConfigA;                         

Is there a way to disable the warning or to avoid it?

Thanks in advance for all comments.

 

0 Kudos
1 Solution
Steven_L_Intel1
Employee
3,525 Views

/diag-disable:8753

I had not noticed that we were talking about a derived type. The bit about sequence association and the exception I mentioned is related to actual and dummy argument correspondence only.

I don't see the ambiguity here, 15.34 and 15.3.5 are saying that a derived type component is interoperable if a variable with those characteristics is interoperable, and 15.3.2 says:

If the type is character, the length type parameter is interoperable if and only if its value is one. 

View solution in original post

0 Kudos
18 Replies
IanH
Honored Contributor III
3,525 Views

The formally equivalent type uses character array components of length one and size of the C array, rather than character scalars with length of the C array.

type, bind(C) :: MDSLConfigA
    character(KIND=C_CHAR) :: szAppName(MDSL_APPNAME_LEN)
    character(KIND=C_CHAR) :: szLocalPath(MDSL_MAXPATH_LEN)
    character(KIND=C_CHAR) :: szGlobalPath(MDSL_MAXPATH_LEN)
    character(KIND=C_CHAR) :: szHelpFile(MDSL_MAXPATH_LEN)
    integer(C_INT)         :: iLangID      
end type MDSLConfigA

 

0 Kudos
Steven_L_Intel1
Employee
3,525 Views

Note also that with the correct interface, as Ian shows, you can still pass character values of the desired length. This is an exception carved out in the language.

The warning is telling you that you are violating a rule of the standard for interoperable types.

0 Kudos
JVanB
Valued Contributor II
3,525 Views

I used to think that the quoted warning was correct, but now I'm not so sure.

Section 15.3.4 says:

A Fortran derived type is interoperable with a C struct type if and only if the Fortran type has the BIND
attribute (4.5.2), the Fortran derived type and the C struct type have the same number of components, and the
components of the Fortran derived type would interoperate with corresponding components of the C struct type
as described in 15.3.5 and 15.3.6 if the components were variables. A component of a Fortran derived type and
a component of a C struct type correspond if they are declared in the same relative position in their respective
type definitions.

So in 15.3.5 we see:

A named scalar Fortran variable is interoperable if and only if its type and type parameters are interoperable, it
is not a coarray, it has neither the ALLOCATABLE nor the POINTER attribute, and if it is of type character
its length is not assumed or declared by an expression that is not a constant expression.

So it seems to me that scalar character variables of nonunit length should be acceptable in this context. Am I missing something?

0 Kudos
mecej4
Honored Contributor III
3,525 Views

It is not clear whether, because the 2013 compiler was used,  F2003 rules were in effect. In F2008, Note 15.18 says this:

Fortran's rules of sequence association (12.5.2.11) permit a character scalar actual argument to correspond
to a dummy argument array. This makes it possible to argument associate a Fortran character string with
a C string.

but that is in the context of associating formal and actual arguments, and R.O. provided the relevant quote from 15.3.5. The standard gives example code for calling from Fortran a C routine that copies a character array to another.

0 Kudos
andrew_4619
Honored Contributor III
3,525 Views

To clarify/add to the last post, you would still get that warning with that latest compiler (15.0.1.148) and /stand:f08

0 Kudos
IanH
Honored Contributor III
3,525 Views

Repeat Offender wrote:
...

So in 15.3.5 we see:

A named scalar Fortran variable is interoperable if and only if its type and type parameters are interoperable, it
is not a coarray, it has neither the ALLOCATABLE nor the POINTER attribute, and if it is of type character
its length is not assumed or declared by an expression that is not a constant expression.

So it seems to me that scalar character variables of nonunit length should be acceptable in this context. Am I missing something?

15.3.2p1 - 'If the type is character, the length type parameter is interoperable if and only if its value is one."  The bit you've quoted above then (I think) specifies that the compiler has to be able to see in the source of the procedure interface that the value of the length parameter will be one.

(Something about that last bit from 15.3.5 reads a bit funny - sometimes I wish they used parenthesis to disambiguate the precedence of operator words like "not" in written English like we use in written Fortran source...  could it be read "A named scalar Fortran variable is interoperable if and only if... its length is ... declared by an expression that is not a constant expression"???  Should there not be an additional "not" before that "declared", or not?  Perhaps that would only be required if there was a comma after assumed.  I hate lists of requirements in text because of this sort of stuff.)

Addressing other posts - the sequence association "trick" where a KIND=C_CHAR character scalar actual can be associated with an array dummy is only applicable if the argument is of type character.  In terms of formal behaviour that trick doesn't apply to interoperability of components of a derived type (which is what the warning is about) or argument association of that derived type (e.g. - the OP (perhaps) isn't passing just a character scalar - they are (likely) passing the entire object of derived type - otherwise why bother declaring the type BIND(C)).

0 Kudos
mecej4
Honored Contributor III
3,525 Views

There are many places in that chapter of the standard which raise doubts, but it is too tiresome to chase the answers down. Here are a couple of examples.

In the quote that Ian provided, we have "named Fortran scalar variable", which prompts the question, "what are unnamed Fortran scalar variables?" Or did they want to exclude scalar expressions?

Note 15.2 says, "The value of NEW_LINE(C_NEW_LINE) is C_NEW_LINE (13.7.121)." What do you make of that? Do parentheses demarcate explanatory text, or is there an intrinsic function called NEW_LINE?

0 Kudos
goetti
Beginner
3,525 Views


Thank you for your comments.

The suggestion from IanH helps to get rid of the annoying waring, but then the following assignment does not work any more:

      if( present(strName) ) then
        strName  = ModelInfo % szAppName
        call StripCNullChars( strName )
      end if

error #6366: The shapes of the array expressions do not conform.   [STRNAME]

In other words it is necessary to copy the string byte by byte. Is this how C inter-op should work in Fortran or have I missed something? Not a problem at all but not beautiful.

I would now like to know whether my first  approach was correct or whether it can lead to problems.

0 Kudos
goetti
Beginner
3,525 Views

Steve Lionel (Intel) wrote:

Note also that with the correct interface, as Ian shows, you can still pass character values of the desired length. This is an exception carved out in the language.

The warning is telling you that you are violating a rule of the standard for interoperable types.

When I read Steve's comment, I suppose my first approach was correct.

Then I just need to switch OFF the warning #8753. In C++ it works fine using local #pragma warning( disable: xxx ) statements in the source file. Any waring can be customized there. Is something similar available for Fortran?

0 Kudos
Steven_L_Intel1
Employee
3,526 Views

/diag-disable:8753

I had not noticed that we were talking about a derived type. The bit about sequence association and the exception I mentioned is related to actual and dummy argument correspondence only.

I don't see the ambiguity here, 15.34 and 15.3.5 are saying that a derived type component is interoperable if a variable with those characteristics is interoperable, and 15.3.2 says:

If the type is character, the length type parameter is interoperable if and only if its value is one. 

0 Kudos
goetti
Beginner
3,525 Views

Steve Lionel (Intel) wrote:

/diag-disable:8753

Thanks Steve, this was my first approach. I've added it to to compiler options. It does not work.

/nologo /debug:full /MP /O2 /Oy- /heap-arrays0 /fpp /free /noaltparam /Qdiag-disable:8753 /real_size:64 /assume:byterecl /fpe:0 /fpconstant /iface:mixed_str_len_arg /module:"Release\\" /object:"Release\\" /Fd"Release\vc120.pdb" /check:none /libs:dll /threads /c

 

0 Kudos
goetti
Beginner
3,525 Views

Sorry, I was too silly configure it correctly. I've applied it in wrong configuration (Release instead of debug).

It works well!

0 Kudos
FortranFan
Honored Contributor III
3,525 Views

Steve Lionel (Intel) wrote:

/diag-disable:8753

..

Steve,

What does /diag-diable:8753 do?  It simply suppresses the message, right?  If the code is non-conforming, then that issue remains, correct?

Now in the case of derived-type components, as you explain from the standard, "If the type is character, the length type parameter is interoperable if and only if its value is one."  If you look back at the original post, for character components in the derived type, the length parameter value is not one.  Now if a user takes such code and applies /diag-disable:8753, the warning will get suppressed and presumably the code will still work ok and the user will be happy.  But is that based on an Intel Fortran extension?  And is there any guarantee the user can take the code and get it to work with another Fortran 2003 compliant compiler?  

0 Kudos
mecej4
Honored Contributor III
3,525 Views

Disabling a warning message does just that. The generated code is the same whether the warning message is issued or not. Other compilers have similar options to control the number of warning messages issued.

0 Kudos
FortranFan
Honored Contributor III
3,525 Views

Well, let us again look at the key line from the standard for derived components, "If the type is character, the length type parameter is interoperable if and only if its value is one".  So if the length is not one, then the type should be not interoperable; note this is the situation shown in the original post.  But now, what does interoperable (or not) mean from a coder perspective?  It appears the coders find that the "stuff" works and there are only warnings, so why should anyone bother if it is really interoperable or not, and why not simply suppress the damn warning?

But I think it will be useful if everyone undertsood clearly the ramifications, if any, before going about disabling the warnings.

0 Kudos
IanH
Honored Contributor III
3,525 Views

FortranFan wrote:

Well, let us again look at the key line from the standard for derived components, "If the type is character, the length type parameter is interoperable if and only if its value is one".  So if the length is not one, then the type should be not interoperable; note this is the situation shown in the original post.  But now, what does interoperable (or not) mean from a coder perspective?  It appears the coders find that the "stuff" works and there are only warnings, so why should anyone bother if it is really interoperable or not, and why not simply suppress the damn warning?

But I think it will be useful if everyone undertsood clearly the ramifications, if any, before going about disabling the warnings.

You move into processor specific territory. 

It is not inconceivable that a Fortran processor might always want to have a descriptor for a character variable that stores the length of the variable, similar to how processors have descriptors for certain varieties of arrays.  When you are dealing with objects of derived type, a reasonable (perhaps only) place to store that descriptor is in the derived type object with the character data (perhaps a length leading representation - like strings in VB).  But if the processor does that, then you are going to have a mismatch between the data layout of the Fortran derived type and that of the supposedly corresponding C structure.

The same aspect arises when passing character scalars as arguments.

If the length is always going to be one, then there's no need to store the length and no need to resolve where and how that length will be stored.  The Fortran processor will still need to special case the storage layout of the character component in the BIND(C) derived type to avoid storing the length, but special casing for always length one character variables is a reasonable compromise anyway.

In #9 goetti shows a code snippet where a variable is defined using assignment of the value of the (currently non-unity length) character component and a procedure call to accommodate the null terminated C string convention.  Why not just replace that statement pair with a single reference to a procedure that does the appropriate array to scalar and C null terminated to Fortran trailing blank convention?  Then you can have a conforming BIND(C) derived type, portable code and no warning.

0 Kudos
FortranFan
Honored Contributor III
3,525 Views

IanH wrote:

..

You move into processor specific territory. 

..

That is why I asked in Quote #14, "is there any guarantee the user can take the code and get it to work with another Fortran 2003 compliant compiler?"

IanH wrote:

..

In #9 goetti shows a code snippet where a variable is defined using assignment of the value of the (currently non-unity length) character component and a procedure call to accommodate the null terminated C string convention.  Why not just replace that statement pair with a single reference to a procedure that does the appropriate array to scalar and C null terminated to Fortran trailing blank convention?  Then you can have a conforming BIND(C) derived type, portable code and no warning.

Aha! "Why not just replace.. with a single reference to a procedure .. Then you can have a conforming BIND(C) derived type, portable code and no warning."  - if the user can disable the first warning then the second issue would never arise, hence the question as to whether coders should simply go about disabling such warnings.

0 Kudos
IanH
Honored Contributor III
3,525 Views

Well, bar circumstances that I am inherently assuming don't apply, I would rewrite to conforming code and not disable the warning.  I'd expect (without having access to any detail) that the upfront cost of the rewrite is exceeded by the longer term benefits associated with conforming code (e.g. - the need to special case disable a particular warning represents a long term complexity disbenefit, before you even get to questions of portability).  But that tradeoff is a bit of a judgement call, and it is affected by the details of the situation.

I assumed you were asking leading questions - elaborate if not.

0 Kudos
Reply