0

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);
}
embedded_guy
  • 1,939
  • 3
  • 24
  • 39
  • 1
    `AnotherExample_t const * const p_example` -> `const AnotherExample_t* p_example`. I also bet this example is not [mcve] (as in - non **minimal**) – SergeyA Jul 20 '21 at 20:58
  • @SergeyA I tried that as well, but still have the same error. – embedded_guy Jul 20 '21 at 21:03
  • you need to really work on your example and minimize it. I am pretty sure there is a lot of noise there. Please post the full but minimal code where function signature matches the one I suggested. – SergeyA Jul 20 '21 at 21:04
  • @SergeyA Added a better example. – embedded_guy Jul 20 '21 at 21:14
  • I was not able to reproduce the problem using online Lint here: https://gimpel.com/demo.html Original snippet has another issue (%c incompatible with char* for printf), which online Lint picks up. But otherwise the code is fine. Are you sure it is the right snippet? – SergeyA Jul 20 '21 at 21:34
  • @SergeyA I am sure. That was copied and pasted directly from the code that I ran PC-lint on. – embedded_guy Jul 20 '21 at 21:38
  • 1
    Well, that means your Lint has a bug. If you are sure this is the code, and this is the only warning Lint gave you, it means that Lint failed to warn on the real problem of incompatible printf format string, but instead reported on absolutely correct function definition. The only thing I can suggest at this point is filing a bug report with Lint maintainers. – SergeyA Jul 20 '21 at 21:46

1 Answers1

2

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.

embedded_guy
  • 1,939
  • 3
  • 24
  • 39
  • that's.... bizarre, the vendor stdio.h does `#define const` to something? – M.M Jul 21 '21 at 01:31
  • I'm still working through the library files, but it is not just affecting stdio.h. I am using code composer studio and the cl430 compiler for TI's MSP430 product line. I suspect that there is some project defined #define's that are utilized by a library file that I have yet to track down and that those are utilized in some of the TI library files (ie. - _ti_config.h, linkage.h, sys/cdefs.h, machine/_types.h, etc). I'm hoping to find a more elegant solution specific to this compiler. Unfortunately, I haven't seen a good compiler options file for lint that works with cl430. – embedded_guy Jul 21 '21 at 15:14