Opened 8 years ago

Closed 8 years ago

#6602 closed defect (fixed)

C does not like const of CSLFindString as done in r34749

Reported by: Kurt Schwehr Owned by: Kurt Schwehr
Priority: normal Milestone:
Component: default Version: svn-trunk
Severity: blocker Keywords:
Cc:

Description (last modified by Kurt Schwehr)

e.g. https://travis-ci.org/rouault/gdal_coverage/builds/146409340

gcc -I/home/travis/build/rouault/gdal_coverage/gdal/port -I/home/travis/build/rouault/gdal_coverage/gdal/gcore -I/home/travis/build/rouault/gdal_coverage/gdal/alg -I/home/travis/build/rouault/gdal_coverage/gdal/ogr -I/home/travis/build/rouault/gdal_coverage/gdal/ogr/ogrsf_frmts -I/home/travis/build/rouault/gdal_coverage/gdal/gnm -I/home/travis/build/rouault/gdal_coverage/gdal/apps -fPIC  -g -DDEBUG -ftrapv  -Wall -Wdeclaration-after-statement -Wextra -Winit-self -Wunused-parameter -Wmissing-prototypes -Wmissing-declarations -Wformat -Werror=format-security -Wno-format-nonliteral -Wlogical-op -Wshadow -Werror=vla -Wdeclaration-after-statement -DDEBUG_BOOL -Wextra -Werror -I../shape -I.. -I../..  -DOGR_ENABLED -D_REENTRANT  -I/home/travis/build/rouault/gdal_coverage/gdal/port -I/usr/local/include -I/usr/include  -DGDAL_COMPILATION -c -o ../o/avc_e00read.o avc_e00read.c
avc_e00read.c: In function ‘_AVCE00ReadBuildSqueleton’:
avc_e00read.c:1040:5: error: passing argument 1 of ‘CSLFindString’ from incompatible pointer type [-Werror]
/home/travis/build/rouault/gdal_coverage/gdal/port/cpl_string.h:106:13: note: expected ‘const char * const*’ but argument is of type ‘char **’
avc_e00read.c:1061:5: error: passing argument 1 of ‘CSLFindString’ from incompatible pointer type [-Werror]
/home/travis/build/rouault/gdal_coverage/gdal/port/cpl_string.h:106:13: note: expected ‘const char * const*’ but argument is of type ‘char **’
...
cc1: all warnings being treated as errors

What exactly is this complaining about?

Possible solutions (will they even work)?

  • Separate out a new const function and have the old call the new. CSLFindStringConst or CSLFindString2 or CSLFindStringEx
  • Provide a different signature for C without the const (if it will link)
  • Have a define like GDAL_CONST_STRICT to provide a more cost API for places that want it
  • Revert and give up in despair
  • Can we cast in the C code?
  • Convert C code to C++ (doesn't help mapserver, which is C)
  • Or?

Reported by EvenR.

Example code that is failing (from Ubuntu 14.04 @ r34748):

/* avc_e00read.c */
static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
                                     char **papszCoverDir)
{

/* ... */

    szFname = (psInfo->eCoverType==AVCCoverV7 ||
               psInfo->eCoverType==AVCCoverPC2 ) ? "arc.adf": "arc";
    if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
         (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
                                  psInfo->eCoverType, AVCFileARC,
                                  psInfo->psDBCSInfo)) != NULL)
    {

Fails like:

avc_e00read.c: In function '_AVCE00ReadBuildSqueleton':
avc_e00read.c:1040:5: warning: passing argument 1 of 'CSLFindString' from incompatible pointer type [enabled by default]
     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
     ^
In file included from avc.h:119:0,
                 from avc_e00read.c:129:
/home/schwehr/src/gdal/gdal/port/cpl_string.h:106:13: note: expected 'const char * const*' but argument is of type 'char **'
 int CPL_DLL CSLFindString( const char * const *, const char * );

Could cast in C:

    szFname = (psInfo->eCoverType==AVCCoverV7 ||
               psInfo->eCoverType==AVCCoverPC2 ) ? "arc.adf": "arc";
    if ( (iFile=CSLFindString((const char * const *)papszCoverDir, szFname)) != -1 &&
         (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
                                  psInfo->eCoverType, AVCFileARC,
                                  psInfo->psDBCSInfo)) != NULL)
    {

Or modify cpl_string.h to present non-const to C. (least bad so far)

#ifdef __cplusplus
int CPL_DLL CSLFindString( const char * const *, const char * );
int CPL_DLL CSLFindStringCaseSensitive( const char * const *, const char * );
int CPL_DLL CSLPartialFindString( const char * const *papszHaystack,
                                  const char * pszNeedle );
#else
// Present non-const to C code that does not like passing non-const to const.
int CPL_DLL CSLFindString( char **, const char * );
int CPL_DLL CSLFindStringCaseSensitive( char **, const char * );
int CPL_DLL CSLPartialFindString( char **papszHaystack,
                                  const char * pszNeedle );
#endif

Change History (3)

comment:1 by Kurt Schwehr, 8 years ago

Description: modified (diff)

comment:2 by Kurt Schwehr, 8 years ago

Description: modified (diff)
Status: newassigned

comment:3 by Kurt Schwehr, 8 years ago

Resolution: fixed
Status: assignedclosed

r34750 Marking as fixed. Reopen if this doesn't work somehow.

Apparently the general reason for this restriction is that if you could pass "char " into "const char ", then you could assign a "const char *" to the outer pointer and thus allow the caller to violate constness. C++ has a more complex rule which recognizes that "const char * const *" is safe against this, but C does not.

Note: See TracTickets for help on using tickets.