2017-03-02 48 views
6

我正在研究C++ 11的靜態分析器。在一個類的靜態常量成員和鏈接之間有一個交互,我不確定它是否被定義。只有當這個構造沒有被定義時,我的靜態分析器纔會警告它。在另一個文件中定義的靜態常量數據成員

的例子是這樣的一個:

文件f1.cpp:

struct Foo { 
    static const int x = 2; 
}; 

int main(void) { 
    return *&Foo::x; 
} 

,並在文件f2.cpp:

struct Foo { 
    static int x; 
}; 

int Foo::x; 

編譯和clang++ -std=c++11 -Weverything f1.cpp f2.cpp原因鏈接兩個文件沒有警告併產生返回0的二進制文件。與g++ -std=c++11 -Wall -Wextra -pedantic f1.cpp f2.cpp編譯時相同的文件不會導致警告並返回2.

我的直覺是,這個程序是不明確的,但不要求警告,如:

  • 兩個名字的Foo :: x具有以下N3376 [basic.link] P5外部鏈接:

    此外,成員函數靜態數據成員 具有用於鏈接目的的typedef名稱(7.1.3),如果該類名稱具有外部 鏈接,則具有外部鏈接。

  • 但他們打破N3376 [basic.link] P10要求:

    的類型所有的調整之後(在此期間類型定義(7.1.3)由它們的定義被替換),該類型 由所有涉及給定變量或函數的聲明指定的應該是相同的[...]違反此類型標識規則不需要診斷。

是100%地肯定這一點,需要對這些「類型的所有調整」的定義,但似乎無處可在C++ 11標準中找到。有沒有,上面的推理是正確的?

+2

見[§basic.def.odr/ P5] (https://timsong-cpp.github.io/cppwp/n3337/basic.def.odr#5),具體爲[5.1](https://timsong-cpp.github.io/cppwp/n3337/basic.def。 odr#5.1):'可以有一個以上的類類型定義... D的每個定義應該由相同的令牌序列組成;和' –

回答

3

這是一個ODR違規。 Foo類型在每個文件中有不同的聲明。

一個定義表示x被與外部連接聲明(可以是任何東西,連接時所確定的)和其他,這是一個編譯時通過恆定值2.

+0

這不是由N3376 [class.static.data] p1允許的嗎? >靜態數據成員不是類的子對象的一部分。 – Szm

+0

@Szm:'Foo :: x'存在違反ODR的情況,現在你可能會認爲'class Foo'沒問題,只有靜態部分是有問題的,但無論如何這個程序是不合格的。 – Jarod42

+0

@szm子對象在這裏沒有關係。我已經擴大了答案。 – Macke

相關問題