Paul, Ralph,

I had several issues in 2010 with with PGI pgcc being overly picky about type mismatches.  Attached are my e-mails from that time.  I was working on NetCDF and OpenMPI.  In the OpenMPI report (17 Aug 2010), I found problems in conditional expressions.  The last e-mail in the thread from PGI said they fixed the bugs in the 12.10 release.  But, that e-mail (14 Dec 2012) only cites TPRs 17185 and 17186, not my earlier TPR 17139.  I have not revisited these issues since then, so I don't know if that old bug is still around and is what is biting you.

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov



On 17 Jan 2014, at 8:56 AM, Ralph Castain wrote:
--- Begin Message ---
Customer information:

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

Product: 2183-WS
PIN: 507549

Problem description:

I am trying to track down the warnings that occur when compiling the UCAR NetCDF package with PGI compilers. I have found a case that gcc does not warn about, but pgcc does. If I understand the code and the C (1990) standard, I think pgcc is complaining too much.

You can reproduce the warnings by downloading the UCAR NetCDF source package, netcdf.tar.gz, from http://www.unidata.ucar.edu/software/netcdf/ . Assuming you download it to /usr/local/src, here are the commands that illustrate the warnings:

# cd /usr/local/src
# tar -xzf netcdf.tar.gz
# cd netcdf-4.1.1
# ./configure >/dev/null 2>&1
# cd ncgen
# pgcc -DHAVE_CONFIG_H -I. -I.. -I../fortran -I.. -I../libsrc - I../libsrc -g -O2 -tp amd64 -Msignextend -DNO_PGI_OFFSET -c -o genf77.o genf77.c
PGC-W-0095-Type cast required for this conversion (genf77.c: 498)
PGC-W-0095-Type cast required for this conversion (genf77.c: 511)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

