簡體   English   中英

為什么海灣合作委員會不夠聰明,無法理解遺漏的退貨聲明?

[英]Why isn't GCC smart enough to understand a missing return statement?

我有這個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運行相同的代碼,它總是會給出一個丟失的返回警告。

這很煩人,因為如果我輸入了返回語句,那么我的代碼覆蓋率會因為我沒有涵蓋那些“不可能”的情況而中斷。 有沒有辦法讓GCC像clang / javac一樣處理這個問題?

這有時會發生,但使用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;

}

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仍然沒有給你一個警告,我建議你報告一個缺陷。

你沒有給編譯器任何信息知道只有四個可能的值,例如你把switch(page-> type&3)然后編譯器要足夠智能知道你已經涵蓋所有可能的處理案例和所有路徑(交換機被標記為無法訪問后的任何代碼)。 編譯器是否可以執行此操作與編譯器,該品牌和版本的特定功能有關。

擁有一個單一的返回點並不能為你帶來任何你想要做的事情,你仍然必須通過這個代碼驗證5條路徑(你從系統層面說的是哪一條是不能到達那里)。 編譯器總是不能始終查看系統級別,但有時只能關注功能級別。 llvm工具可以使用單獨編譯的源文件輕松地在整個項目中進行優化,其中gcc需要在一個大文件(包括include)中完成所有這些操作。

在編寫代碼時,編譯器將正確生成代碼中的第五條路徑,即代碼告訴它要執行的操作,除非編譯器中存在錯誤,否則它將執行此操作。 如果您希望編譯器執行其他操作,請通過更改源代碼來告訴編譯器執行其他操作(或者顯示編譯器比您向我們展示的更多,如果此處有代碼,我們無法看到使用此代碼編譯另一個故事,或者如上所示,如果在此代碼中您向編譯器演示了范圍限制,那么它可以有機會限制到該范圍)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM