为什么 PC-Lint 会抱怨重新声明(错误 18)?

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

请注意,以下代码毫无意义,我只是想重现我在更复杂的代码库中看到的错误。显然,我不会创建一个具有全局范围的变量来将它传递给一个仅在该变量所在的文件中使用的函数。

我是 运行 PC-Lint 9.00L。

在以下示例中,PC-Lint 抱怨重新声明:

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

代码如下:

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

为什么 lint 抛出这个错误?

我尝试过的事情

我注意到当我删除 const AnotherExample_t 的声明时,投诉就消失了。即 -

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

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

我还尝试从 example1.c 发出调用,只是想看看是否改变了什么:

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

这并没有改变任何东西。

在这两种情况下,我都会收到 Info 818 消息:

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

最小可重现代码

这也会导致同样的错误。

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

这既不是 PC-Lint 的错误,也不是我的代码中的错误。编译器库中对关键字进行了一些重新定义,导致 PC-Lint 在其预处理步骤中删除了一些关键字(例如 constvolatile)。

最终结果是,当我添加 #include <stdio.h> 时,我对 testFunction 的定义将被删除其 const 限定符,并且它将不再匹配我的 [=63] 中的声明=].

我在 co-XXXX.lnt 文件中添加了以下选项,错误消失了。

+dconst=const
+dvolatile=volatile

特别感谢 Gimpel 的工作人员,他们愿意与我一起解决这个问题,尽管 PC-Lint 这个版本不再受支持。

更新

不幸的是,我没有时间在库中找到 constvolatile re-defined,但我找到了更好的 work-around 而不仅仅是 lint 编译器选项文件中的 re-defining 这些关键字。使用 PC-Lint 中的 -scavenge 选项,然后 运行 通过 pre-processor 选项创建的 .c 文件创建一个 header 定义编译器的 built-in 供 PC-Lint 使用的宏。这是我使用的过程。

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

然后,我 运行 从 Code Composer Studio 中对我的代码进行了标准构建,以验证哪些选项被 运行 使用 cl430 编译器。在那之后,我 运行 interim.c 通过具有相同选项的编译器 - 唯一的例外是我使用 -ppo 选项来 运行 它仅通过预处理器,保存结果文件为 interim.lnt.

此时,PC-Lint 手册对 运行 说:lint -scavenge(clean,interim.lnt)。在我的情况下,似乎只是清除了所有数据的文件,所以我跳过了这一步。但是,检查在此步骤之前创建的 interim.lnt 文件表明我的所有宏都是在此文件中创建的。我将其重命名为 lint_header.h 并将以下行添加到我的 co-MSP430.lnt 文件的开头:

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

我不再为 constvolatile 使用 +d 选项,现在可以更准确地表示我的库文件在与 PC-Lint 一起使用时应该做什么。我也不再有重新声明错误。