3

我有这个 C 代码:

EaglePage* EaglePage_RealCopy(EaglePage *page)
{
    if(NULL == page) {
        return NULL;
    }

    switch(page->type) {

        case EagleDataTypeUnknown:
            EagleLogger_Log(EagleLoggerSeverityError, "Cannot page of Unknown type.");
            return NULL;

        case EagleDataTypeInteger:
            return EaglePage_RealCopyInt_(page);

        case EagleDataTypeVarchar:
            return EaglePage_RealCopyVarchar_(page);

        case EagleDataTypeFloat:
            return EaglePage_RealCopyFloat_(page);

    }
}

当我在 Mac OS X 上使用 clang 编译它时,它知道开关处理所有“可能的”分支,并且不会警告缺少返回语句(如 Java)。但是,如果我通过 GCC 4.4.5 运行相同的代码,它总是会给出缺少返回警告。

这很烦人,因为如果我放入 return 语句,那么我的代码覆盖率就会中断,因为我没有涵盖那些“不可能”的场景。GCC 有没有办法像 clang/javac 一样处理这个问题?

4

3 回答 3

4

default有时会发生这种情况,但使用标签很容易解决。

switch(page->type) {

    case EagleDataTypeInteger:
        return EaglePage_RealCopyInt_(page);

    case EagleDataTypeVarchar:
        return EaglePage_RealCopyVarchar_(page);

    case EagleDataTypeFloat:
        return EaglePage_RealCopyFloat_(page);

    case EagleDataTypeUnknown:
    default:
        EagleLogger_Log(EagleLoggerSeverityError, "Cannot page of Unknown type.");
        return NULL;

}
于 2013-06-15T08:57:11.520 回答
0

您没有向编译器提供任何信息来知道只有四个可能的值,例如,如果您放置 switch(page->type&3) 则取决于编译器是否足够聪明,知道您已经涵盖了所有可能的值案例和所有路径都被处理(切换后的任何代码都将被标记为无法访问)。编译器能否做到这一点与编译器、该品牌和版本的特定功能有关。

拥有一个返回点不会给您带来任何您想要做的事情,您仍然必须通过此代码验证 5 条路径(您从系统级别说的其中一条是无法到达那里的)。编译器并不总是也不能总是关注系统级别,但有时只能关注功能级别。llvm 工具可以使用单独编译的源文件轻松优化整个项目,其中 gcc 需要将所有内容放在一个大文件中(包含包含)来做到这一点。

当您编写代码时,编译器将通过代码正确生成第五条路径,这就是您的代码告诉它要做的事情,除非编译器中存在错误,否则它会这样做。如果您希望编译器执行其他操作,然后通过更改您的源代码告诉编译器执行其他操作(或向编译器显示比您向我们显示的更多,如果这里有代码我们看不到使用此代码编译的代码是另一个故事,或者如我上面所展示的,如果在此代码中您向编译器演示了范围限制,那么它就有机会限制在该范围内)。

于 2013-06-15T19:44:23.603 回答
0

clang 不仅仅是一个编译器,更是字节码编译器和静态分析工具的混合体。因此,在这种特殊情况下您没有看到来自 clang 的警告的原因是,可以证明您的函数不能使用开关未覆盖的值调用。

或者它可能是clang中的一个错误。

尝试将此函数添加到您的代码中,并确保它被调用,然后看看会发生什么:

void BogusEaglePage_Call(void) {
  EaglePage *bp, *br;
  bp = malloc (sizeof (*bp));
  if (bp) {
    bp->type = (EagleDataTypeInteger | EagleDataTypeVarchar | EagleDataTypeFloat | EagleDataTypeUnknown) << 2;
    br = EaglePage_RealCopy(bp);
  }
}

如果clang仍然没有给你警告,我建议你报告一个缺陷。

于 2013-06-15T19:22:37.167 回答