cstatic-analysislintpc-lint

Why does PC-Lint complain about redeclaration (Error 18)?


Please note that the following code is pretty meaningless, I just wanted to reproduce an error that I am seeing in a much more complex codebase. Obviously, I would not create a variable with global scope to pass it to a function that is used in only one file in which the variable resides.

I'm running PC-Lint 9.00L.

In the following example, PC-Lint complains about a redeclaration:

example2.c 18 Error 18: Symbol'testFunction(const struct AnotherExample_t *)' redeclared (Arg. no. 1: qualification) conflicts with line 21, file example.h, module example1.c

Here is the code:

example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

#include <stdint.h>

typedef struct
{
    volatile uint8_t item1;
    volatile uint8_t item2;
} Example_t;

typedef struct
{
    Example_t * p_items;
    uint8_t something;
    uint16_t somethingElse;
} AnotherExample_t;

extern AnotherExample_t g_externalVariable;

extern void testFunction (AnotherExample_t const * const p_example);  //line 21
    
#endif

example1.c

#include "example.h"
#include <stdio.h>

int main(void)
{
    g_externalVariable.something = 5;
    
    (void)printf("%d", g_externalVariable.something);
    
    testFunction(&g_externalVariable);
    return 0;
}

example2.c

#include "example.h"
#include <stdio.h>

static Example_t p = 
{
    .item1 = 0,
    .item2 = 1,
};

AnotherExample_t g_externalVariable =
{
    .p_items = &p,
    .something = 2,
    .somethingElse = 3,
};

void testFunction (AnotherExample_t const * const p_example)
{  // Line referenced in lint (line 18)
    (void)printf("%d", (int)p_example->somethingElse);
}

Why is lint throwing this error?

THINGS I ATTEMPTED

I noticed that when I remove the declaration of const AnotherExample_t that the complaint goes away. i.e. -

extern void testFunction (AnotherExample_t * const p_example);  //example.h

void testFunction (AnotherExample_t * const p_example)  //example2.c
{
    ...
}

I also attempted to cast the call from example1.c just to see if that changed anything:

testFunction((AnotherExample_t const * const)&g_externalVariable);

That did not change anything.

In both cases, I get an Info 818 message as well:

example2.c 20 Info 818: Pointer parameter 'p_example' (line 17) could be declared as pointing to const

Minimal Reproducible Code

This also results in the same error.

example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

extern void testFunction (const char * const p_example);
    
#endif

example1.c

#include "example.h"
#include <stdio.h>

int main(void)
{
    char testValue = 'c';
    char * p_testValue = &testValue;
    
    testFunction(p_testValue);
    
    return 0;
}

example2.c

#include "example.h"
#include <stdio.h>

void testFunction (const char * const p_example)
{
    (void)printf("%c", p_example);
}

Solution

  • This was neither a bug with PC-Lint nor an error in my code. There were some redefinitions of keywords in the compiler libraries that were causing PC-Lint to strip some keywords during its preprocessing step (such as const and volatile).

    The end result was that when I added #include <stdio.h> my definition of testFunction would be stripped of its const qualifiers and it would no longer match the declaration in my header.

    I added the following options to my co-XXXX.lnt file and the error went away.

    +dconst=const
    +dvolatile=volatile
    

    A special thanks to the Gimpel staff who were willing to work through this with me despite the fact that this version of PC-Lint is no longer supported.

    UPDATE

    Unfortunately, I haven't had time to track down where in the libraries that const and volatile were being re-defined, but I have found a better work-around than just re-defining these keywords in the lint compiler options file. Utilizing the -scavenge option within PC-Lint and then running the .c file that option creates through the pre-processor creates a header that defines the compilers' built-in macros for use by PC-Lint. Here is the process that I used.

    lint-nt -i"/path/to/my/libraries" -scavenge(*.h) > interim.c
    

    I then ran a standard build of my code from Code Composer Studio to verify which options were being run with the cl430 compiler. After that, I ran interim.c through the compiler with the same options - the only exception being that I used the -ppo option to run it through the preprocessor only, saving the resultant file as interim.lnt.

    At this point, the PC-Lint manual says to run: lint -scavenge(clean,interim.lnt). In my situation that only seemed to clear the file of all data, so I skipped this step. However, examining the interim.lnt file created prior to this step showed that all of my macros were created in this file. I renamed it to lint_header.h and added the following lines to the beginning of my co-MSP430.lnt file:

    -header(lint_header.h)
    +libh(lint_header.h)
    

    I am no longer using the +d options for const and volatile and now have a more accurate representation of what my library files should be doing for use with PC-Lint. I no longer have the redeclaration error as well.