Redeclaration errors with Mixed C and C++ code

When simultaneously linting C and C++ modules that both make use of string facilities, re-declaration errors for certain standard library functions may be encountered due to the fact that a handful of C library functions have slightly different signatures in C++.  For example, the prototype for the memchr function in C is:

void *memchr(const void *s, int c, size_t n);

while C++ provides the following prototypes for memchr:

const void* memchr(const void* s, int c, size_t n);
void* memchr(void* s, int c, size_t n);

With GCC, when processing the string.h header without __cplusplus defined, only the first prototype is visible; when __cplusplus is defined, only the second two are visible (cstring includes string.h).  When you run PC-lint/FlexeLint on mixed C and C++ code, both of which include string.h (directly or indirectly), you get all three declarations and the C version conflicts with the first C++ version.  There are a couple of things you can do here:
  1. Lint the C and C++ code separately.  This will completely avoid the issue.
  2. Suppress the message using either:
    -elib(18)  or (preferably)
    '-esym(18,memchr)' '-esym(18,strchr)' '-esym(18,strrchr)' ...
Neither solution is perfect, with the first solution you may miss important cross-module checks between C and C++ modules.  With the second solution, although the messages will be suppressed, it is important to note that the conflicting declarations will not be loaded into the symbol table.  If the C declaration is seen first, this means that the first C++ declaration won't be loaded.  The effect is minimal, assigning the result of one of the alternately declared functions called with a const first argument to a non-const variable will not be detected:

#include <cstring>

extern const void *cvp2;
extern void *vp2;


void f2() {
    vp2 = memchr(cvp2, 'a', 10);  // no complaint about loss of const-ness
}

If the module is processed without first seeing the C declaration, you will receive a message about the increase in capability during the assignment, with the C declaration visible there is no warning.

If Lint processes the C++ versions first, then the C version will never be loaded which will have the opposite effect, producing a warning where none is expected:

#include <string.h>

extern int *ip1;
extern const void *cvp1;

void f1(void) {
    ip1 = memchr(cvp1, 'a', 10);  // unexpected warning here
}

So you probably want to ensure the C versions are loaded first, either by listing the C modules before the C++ modules when linting or by including a dummy C file that #includes string.h and wchar.h as the first file linted (all the conflicting declarations come from these headers).  For reference purposes, the full list of conflicting names (on GCC) is:

memchr
strchr
strrchr
strpbrk
strstr
strerror_r
index
rindex
wcschr
wcsrchr
wcspbrk
wcsstr
wmemchr

which corresponds to the following suppression options:

-esym(18,memchr)
-esym(18,strchr)
-esym(18,strrchr)
-esym(18,strpbrk)
-esym(18,strstr)
-esym(18,strerror_r)
-esym(18,index)
-esym(18,rindex)
-esym(18,wcschr)
-esym(18,wcsrchr)
-esym(18,wcspbrk)
-esym(18,wcsstr)
-esym(18,wmemchr)

Feedback and Knowledge Base