为什么海湾合作委员会不够聪明,无法理解遗漏的退货声明?

时间:2013-06-15 08:50:54

标签: c llvm clang

我有这个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);

    }
}

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

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

3 个答案:

答案 0 :(得分: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;

}

答案 1 :(得分:1)

您还没有给编译器任何信息知道只有四个可能的值,例如,如果你把switch(page-> type& 3),那么由编译器决定是否足够聪明才能知道您已经涵盖了所有可能的情况并且处理了所有路径(交换机被标记为无法访问后的任何代码)。编译器是否可以执行此操作与编译器,该品牌和版本的特定功能有关。

只有一个返回点并不能用你想要的东西给你买任何东西,你仍然必须通过这个代码验证5条路径(你从系统层面说的那条路是不能到达那里)。编译器总是不能始终查看系统级别,但有时只能关注功能级别。 llvm工具可以使用单独编译的源文件轻松地在整个项目中进行优化,其中gcc需要在一个大文件(包含include)中完成所有这些操作。

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

答案 2 :(得分: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仍然没有给你一个警告,我建议你报告一个缺陷。