2017-08-26 33 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