2017-08-26 58 views
2

我正在使用內置CDT 9.3.0的Oxygen。使用_Generic關鍵字的Eclipse的CDT語法錯誤

當我使用我定義的使用_Generic的宏時,所有這些宏用法都帶有「語法錯誤」的下劃線,但項目編譯正常(設置爲使用我的makefile)。

在閱讀similar這樣的問題之後,由於_Generic從C11開始可能不被eclipse的代碼分析支持,我試着爲我的宏定義定義一個符號來清空它,但它不起作用。 (在項目設置中,C/C++常規 - >路徑和符號 - >符號選項卡,GNU C,添加了符號CONVERT(...)而沒有值並添加了符號CONVERT(X),並且CONVERT()和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的「智能感知」尚不支持它。 –

回答

2

由於@ErikW指出,_Generic是C11功能,它的Eclipse CDT的解析器尚不支持。 This bug跟蹤添加對它的支持。

(順便說一句,contributions到Eclipse CDT的C11支持是非常歡迎!)


它可以解決此使用宏。

試圖在「路徑和符號」中定義CONVERT(...)宏的另一個版本的問題是,在那裏定義的宏被視爲您將它們寫在文件的最頂端。隨後在實際代碼中重新定義將覆蓋「路徑和符號」中的定義。

我能想到的兩種方法去了解這一點:


方法1

CDT定義了一個特殊的宏__CDT_PARSER__時,它的解析代碼,計算結果爲真實的,但假的當代碼實際上是編譯的。

你可以利用這種方法來定義不同版本的CONVERT(...)對CDT的目的:

#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將工作:

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

方法2

而不是定義不同版本的CONVERT(...)的,我們可以定義_Generic(...)本身成爲CDT的目的宏。

這一次,我們可以在「路徑和符號」中做到這一點,因爲在代碼中沒有對_Generic(...)進行重新定義。

所以,讓我們定義一個符號「路徑和符號」,以_Generic(...)的名稱和空值。

現在,這條線:

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

將擴大到:

void* test = _Generic((FIRST("testme", 42)), \ 
        char*  : toText, \ 
        int   : toInt, \ 
        ) ("testme", 42) 

這將反過來擴大到:

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

,它解析(("testme", 42)解析爲一個括號逗號-expression,因此是一個有效的初始化)。

此方法的優點是不需要修改實際代碼,並且它可以處理_Generic宏的所有用法,而不僅僅是CONVERT中的那個。

另一方面,對於_Generic宏的其他用途,這種特殊擴展可能不會被解析。如果是這樣的話,你也許可以想出一個不同的擴展,將分析各種用途,否則你可以用接近1