_Atomic类型说明和限定的C11语法歧义 [英] C11 grammar ambiguity between _Atomic type specifier and qualifier

查看:685
本文介绍了_Atomic类型说明和限定的C11语法歧义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试着编写基于关闭N1570为C11类lex / yacc语法。我的大部分语法是从信息的语法摘要逐字复制,但是有些矛盾YACC出现。我已经成功地解决所有的人除了一个:似乎有当'_Atomic作为类型说明符,当它作为一个类型修饰符之间的一些模糊

在说明的形式,_Atomic立即用括号后面,所以我假定它有事情做用C的很少使用的语法,这使得说明符是在括号中,从而使括号紧跟在预选赛。但我的语法已经知道如何区别于其他标识符typedef名称,所以YACC应该知道其中的差别,不应该吗?

我不能为我的生活想象的情况时,它实际上是不明确的。

我怀疑这会有所帮助,但这里的国家相关的输出,我得到当我使用YACC的-v标志。 原子显然是我的令牌名为_Atomic

  23的状态  152 atomic_type_specifier:ATOMIC。 '('TYPE_NAME')'
  156 type_qualifier:ATOMIC。    (转变,进入状态49    ([减少使用规则156(type_qualifier)
    $默认使用减少156规则(type_qualifier)


解决方案

是的,我认为有歧义的规范。以

  _Atomic INT(* F)(INT);

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

  INT _Atomic(* F)(INT);

通常键入限定符可以来后 INT 这应该是等同于其他声明。但现在 _Atomic 后面括号,所以它的必须的是PTED作为一个类型说明符,然后是一个语法错误间$ P $。我认为它甚至有可能编造一个例子,其中 *˚F可能是一个有效的的typedef 更换。

看一看的6.7.2.4 P4前半句


  

具有原子类型相关的属性是仅用于有意义
  前pressions是左值。


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

编辑:

会发生对相同的歧义

  _Atomic INT(* A)[3];

这非常有意义(指针三个原子整数数组),并且我们应能改写为

  INT _Atomic(* A)[3];

编辑2::要看到,具有括号一类的标准,是不是歧义采取以下有效的C99 code:

 的typedef INT TOTO;诠释主要(无效){
  const int的TOTO(无效);
  INT常量TOTO(无效);
  const int的(TOTO)(无效);
  INT常量(TOTO)(无效);
  返回TOTO();
}

这redeclares TOTO 作为函数。和所有的四行是相同功能的有效原型。现在使用 _Atomic 作为限定符

 的typedef INT TOTO;诠释主要(无效){
  INT _Atomic(TOTO)(无效);
  返回TOTO();
}

这应该是有效的,与常量的版本。现在,我们这里的地方后面括号与一类里面 _Atomic 的情况下,却不失它是不是一个类型说明符。

I'm trying to write a lex/yacc grammar for C11 based off of N1570. Most of my grammar is copied verbatim from the informative syntax summary, but some yacc conflicts arose. I've managed to resolve all of them except for one: there seems to be some ambiguity between when '_Atomic' is used as a type specifier and when it's used as a type qualifier.

In the specifier form, _Atomic is followed immediately by parentheses, so I'm assuming it has something to do with C's little-used syntax which allows declarators to be in parentheses, thus allowing parentheses to immediately follow a qualifier. But my grammar already knows how to differentiate typedef names from other identifiers, so yacc should know the difference, shouldn't it?

I can't for the life of me think of a case when it would actually be ambiguous.

I doubt it helps, but here's the relevant state output I get when I use yacc's -v flag. "ATOMIC" is obviously my token name for "_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)

解决方案

Yes, I think there is ambiguity in the specification. Take

_Atomic int (*f)(int);

here the _Atomic is a type-qualifier. (As return type of a function it makes not much sense, but is valid, I think). Now take this alternative form

int _Atomic (*f)(int);

normally type-qualifiers can come after the int and this should be equivalent to the other declaration. But now _Atomic is followed by parenthesis, so it must be interpreted as a type-specifier which then is a syntax error. I think it would even be possible to cook up an example where *f could be replace by a valid typedef.

Have a look at the first phrase of 6.7.2.4 p4

The properties associated with atomic types are meaningful only for expressions that are lvalues.

This clearly indicates that they don't expect return types of functions to be _Atomic qualified.

Edit:

The same ambiguity would occur for

_Atomic int (*A)[3];

which makes perfect sense (a pointer to an array of three atomic integers) and which we should be able to rewrite as

int _Atomic (*A)[3];

Edit 2: To see that the criteria of having a type in the parenthesis is not disambiguating take the following valid C99 code:

typedef int toto;

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

This redeclares toto inside main as a function. And all four lines are valid prototypes for the same function. Now use the _Atomic as a qualifier

typedef int toto;

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

this should be valid as the version with const. Now we have here a case where _Atomic is followed by parenthesis with a type inside, but yet it is not a type-specifier.

这篇关于_Atomic类型说明和限定的C11语法歧义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