2017-08-26 7 views
2

私はCDT 9.3.0ビルトインでOxygenを使用しています。_Genericキーワードを使用したマクロのEclipse CDT構文エラー

_Genericを使用して定義したマクロを使用すると、それらのマクロの使用にはすべて「構文エラー」が表示されますが、プロジェクトは正常にコンパイルされます(makefileを使用するように設定されています)。

similarの質問を読んだあと、_GenericはC11から始まる可能性があります(eclipseのコード解析ではサポートされていない可能性があります)。マクロ定義のシンボルを空にすることを試みましたが、動作しませんでした。 (プロジェクト設定では、C/C++ General-> Paths and Symbols-> Symbolsタブ、GNU C、値なしのシンボルCONVERT(...)を追加し、シンボルCONVERT(X)、CONVERT値)。私のマクロがある

例えば:

#define FIRST_(_1, ...) _1 
#define FIRST(...) FIRST_(__VA_ARGS__, _1, _2, _3) 

#define CONVERT(...)       \ 
       _Generic((FIRST(__VA_ARGS__)), \ 
        char*  : toText, \ 
        int   : toInt, \ 
        ) (__VA_ARGS__) 

と利用ポイント、それは構文エラーを与える:

void* test = CONVERT("testme"); 
+4

'_Generic'はC11標準のものです。私が知っていることから、Eclipseの "intellisense"はまだそれをサポートしていません。 –

答えて

2

として@ErikW_Genericは、Eclipse CDTのことをC11の機能で、指摘しましたパーサーはまだサポートしていません。 This bugトラックがそれをサポートしています。

(ちなみに、contributionsではCDTのC11サポートをEclipseに非常に歓迎されている!)


マクロを使用してこの問題を回避することが可能です。

"パスとシンボル"にCONVERT(...)マクロの別のバージョンを定義しようとすると、そこに定義されているマクロがファイルの最上部に書かれているように扱われるという問題があります。その後の実際のコードでの再定義は、「パスとシンボル」の定義を上書きします。

私はこれについて移動するための2つのアプローチを考えることができます。


アプローチ1

CDTは、それがコードを解析だときtrueと評価され、特別なマクロ__CDT_PARSER__を定義しますが、偽のときコードは実際にコンパイルされます。

あなたはCDTの目的のためにCONVERT(...)の異なるバージョンを定義するためにこれを利用することができます

#ifdef __CDT_PARSER__ 
    #define CONVERT(...) 
#else 
    #define CONVERT(...)       \ 
        _Generic((FIRST(__VA_ARGS__)), \ 
         char*  : toText, \ 
         int   : toInt, \ 
         ) (__VA_ARGS__) 
#endif 

これはほとんど作品が、非常にされていません。

void* test = CONVERT("testme", 42); 

今に展開されます:

void* test = ; 

あなたが見ることができるように、私たちは実際にCONVERT(...)ため、空の拡張を望んでいないこの行はので、私たちはまだ、構文エラーを取得します。変数の初期化子として解析される展開が必要です。0が動作します:代わりにCONVERT(...)の異なるバージョンを定義する

#ifdef __CDT_PARSER__ 
    #define CONVERT(...) 0 
#else 
    ... 
#endif 

アプローチ2

を、私たちは、CDTの目的のために、マクロであることを_Generic(...)自体を定義することができます。

今度は、「パスとシンボル」でこれを行うことができます。コード内に_Generic(...)という再定義が含まれていないためです。

シンボルを「パスとシンボル」に定義しましょう。名前は_Generic(...)、空の値にしてください。

さて、この行:

順次に拡大していきます
void* test = _Generic((FIRST("testme", 42)), \ 
        char*  : toText, \ 
        int   : toInt, \ 
        ) ("testme", 42) 

("testme", 42)は、括弧内のコンマとして解析し、解析し(
void* test = ("testme", 42); 

void* test = CONVERT("testme", 42); 

はに拡大します-expressionであり、したがって有効なイニシャライザです)。

このアプローチには、実際のコードを変更する必要がなく、CONVERTのマクロではなく_Genericマクロのすべての使用を処理するという利点があります。

一方、_Genericマクロの他の用途では、この特定の拡張は解析されない可能性があります。そうであれば、すべての用途のために解析する別の拡張を思いつくことができます。それ以外の場合は、アプローチ1に進むことができます。

関連する問題