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);
}
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.