To eliminate the warnings, I had to modify the two source lines to cast the result from static const char* f77varncid() as (char *):

    /* Use the specialized put_att_XX routines if possible*/
    switch (basetype->typ.typecode) {
    case NC_BYTE:
    case NC_SHORT:
    case NC_INT:
    case NC_FLOAT:
    case NC_DOUBLE:
        f77attrify(asym,code);
        codedump(code);
        bbClear(code);
bbprintf0(stmt,"stat = nf_put_att_%s(ncid, %s, %s, %s, %lu, %sval)\n",
                nfstype(basetype->typ.typecode),
                (asym->att.var == NULL?"NF_GLOBAL"
:(char *) f77varncid(asym- >att.var)), <--- here
                f77escapifyname(asym->name),
                nftype(basetype->typ.typecode),
                len,
                ncftype(basetype->typ.typecode));
        codedump(stmt);
        break;

    case NC_CHAR:
        len = bbLength(code);
        f77quotestring(code);
        bbprintf0(stmt,"stat = nf_put_att_text(ncid, %s, %s, %lu, ",
                (asym->att.var == NULL?"NF_GLOBAL"
:(char *)f77varncid(asym- >att.var)), <--- and here
                f77escapifyname(asym->name),
                (len==0?1:len));
        codedump(stmt);
        codedump(code);
        codeline(")");
        break;

Here is static const char* f77varncid():

/* Compute the name for a given var's id*/
/* Watch out: the result is a static*/
static const char*
f77varncid(Symbol* vsym)
{
    const char* tmp1;
    char* vartmp;
    tmp1 = f77name(vsym);
    vartmp = poolalloc(strlen(tmp1)+strlen("_id")+1);
    strcpy(vartmp,tmp1);
    strcat(vartmp,"_id");
    return vartmp;
}

There are other lines in genf77.c that use f77varncid() in a print statement, so the warnings do not occur every time f77varncid() provides a string for %s:

    if (nvars > 0) {
        f77skip();
        f77comment("variable ids");
        for(ivar = 0; ivar < nvars; ivar++) {
            Symbol* vsym = (Symbol*)listget(vardefs,ivar);
            bbprintf0(stmt,"integer %s;\n", f77varncid(vsym));
            codedump(stmt);
        }

The warnings occur in the only two instances where f77varncid() is used in a conditional expression. In both cases, the second operand is a literal string, e.g., "NF_GLOBAL". I would have thought that a (static const char*) and a string literal would be compatible types. I experimented with a (const char *) cast instead of a (char *) cast, but that does not work. I think it should.

I admit, I have an old copy of the C standard — from 1990. But, here's my interpretation of what it says about this:

• 6.1.4 String literals, says string literals are converted to an array of type char. If the program attempts to modify a string literal, the behavior is undefined. It does not say that the type has the const type qualifier (though, you would think it should).

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

This would seem to explain the warning message, since the string literal is (char *) and f77varncid() is (const char *). However, 6.3.15 goes on to say:

Furthermore, if both operands are pointers to ... differently qualified versions of a compatible type, the result has the composite type.

Which leads me to believe you are allowed to mix const and non-const versions of a compatible type.

Lastly:

• 6.5.3 Type qualifiers, says that the properties associated with qualified types are meaningful only for expressions that are lvalues.

Seems to make the issue moot, since it says const-ness only applies to lvalues.

So, I think both 6.3.15 and 6.5.3 imply that (char *) and (const char *) are compatible as the second and third operands in a conditional expression which is not an lvalue, which is the case in this code. As I mentioned above, gcc does not complain about this code. What do you think?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov


--- End Message ---
--- Begin Message ---
Larry,

    Thanks for the report.

    We recreated your behavior and logged it as TPR 17139.

regards,
dave


Larry Baker wrote:
Customer information:

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

Product: 2183-WS
PIN: 507549

Problem description:

I am trying to track down the warnings that occur when compiling the UCAR NetCDF package with PGI compilers. I have found a case that gcc does not warn about, but pgcc does. If I understand the code and the C (1990) standard, I think pgcc is complaining too much.

You can reproduce the warnings by downloading the UCAR NetCDF source package, netcdf.tar.gz, from http://www.unidata.ucar.edu/software/netcdf/. Assuming you download it to /usr/local/src, here are the commands that illustrate the warnings:

# cd /usr/local/src
# tar -xzf netcdf.tar.gz
# cd netcdf-4.1.1
# ./configure >/dev/null 2>&1
# cd ncgen
# pgcc -DHAVE_CONFIG_H -I. -I.. -I../fortran -I.. -I../libsrc -I../libsrc -g -O2 -tp amd64 -Msignextend -DNO_PGI_OFFSET -c -o genf77.o genf77.c
PGC-W-0095-Type cast required for this conversion (genf77.c: 498)
PGC-W-0095-Type cast required for this conversion (genf77.c: 511)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

To eliminate the warnings, I had to modify the two source lines to cast the result from static const char* f77varncid() as (char *):

    /* Use the specialized put_att_XX routines if possible*/
    switch (basetype->typ.typecode) {
    case NC_BYTE:
    case NC_SHORT:
    case NC_INT:
    case NC_FLOAT:
    case NC_DOUBLE:
        f77attrify(asym,code);
        codedump(code);
        bbClear(code);
bbprintf0(stmt,"stat = nf_put_att_%s(ncid, %s, %s, %s, %lu, %sval)\n",
                nfstype(basetype->typ.typecode),
                (asym->att.var == NULL?"NF_GLOBAL"
:(char *) f77varncid(asym->att.var)), <--- here
                f77escapifyname(asym->name),
                nftype(basetype->typ.typecode),
                len,
                ncftype(basetype->typ.typecode));
        codedump(stmt);
        break;

    case NC_CHAR:
        len = bbLength(code);
        f77quotestring(code);
        bbprintf0(stmt,"stat = nf_put_att_text(ncid, %s, %s, %lu, ",
                (asym->att.var == NULL?"NF_GLOBAL"
:(char *)f77varncid(asym->att.var)), <--- and here
                f77escapifyname(asym->name),
                (len==0?1:len));
        codedump(stmt);
        codedump(code);
        codeline(")");
        break;

Here is static const char* f77varncid():

/* Compute the name for a given var's id*/
/* Watch out: the result is a static*/
static const char*
f77varncid(Symbol* vsym)
{
    const char* tmp1;
    char* vartmp;
    tmp1 = f77name(vsym);
    vartmp = poolalloc(strlen(tmp1)+strlen("_id")+1);
    strcpy(vartmp,tmp1);
    strcat(vartmp,"_id");
    return vartmp;
}

There are other lines in genf77.c that use f77varncid() in a print statement, so the warnings do not occur every time f77varncid() provides a string for %s:

    if (nvars > 0) {
        f77skip();
        f77comment("variable ids");
        for(ivar = 0; ivar < nvars; ivar++) {
            Symbol* vsym = (Symbol*)listget(vardefs,ivar);
            bbprintf0(stmt,"integer %s;\n", f77varncid(vsym));
            codedump(stmt);
        }

The warnings occur in the only two instances where f77varncid() is used in a conditional expression. In both cases, the second operand is a literal string, e.g., "NF_GLOBAL". I would have thought that a (static const char*) and a string literal would be compatible types. I experimented with a (const char *) cast instead of a (char *) cast, but that does not work. I think it should.

I admit, I have an old copy of the C standard — from 1990. But, here's my interpretation of what it says about this:

• 6.1.4 String literals, says string literals are converted to an array of type char. If the program attempts to modify a string literal, the behavior is undefined. It does not say that the type has the const type qualifier (though, you would think it should).

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

This would seem to explain the warning message, since the string literal is (char *) and f77varncid() is (const char *). However, 6.3.15 goes on to say:

Furthermore, if both operands are pointers to ... differently qualified versions of a compatible type, the result has the composite type.

Which leads me to believe you are allowed to mix const and non-const versions of a compatible type.

Lastly:

• 6.5.3 Type qualifiers, says that the properties associated with qualified types are meaningful only for expressions that are lvalues.

Seems to make the issue moot, since it says const-ness only applies to lvalues.

So, I think both 6.3.15 and 6.5.3 imply that (char *) and (const char *) are compatible as the second and third operands in a conditional expression which is not an lvalue, which is the case in this code. As I mentioned above, gcc does not complain about this code. What do you think?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov



--
Dave Borer      Customer Service Manager, The Portland Group
email           dave.bo...@st.com
phone           (503)-431-7113


--- End Message ---
--- Begin Message ---
FYI.  The Intel compilers also do not complain.

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

On Jul 27, 2010, at 5:59 PM, PGI Technical Support wrote:

Larry,

   Thanks for the report.

   We recreated your behavior and logged it as TPR 17139.

regards,
dave


Larry Baker wrote:
Customer information:

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

Product: 2183-WS
PIN: 507549

Problem description:

I am trying to track down the warnings that occur when compiling the UCAR NetCDF package with PGI compilers. I have found a case that gcc does not warn about, but pgcc does. If I understand the code and the C (1990) standard, I think pgcc is complaining too much.

You can reproduce the warnings by downloading the UCAR NetCDF source package, netcdf.tar.gz, from http://www.unidata.ucar.edu/software/netcdf/ . Assuming you download it to /usr/local/src, here are the commands that illustrate the warnings:

# cd /usr/local/src
# tar -xzf netcdf.tar.gz
# cd netcdf-4.1.1
# ./configure >/dev/null 2>&1
# cd ncgen
# pgcc -DHAVE_CONFIG_H -I. -I.. -I../fortran -I.. -I../libsrc -I../libsrc -g -O2 -tp amd64 -Msignextend -DNO_PGI_OFFSET -c -o genf77.o genf77.c
PGC-W-0095-Type cast required for this conversion (genf77.c: 498)
PGC-W-0095-Type cast required for this conversion (genf77.c: 511)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

To eliminate the warnings, I had to modify the two source lines to cast the result from static const char* f77varncid() as (char *):

   /* Use the specialized put_att_XX routines if possible*/
   switch (basetype->typ.typecode) {
   case NC_BYTE:
   case NC_SHORT:
   case NC_INT:
   case NC_FLOAT:
   case NC_DOUBLE:
       f77attrify(asym,code);
       codedump(code);
       bbClear(code);
bbprintf0(stmt,"stat = nf_put_att_%s(ncid, %s, %s, %s, %lu, %sval)\n",
               nfstype(basetype->typ.typecode),
               (asym->att.var == NULL?"NF_GLOBAL"
:(char *) f77varncid(asym- >att.var)), <--- here
               f77escapifyname(asym->name),
               nftype(basetype->typ.typecode),
               len,
               ncftype(basetype->typ.typecode));
       codedump(stmt);
       break;

   case NC_CHAR:
       len = bbLength(code);
       f77quotestring(code);
       bbprintf0(stmt,"stat = nf_put_att_text(ncid, %s, %s, %lu, ",
               (asym->att.var == NULL?"NF_GLOBAL"
:(char *)f77varncid(asym- >att.var)), <--- and here
               f77escapifyname(asym->name),
               (len==0?1:len));
       codedump(stmt);
       codedump(code);
       codeline(")");
       break;

Here is static const char* f77varncid():

/* Compute the name for a given var's id*/
/* Watch out: the result is a static*/
static const char*
f77varncid(Symbol* vsym)
{
   const char* tmp1;
   char* vartmp;
   tmp1 = f77name(vsym);
   vartmp = poolalloc(strlen(tmp1)+strlen("_id")+1);
   strcpy(vartmp,tmp1);
   strcat(vartmp,"_id");
   return vartmp;
}

There are other lines in genf77.c that use f77varncid() in a print statement, so the warnings do not occur every time f77varncid() provides a string for %s:

   if (nvars > 0) {
       f77skip();
       f77comment("variable ids");
       for(ivar = 0; ivar < nvars; ivar++) {
           Symbol* vsym = (Symbol*)listget(vardefs,ivar);
           bbprintf0(stmt,"integer %s;\n", f77varncid(vsym));
           codedump(stmt);
       }

The warnings occur in the only two instances where f77varncid() is used in a conditional expression. In both cases, the second operand is a literal string, e.g., "NF_GLOBAL". I would have thought that a (static const char*) and a string literal would be compatible types. I experimented with a (const char *) cast instead of a (char *) cast, but that does not work. I think it should.

I admit, I have an old copy of the C standard — from 1990. But, here's my interpretation of what it says about this:

• 6.1.4 String literals, says string literals are converted to an array of type char. If the program attempts to modify a string literal, the behavior is undefined. It does not say that the type has the const type qualifier (though, you would think it should).

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

This would seem to explain the warning message, since the string literal is (char *) and f77varncid() is (const char *). However, 6.3.15 goes on to say:

Furthermore, if both operands are pointers to ... differently qualified versions of a compatible type, the result has the composite type.

Which leads me to believe you are allowed to mix const and non- const versions of a compatible type.

Lastly:

• 6.5.3 Type qualifiers, says that the properties associated with qualified types are meaningful only for expressions that are lvalues.

Seems to make the issue moot, since it says const-ness only applies to lvalues.

So, I think both 6.3.15 and 6.5.3 imply that (char *) and (const char *) are compatible as the second and third operands in a conditional expression which is not an lvalue, which is the case in this code. As I mentioned above, gcc does not complain about this code. What do you think?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov



--
Dave Borer      Customer Service Manager, The Portland Group
email           dave.bo...@st.com
phone           (503)-431-7113



--- End Message ---
--- Begin Message ---
Dave,

The more I thought about this issue, it seems to me the C 1990 section 6.3.15 applies:

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

Thus, ( cond ? (char *) : (const char *) ) should have the result type (const char *). Both (char *) and (const char *) are compatible as rvalues with (const char *), similar to passing either a (char *) or a (const char *) to a (const char *) function argument. pgcc should not be complaining. Do you agree?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov


--- End Message ---
--- Begin Message ---
Larry Baker wrote:
Dave,

The more I thought about this issue, it seems to me the C 1990 section 6.3.15 applies:

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

Thus, ( cond ? (char *) : (const char *) ) should have the result type (const char *). Both (char *) and (const char *) are compatible as rvalues with (const char *), similar to passing either a (char *) or a (const char *) to a (const char *) function argument. pgcc should not be complaining. Do you agree?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov <mailto:ba...@usgs.gov>

Larry,

 I created TPR 17139, and put your arguments in the report.
Engineering has not responded yet, but there is every possibility
you are correct.

 The language standards are are complicated, so I let
engineering tell me if a problem like this is a user bug or a compiler defect.

regards,
dave


--
Dave Borer      Customer Service Manager, The Portland Group
email           dave.bo...@st.com
phone           (503)-431-7113


--- End Message ---
--- Begin Message ---
Dave,

I have encountered more warnings that I think are spurious in conditional expressions. They all seem to be related to type conversions, like TPR 17139. I'll let you decide whether to report these separately, or add them to TPR 17139.

Before that, I wanted to add to TPR 17139 a discovery I made while looking into these other warnings. In the 1990 ISO C standard, section 6.3.15, Conditional operator, there are examples of operand types and the common type of the result of the conditional operator. One example is practically identical to the case I described, with int instead of char:

Given the declarations

   const int *c_ip;
   int *ip;

the third column in the following table is the common type that is the result of a conditional expression in which the first two columns are the second and third operands (in either order):

   ip    c_ip  const int *

These warnings appear when compiling openmpi-1.4.2 from http://www.open-mpi.org .

• Array name used in logical expression

OpenMPI defines a macro LT_STRLEN() that guards against calling strlen() with a null string. pgcc issues a warning for instances of LT_STRLEN() with a character array as the argument. For example:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    (((s) && (s)[0]) ? strlen (s) : 0)

int main () {
   char text[] = "junk";
   return LT_STRLEN( text );
}

[baker@hydra ~]$ pgcc -c junk.c
PGC-W-0089-Array name used in logical expression (junk.c: 6)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

Whether or not this warning is issued is inconsistent: it does not occur when the character array is a dummy argument:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    (((s) && (s)[0]) ? strlen (s) : 0)

int junk( char text[] ) {
   return LT_STRLEN( text );
}

I simplified the LT_STRLEN() macro to use a simpler form:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    ((s) ? strlen (s) : 0)

pgcc issues the same warning.

I assume the warning is because section 6.3.15 Conditional operator, requires a scalar type for the first operand:

Constraints

   Each of the operands shall have a scalar type.

However, section 6.2 Conversions, 6.2.2 Other operands, 6.2.2.1 L values and function designators, covers this situation:

Except ..., an lvalue that has type "array of type" is converted to an expression that has type "pointer to type" that points to the initial element of the array object and is not an lvalue.

According to section 6.1.2.5 Types, that is sufficient to convert an array name to a scalar type:

Arithmetic types and pointer types are collectively called scalar types.

I think this warning is spurious.

• Pointer value created from a nonlong integral type

OpenMPI uses 0 instead of NULL in conditional expressions with pointer type, usually as the third operand. For example, I modified one of their functions to simplify the code:

#include <stdlib.h>

void* malloc_starter(size_t sz, const void *caller) {
  void* victim;
  victim = malloc(sz);
  return victim ? victim : 0;
}

[baker@hydra ~]$ pgcc -c junk.c
PGC-W-0095-Type cast required for this conversion (junk.c: 6)
PGC-W-0155-Pointer value created from a nonlong integral type (junk.c: 6)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

Section 6.3.15 Conditional operator, Semantics, says:

If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types pointer-to by both operands. Furthermore, ...; if one operand is a null pointer constant, the result has the type of the other operand; ...

Section 6.2.2.3 Pointers, defines literal 0 as the null pointer constant:

An integral constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

According to the 1990 ISO C standard, no type cast is required; in this context, 0 is not an int (nonlong integral type), it is a pointer value -- specifically, it is the null pointer constant.

I think this warning is wrong.

Thanks,

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

On Jul 29, 2010, at 9:54 AM, PGI Technical Support wrote:

Larry Baker wrote:
Dave,

The more I thought about this issue, it seems to me the C 1990 section 6.3.15 applies:

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

Thus, ( cond ? (char *) : (const char *) ) should have the result type (const char *). Both (char *) and (const char *) are compatible as rvalues with (const char *), similar to passing either a (char *) or a (const char *) to a (const char *) function argument. pgcc should not be complaining. Do you agree?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov <mailto:ba...@usgs.gov>

Larry,

I created TPR 17139, and put your arguments in the report.
Engineering has not responded yet, but there is every possibility
you are correct.

The language standards are are complicated, so I let
engineering tell me if a problem like this is a user bug or a compiler defect.

regards,
dave


--
Dave Borer      Customer Service Manager, The Portland Group
email           dave.bo...@st.com
phone           (503)-431-7113



--- End Message ---
--- Begin Message ---
Larry,

  I have logged your report as TPR 17185.

thanks,
dave



Larry Baker wrote:
Dave,

I have encountered more warnings that I think are spurious in conditional expressions. They all seem to be related to type conversions, like TPR 17139. I'll let you decide whether to report these separately, or add them to TPR 17139.

Before that, I wanted to add to TPR 17139 a discovery I made while looking into these other warnings. In the 1990 ISO C standard, section 6.3.15, Conditional operator, there are examples of operand types and the common type of the result of the conditional operator. One example is practically identical to the case I described, with int instead of char:

Given the declarations

   const int *c_ip;
   int *ip;

the third column in the following table is the common type that is the result of a conditional expression in which the first two columns are the second and third operands (in either order):

   ip    c_ip  const int *

These warnings appear when compiling openmpi-1.4.2 from http://www.open-mpi.org.

• Array name used in logical expression

OpenMPI defines a macro LT_STRLEN() that guards against calling strlen() with a null string. pgcc issues a warning for instances of LT_STRLEN() with a character array as the argument. For example:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    (((s) && (s)[0]) ? strlen (s) : 0)

int main () {
   char text[] = "junk";
   return LT_STRLEN( text );
}

[baker@hydra ~]$ pgcc -c junk.c
PGC-W-0089-Array name used in logical expression (junk.c: 6)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

Whether or not this warning is issued is inconsistent: it does not occur when the character array is a dummy argument:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    (((s) && (s)[0]) ? strlen (s) : 0)

int junk( char text[] ) {
   return LT_STRLEN( text );
}

I simplified the LT_STRLEN() macro to use a simpler form:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    ((s) ? strlen (s) : 0)

pgcc issues the same warning.

I assume the warning is because section 6.3.15 Conditional operator, requires a scalar type for the first operand:

Constraints

   Each of the operands shall have a scalar type.

However, section 6.2 Conversions, 6.2.2 Other operands, 6.2.2.1 L values and function designators, covers this situation:

Except ..., an lvalue that has type "array of type" is converted to an expression that has type "pointer to type" that points to the initial element of the array object and is not an lvalue.

According to section 6.1.2.5 Types, that is sufficient to convert an array name to a scalar type:

Arithmetic types and pointer types are collectively called scalar types.

I think this warning is spurious.

• Pointer value created from a nonlong integral type

OpenMPI uses 0 instead of NULL in conditional expressions with pointer type, usually as the third operand. For example, I modified one of their functions to simplify the code:

#include <stdlib.h>

void* malloc_starter(size_t sz, const void *caller) {
  void* victim;
  victim = malloc(sz);
  return victim ? victim : 0;
}

[baker@hydra ~]$ pgcc -c junk.c
PGC-W-0095-Type cast required for this conversion (junk.c: 6)
PGC-W-0155-Pointer value created from a nonlong integral type (junk.c: 6)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

Section 6.3.15 Conditional operator, Semantics, says:

If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types pointer-to by both operands. Furthermore, ...; if one operand is a null pointer constant, the result has the type of the other operand; ...

Section 6.2.2.3 Pointers, defines literal 0 as the null pointer constant:

An integral constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

According to the 1990 ISO C standard, no type cast is required; in this context, 0 is not an int (nonlong integral type), it is a pointer value -- specifically, it is the null pointer constant.

I think this warning is wrong.

Thanks,

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

On Jul 29, 2010, at 9:54 AM, PGI Technical Support wrote:

Larry Baker wrote:
Dave,

The more I thought about this issue, it seems to me the C 1990 section 6.3.15 applies:

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

Thus, ( cond ? (char *) : (const char *) ) should have the result type (const char *). Both (char *) and (const char *) are compatible as rvalues with (const char *), similar to passing either a (char *) or a (const char *) to a (const char *) function argument. pgcc should not be complaining. Do you agree?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov <mailto:ba...@usgs.gov>

Larry,

I created TPR 17139, and put your arguments in the report.
Engineering has not responded yet, but there is every possibility
you are correct.

The language standards are are complicated, so I let
engineering tell me if a problem like this is a user bug or a compiler defect.

regards,
dave


--
Dave Borer    Customer Service Manager, The Portland Group
email        dave.bo...@st.com
phone        (503)-431-7113




--
Dave Borer      Customer Service Manager, The Portland Group
email           dave.bo...@st.com
phone           (503)-431-7113


--- End Message ---
--- Begin Message ---
Larry,

    This mail is inform you that TPRs

17185 - pgcc generating warnings from legal code - part 2

17186 - pgcc: Pragma ignored – string expected after #pragma ident

have been verified as fixed in the 12.10 PGI release.

Thanks again for the submissions.

regards,
dave



On 08/17/10 14:49, Larry Baker wrote:
Dave,

I have encountered more warnings that I think are spurious in conditional expressions. They all seem to be related to type conversions, like TPR 17139. I'll let you decide whether to report these separately, or add them to TPR 17139.

Before that, I wanted to add to TPR 17139 a discovery I made while looking into these other warnings. In the 1990 ISO C standard, section 6.3.15, Conditional operator, there are examples of operand types and the common type of the result of the conditional operator. One example is practically identical to the case I described, with int instead of char:

Given the declarations

   const int *c_ip;
   int *ip;

the third column in the following table is the common type that is the result of a conditional expression in which the first two columns are the second and third operands (in either order):

   ip    c_ip  const int *

These warnings appear when compiling openmpi-1.4.2 from http://www.open-mpi.org.

• Array name used in logical expression

OpenMPI defines a macro LT_STRLEN() that guards against calling strlen() with a null string. pgcc issues a warning for instances of LT_STRLEN() with a character array as the argument. For example:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    (((s) && (s)[0]) ? strlen (s) : 0)

int main () {
   char text[] = "junk";
   return LT_STRLEN( text );
}

[baker@hydra ~]$ pgcc -c junk.c
PGC-W-0089-Array name used in logical expression (junk.c: 6)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

Whether or not this warning is issued is inconsistent: it does not occur when the character array is a dummy argument:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    (((s) && (s)[0]) ? strlen (s) : 0)

int junk( char text[] ) {
   return LT_STRLEN( text );
}

I simplified the LT_STRLEN() macro to use a simpler form:

/* LT_STRLEN can be used safely on NULL pointers.  */
#define LT_STRLEN(s)    ((s) ? strlen (s) : 0)

pgcc issues the same warning.

I assume the warning is because section 6.3.15 Conditional operator, requires a scalar type for the first operand:

Constraints

   Each of the operands shall have a scalar type.

However, section 6.2 Conversions, 6.2.2 Other operands, 6.2.2.1 L values and function designators, covers this situation:

Except ..., an lvalue that has type "array of type" is converted to an expression that has type "pointer to type" that points to the initial element of the array object and is not an lvalue.

According to section 6.1.2.5 Types, that is sufficient to convert an array name to a scalar type:

Arithmetic types and pointer types are collectively called scalar types.

I think this warning is spurious.

• Pointer value created from a nonlong integral type

OpenMPI uses 0 instead of NULL in conditional expressions with pointer type, usually as the third operand. For example, I modified one of their functions to simplify the code:

#include <stdlib.h>

void* malloc_starter(size_t sz, const void *caller) {
  void* victim;
  victim = malloc(sz);
  return victim ? victim : 0;
}

[baker@hydra ~]$ pgcc -c junk.c
PGC-W-0095-Type cast required for this conversion (junk.c: 6)
PGC-W-0155-Pointer value created from a nonlong integral type (junk.c: 6)
PGC/x86-64 Linux 10.3-0: compilation completed with warnings

Section 6.3.15 Conditional operator, Semantics, says:

If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types pointer-to by both operands. Furthermore, ...; if one operand is a null pointer constant, the result has the type of the other operand; ...

Section 6.2.2.3 Pointers, defines literal 0 as the null pointer constant:

An integral constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

According to the 1990 ISO C standard, no type cast is required; in this context, 0 is not an int (nonlong integral type), it is a pointer value -- specifically, it is the null pointer constant.

I think this warning is wrong.

Thanks,

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov

On Jul 29, 2010, at 9:54 AM, PGI Technical Support wrote:

Larry Baker wrote:
Dave,

The more I thought about this issue, it seems to me the C 1990 section 6.3.15 applies:

• 6.3.15 Conditional operator, says if the second and third operands are pointers ..., the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands.

Thus, ( cond ? (char *) : (const char *) ) should have the result type (const char *). Both (char *) and (const char *) are compatible as rvalues with (const char *), similar to passing either a (char *) or a (const char *) to a (const char *) function argument. pgcc should not be complaining. Do you agree?

Larry Baker
US Geological Survey
650-329-5608
ba...@usgs.gov <mailto:ba...@usgs.gov>

Larry,

I created TPR 17139, and put your arguments in the report.
Engineering has not responded yet, but there is every possibility
you are correct.

The language standards are are complicated, so I let
engineering tell me if a problem like this is a user bug or a compiler defect.

regards,
dave


--
Dave Borer    Customer Service Manager, The Portland Group
email        dave.bo...@st.com
phone        (503)-431-7113





--
Dave Borer, Customer Service Manager             email: t...@pgroup.com
The Portland Group                               Phone:  +1-503-682-2806
Two Centerpointe Dr, Suite 320                   Direct: +1-503-431-7113
Lake Oswego, OR USA 97035                        FAX:    +1-503-682-2637


--- End Message ---
Hi Paul

Looking at these, I'm a tad puzzled. It would appear that PGI is complaining about the fixed string being passed in the last three cases as there is no (const char*)foo being used in those areas. Yet we use that same logic elsewhere and your report isn't showing those as warnings.

Do you think it is the fixed string that is the issue - or is it the (const char*) variable we need to recast?


On Jan 16, 2014, at 11:24 PM, Paul Hargrove <phhargr...@lbl.gov> wrote:

My builds of the trunk with pgcc-13.10 turned up the following warnings:

PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/opal/mca/db/hash/db_hash.c: 354)
PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/opal/mca/db/hash/db_hash.c: 376)
PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/opal/mca/db/hash/db_hash.c: 452)
PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/opal/mca/db/hash/db_hash.c: 534)

PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/orte/mca/state/base/state_base_fns.c: 766)

PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/orte/mca/plm/rsh/plm_rsh_component.c: 368)

PGC-W-0095-Type cast required for this conversion (/scratch/scratchdirs/hargrove/OMPI/openmpi-trunk-linux-x86_64-pgi-13.10/openmpi-1.9a1r30302/orte/mca/plm/rsh/plm_rsh_module.c: 1337)

I believe all of these are related to passing a (const char *) to OPAL_OUTPUT_VERBOSE().

-Paul 


--
Paul H. Hargrove                          phhargr...@lbl.gov
Future Technologies Group
Computer and Data Sciences Department     Tel: +1-510-495-2352
Lawrence Berkeley National Laboratory     Fax: +1-510-486-6900
_______________________________________________
devel mailing list
de...@open-mpi.org
http://www.open-mpi.org/mailman/listinfo.cgi/devel

_______________________________________________
devel mailing list
de...@open-mpi.org
http://www.open-mpi.org/mailman/listinfo.cgi/devel

Reply via email to