C11 grammar ambiguity between _Atomic type specifier and qualifier

拜拜、爱过 提交于 2019-11-29 09:35:59

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.

Okay, whether or not we can come up with a grammatically ambiguous case doesn't matter. Section 6.7.2.4 paragraph 4 of N1570 states that:

If the _Atomic keyword is immediately followed by a left parenthesis, it is interpreted as a type specifier (with a type name), not as a type qualifier.

To enforce this, I simply made _Atomic as a specifier and _Atomic as a qualifier separate tokens in my lex rules.

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

I'm relatively new to lex/yacc and parser generators in general, but my gut says this is kind of a hack. At the same time, what else would the trailing context syntax in lex be for?

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!