问题 _Atomic类型说明符和限定符之间的C11语法歧义


我正在尝试根据N1570编写C11的lex / yacc语法。我的大部分语法都是从信息性语法摘要中逐字复制的,但是出现了一些yacc冲突。我设法解决了除了一个之外的所有问题:当'_Atomic'用作类型说明符和用作类型限定符时,似乎存在一些歧义。

在说明符形式中,_Atomic紧跟着括号,所以我假设它与C的很少使用的语法有关,它允许声明符在括号中,从而允许括号立即跟随限定符。但我的语法已经知道如何区分typedef名称和其他标识符,所以yacc应该知道差异,不应该吗?

我不能为我的生活想到一个实际上是模棱两可的案例。

我怀疑它有帮助,但这是我使用yacc的-v标志时获得的相关状态输出。 “ATOMIC”显然是我的“_Atomic”的令牌名称

state 23

  152 atomic_type_specifier: ATOMIC . '(' type_name ')'
  156 type_qualifier: ATOMIC .

    '('  shift, and go to state 49

    '('       [reduce using rule 156 (type_qualifier)]
    $default  reduce using rule 156 (type_qualifier)

2826
2018-05-19 21:21


起源

区分语法中的说明符和限定符在很大程度上是不可启动的,因为声明可以按任何顺序混合说明符和限定符: const unsigned int, unsigned const int, int unsigned const,... - Kaz


答案:


是的,我认为规范中存在歧义。采取

_Atomic int (*f)(int);

在这里 _Atomic 是一个类型限定符。 (作为函数的返回类型,它没有多大意义,但我认为是有效的)。现在采取这种替代形式

int _Atomic (*f)(int);

通常类型限定符可以在之后 int 这应该等同于另一个声明。但现在 _Atomic 之后是括号,所以它 必须 被解释为类型说明符,然后是语法错误。我想甚至可以在其中做一个例子 *f 可以用有效的替代 typedef

看看6.7.2.4 p4的第一个短语

与原子类型相关的属性仅对于有意义   作为左值的表达式。

这清楚地表明他们不期望返回类型的函数 _Atomic 合格。

编辑:

会出现同样的歧义

_Atomic int (*A)[3];

这是完全合理的(指向三个原子整数数组的指针),我们应该能够重写为

int _Atomic (*A)[3];

编辑2: 要查看括号中的类型的标准不消除歧义,请使用以下有效的C99代码:

typedef int toto;

int main(void) {
  const int toto(void);
  int const toto(void);
  const int (toto)(void);
  int const (toto)(void);
  return toto();
}

这个重新声明 toto 内 main 作为一个功能。并且所有四行都是相同功能的有效原型。现在使用 _Atomic 作为资格赛

typedef int toto;

int main(void) {
  int _Atomic (toto)(void);
  return toto();
}

这应该是有效的版本 const。现在我们在这里有一个案例 _Atomic 后跟括号内部的类型,但它不是类型说明符。


7
2018-05-19 22:34



当你说,“但现在_Atomic后跟括号,所以它必须被解释为类型限定符”我假设你的意思是,“但现在_Atomic后面跟括号,所以它必须被解释为类型说明符”? - Michael Burr
那么,原子类型说明符规则要求括号中的类型名称,而不是声明符,所以我不认为 _Atomic(*anything) 带星号将是一个有效的原子类型说明符。但我最近在标准(6.7.2.4 - 4)中注意到了这一点: 如果_Atomic关键字后面紧跟左括号,则将其解释为类型说明符(具有类型名称),而不是类型限定符。 在这种情况下,永远不会有歧义。括号表示类型说明符,没有括号表示限定符,简单如此。现在以某种方式将该规则纳入我的语法...... - Jo Bates
@MichaelBurr,是的,谢谢,我会编辑它。 - Jens Gustedt
@JoBates,首先,我不是那样读的。对我来说它说那里 必须 是括号中的一个类型。其次,我认为消除歧义并不足够。我会尝试做一个例子。 - Jens Gustedt


好吧,无论我们是否能够提出语法模糊的情况都没关系。 N1570第6.7.2.4节第4段规定:

如果_Atomic关键字后面紧跟左括号,则将其解释为类型说明符(具有类型名称),而不是类型限定符。

为了强制执行此操作,我只是将_Atomic设置为说明符,将_Atomic设置为我的lex规则中的单独标记的限定符。

"_Atomic"/{WHITESPACE}*"(" {return ATOMIC_SPECIFIER;}
"_Atomic"                  {return ATOMIC_QUALIFIER;}

我对lex / yacc和解析器生成器一般都比较新,但我的直觉说这是一种黑客行为。同时,lex中的尾随上下文语法还有什么用呢?


9
2018-05-20 13:20



如果两者之间有评论,这将失败。 - o11c