2012-07-13 87 views
2

我在我們的fortran代碼的自定義預處理器的環境中工作。我使用預處理器將邏輯參數切換爲一種窮人的函數指針。今天我意識到,我有一個類似的情況:gfortran編譯器錯誤?

program main 
    logical,parameter :: untrue=.false. 
    if(untrue)then 
    call func1() 
    else 
    call func2() 
    endif 
    end 

    subroutine func2() 
    print*,"Hello, World!" 
    end 

換句話說,func1不被任何定義,但是,這個編譯與gfortran(版本4.4和4.6),因爲據推測,編譯器優化了通話了。我目前沒有其他編譯器需要檢查,這些代碼是否可以在其他地方編譯?可以/應該這被認爲是一個編譯器錯誤?

因爲我切換邏輯開關(而不是包含/不包含代碼),部分原因是編譯器仍然可以檢查該代碼塊中的接口/語法(如果有能力的話)(並針對事件發出適當的警告不是簡單的函數調用)。這是否意味着這些測試沒有被執行或者鏈接器不需要該功能,因此一切都會通過Ok?

回答

6

這不是一個編譯器錯誤。缺少引用的外部子程序不是標準需要Fortran處理器進行診斷的問題。其他處理器可能會或可能不會抱怨。諸如優化設置等事情可能會影響結果 - 英特爾Fortran 12.1.5抱怨優化關閉,不會抱怨優化。

對於您的示例代碼,其中func2是外部子程序,Fortran單獨的程序單元編譯模型意味着不需要過程接口檢查。對於很多處理器來說,它不太可能發生(實際上func2可能在一個單獨的文件中,這個文件可能在主程序之後很長的時間內編譯,也許在不同的機器上,也許在主程序的源碼不再可用的情況下) 。如果你想保證程序接口檢查,那麼你需要確保程序有一個明確的接口,比如把它們放在一個模塊中。在Fortran 2003標準中引入並且至少由gfortran 4.6支持的過程指針語言功能也可能有所幫助。

+0

謝謝。在這一點上,我不能依賴標準的新版本。代碼是在15年前編寫的,並且預處理器是這​​樣的,許多f90構造甚至可能導致它斷裂:-(我也知道需要一個接口的程序檢查 - 但是,我們的pre -processor。我想,既然標準甚至沒有解決死代碼的問題,什麼都行......謝謝(我會等一會兒,只是爲了確保沒有其他人有任何關於此的說法,如果他們不要,我會很樂意接受這一點+1對於一個很好的答案任何方式。) – mgilson 2012-07-13 03:43:52

1

你在這裏看到的僅僅是編譯器,它允許自己忽略任何永遠不會被調用的引用。該行:

logical,parameter :: untrue=.false. 

保證您的if塊的第一部分不會被執行。正如IanH指出的(+1),這不是編譯器錯誤,是優化過程的一部分。此代碼還將使用pgf90 10.6-0ifort 12.0.2.137進行默認優化編譯。但是,如果指示在未啓用優化的情況下進行編譯,它們將會失敗。

但是,如果你行說:

logical :: untrue=.false. 

它更可能對編譯器的抱怨,作爲變量untrue被允許改變其值。例如,除非需要更高的優化級別,否則pgf90將失敗,而'ifort'仍將在默認優化級別上編譯。

在任何情況下,依賴於編譯器行爲並不是最佳實踐,並且正如IanH指出的那樣,最好通過使用模塊來指定外部函數和子例程接口。

+0

'ifort'的默認優化級別是'O2' :) – 2012-07-13 07:59:53

2

它似乎是GNU Fortran的特定行爲,即使在優化級別O0上也會刪除無法訪問的代碼段。這符合ISO/IEC 1539:1991:§8.1.2規定只有一個IF構造塊必須被執行,§8.1.1。2明確禁止將控制權從控制塊外部轉移到塊的內部。這允許編譯器刪除那些肯定不會執行的代碼部分,這很有意義,因爲您不能在您的示例中更改IF構造的行爲,而無需重新編譯程序源代碼,並且編譯器只是精通符號。

但是我仍然覺得很奇怪gfortran不會提示無法訪問的代碼,即使編譯時使用-Wall -Wunreachable-code