2016-12-29 14 views
1

インテルスレッディングビルディングブロックを使用してCUDAコードをコンパイルしようとしているうちに、nvccのバグだと思っていました。 フレンドサブクラスのベースからプライベートメソッドを使用する - NVCCのコンパイラのバグ?

class Sub; 
class Other; 

namespace internal { 
    class Base 
    { 
    private: 
    friend class ::Sub; 

    static void foo(::Sub& b); 
    static void foo(::Other& c); 
    }; 
} 

class Sub : private internal::Base 
{ 
public: 
    using internal::Base::foo; 
}; 

void internal::Base::foo(Sub& b) 
{ 
} 

int main(int argc, char *argv[]) 
{ 
    Sub *b; 
    b->foo(*b); 
    // Sub::foo(*b); 

    return 0; 
} 
しかし、私は

nvcc -x cu -arch=sm_35 -c minimal.cc 

を使用して、同じホストコンパイラと組み合わせるnvcc 8.0でコンパイルした場合、私は、次の興味深いのエラーを取得:次の最小限の例では、g++ 5.4を用いて微細なコンパイル

../minimal.cc: In function ‘int main(int, char**)’: 
../minimal.cc:28:21: error: ‘internal::Base’ is an inaccessible base of ‘Sub’ 

Baseをから移動した場合、若干記述的なエラーが発生します3210名前空間とグローバルネームスペースの中へ:

../minimal.cc: In function ‘int main(int, char**)’: 
../minimal.cc:6:12: error: ‘class Base Base::Base’ is inaccessible 
    class Base 
      ^
../minimal.cc:32:5: error: within this context 
    b->foo(*b); 
    ^
../minimal.cc:32:11: error: ‘Base’ is an inaccessible base of ‘Sub’ 
    b->foo(*b); 

明らかに、このポインタを使用して静的メソッドを呼び出すの幾分非標準的な方法によるものと思われ、その行がコメントアウトつによって置換されている場合、それはうまくコンパイルされます。

これは有効なC++なので、nvccのバグか、またはg++が何となくうれしく受け入れている無効なC++のバグを誰かが確認できますか?

+1

これは再生できません。投稿したコードは完全にコンパイルされています。ただし、表示されたエラーメッセージは、投稿したコードをコンパイルすることによって生成されたものではないため、説明できない矛盾が発生する可能性があります。正確なコード、コンパイルコマンド、およびエラーメッセージで質問を更新できますか? – talonmies

+0

@talonmies、正確なコードが与えられ、正確なエラーメッセージも与えられ、正確なコンパイルコマンドは 'nvcc -c -arch = sm_35 file.cu'です。前述のように、私はnvcc 8.0とg ++ 5.4を持っています。私はUbuntuを使用しています。16.04 – kalj

+1

あなたが表示したエラーは31行目に報告されています。投稿したコードの 'return 0'です。あなたの質問では、 '.cc'ファイル拡張子を持つファイルにエラーが報告されていることを示し、コメントに投稿したばかりのコンパイルコマンドは' .cu'拡張子のファイルをコンパイルしています。 nvccは、これら2つのケースを異なる方法で処理します。私が言ったように、あなたは一致し、私が再現できるコードとエラーを表示していません。 – talonmies

答えて

2

これをもう少し掘り下げて、それが実際にnvccコンパイルの段階の1つに問題があることがわかりました。 --save-tempsを使用し、そして得られた.cu.cpp.iiファイルをチェックアウトし、それがこのライン

b->foo(*b); 

これは、g++でコンパイルされません、次の

(b->internal::Base::foo(*b)); 

によって置換されることを判明fooがあることを、その後事実以来Subで一般公開されています。結局のところ、これは明示的にそれがprivateである基底クラスからアクセスしようとします。他の種類の呼び出し(Sub::foo)を使用しても、余分なコードは生成されません。

私はこれがnvccのバグだと判断しました。この置換がでないのは興味深いことですが、Baseに2番目のオーバーロードされたvoid foo(::Other &c)が宣言されていない場合、は発生しません。

関連する問題