https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121563
--- Comment #14 from Christopher Bazley <Chris.Bazley at arm dot com> --- (In reply to Harald van Dijk from comment #12) > (In reply to Christopher Bazley from comment #11) > > It includes the following new argument against permitting > > duplicate forward declarations (which may or may not be persuasive to the > > reader). > > That isn't persuasive to me, no. It's not clear to me whether you read the relevant part of the paper, or only the words that I selectively quoted (which is my fault). The wider context is that "the redeclaration semantics of the C language already vary depending on the context in which a declaration appears". (In other words, an argument in favour of permitting duplicate forward declarations, because they appear in the context of a parameter-forward-declaration-list.) > > > Declarations that are valid at file scope are invalid in function scope: > > > > int x, x; // valid > > void f() > > { > > int x, x; // invalid > > } > > That is a bit misleading. It is potentially misleading that the two declarations above use the same derivation rule in the syntax but have different semantics. Nevertheless, both are declarations, as I wrote. Parameter forward declarations do not use the same derivation rule as ordinary declarations, but they use the same derivation rule as parameter declarations (and are indistinguishable from them). "When existing syntax is given new semantics, it inevitably looks wrong (regardless of whether it is subjectively ugly or not) if those semantics contradict user expectations" (from my paper). If file-scope declarations didn't exist and someone invented them with the same syntax as function-scope declarations but different semantics then I think that would be confusing. I also think that "int x, x" looks wrong because function-scope declarations are more common than file-scope declarations. > Multiple declarations are valid in file scope and > in function scope, so long as they are not definitions. It's just that your > function scope example is a definition, whereas your file scope example is > only a declaration (also a tentative definition, but that is not itself a > definition). If we change it so that we have a non-definition and a > definition at file scope, and a non-definition and a definition at function > scope, we get a better comparison. > > int x, x; // declaration, okay > int x = 1, x = 1; // multiple definition, error > > void f() { > extern int x, x; // declaration, okay > int x, x; // multiple definition, error > } Of course, but you have modified the declarations in such a way that they no longer resemble one another. If the syntax of parameter forward declarations required a storage-class specifier like 'extern' then there would be no ambiguity about whether they are definitions or not. > > The main precedent for forward parameter declarations is tentative > > definitions at file scope, > > Multiple non-defining declarations being valid is the general rule, > tentative definitions are not a special exception. > > typedef int x, x; // okay As you noted, "a typedef name can be redefined to denote the same type as it currently does, provided that type is not a variably modified type" (from the ISO standard). I don't think the fact this is called a definition rather than a declaration is relevant though. > void f(), f(); // okay "If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern" (from the ISO standard). So, the only reason this could be mistaken for a defining declaration is the fact that a storage-class specifier is implicit. In any case, I think there is little danger of either of the declarations that you gave as examples being interpreted as definitions. That is why I believe the situation is different from the situation with parameter declarations. > > If the above declaration were allowed in function scope, it would be > > ambiguous because it could be interpreted either as one declaration > > shadowing another or as a redeclaration. Duplicate forward parameter > > declarations are similarly ambiguous. > > They aren't. Because forward parameter declarations are never definitions, > there is no ambiguity. As far as I could tell from its source code, GCC provisionally treats parameter forward declarations as definitions, similar to how tentative definitions are provisionally treated as definitions. Have I misread the code, or is your opinion based on the intended semantics of GCC's extension? GCC's manual doesn't say anything about whether or not parameter forward declarations are definitions. I don't think the ISO C23 standard explicitly describes parameter declarations as definitions either; it just says "Each parameter has automatic storage duration; its identifier, if any, is an lvalue." The C99 standard instead says "Each parameter has automatic storage duration. Its identifier is an lvalue, which is in effect declared at the head of the compound statement that constitutes the function body (and therefore cannot be redeclared in the function body except in an enclosed block)." I suppose one could deduce that an identifier that is "..in effect declared at the head of the compound statement that constitutes the function body.." is probably a definition (although not all such declarations are definitions, as you rightly pointed out). > The only reason forward parameter declarations are a special case is that we > do not know yet at the end of the declarator whether the containing > parameter-list is part of (to use your names) a parameter-declaration is > part of a parameter-forward-declaration-list or of a parameter-type-list, we > have to continue parsing until we reach the end of the parameter-declaration > to make that determination. That may be justifiable as you and Alejandro > also wrote for simplicity of implementation, but it should not be presented > as anything more than that, in my opinion. Do you have any specific concerns about the proposed wording changes in https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3681.pdf ?