On 01/30/2018 03:42 PM, Manfred wrote:
> On 1/30/2018 5:51 PM, James R. Kuyper wrote:
>> On 01/30/2018 10:01 AM, James R. Kuyper wrote:
>>> On 01/30/2018 09:16 AM, Stefan Ram wrote:
>>>> I have a version of GCC here that is not too old and does not
>>>> give an error message for the code below.
>>>>
>>>> void f(){}
>>>
>>> This declaration has file scope.
>>>
>>>> //int f();
>>>
>>> "Function declarations that differ only in the return type, the
>>> exception specification (18.4), or both cannot be overloaded." (16.1p2).
>>> "A program is ill-formed if it contains two such non-overloadable
>>> declarations in the same scope." (16.1p1).
>>>
>>>> int main() { int f(); }
>>>
>>> This declaration has block scope, therefore 16.1p1 doesn't apply. Inside
>>> the scope of this declaration, it hides the file scope declaration.
>>> However, 16.1p2 should still apply - it isn't permitted for a function
>>> matching this declaration to be defined in the same program as the first
>>> definition of f() above. It seems to me that this should qualify as a
>>> diagnosable rule, and therefore one that must result in a diagnostic
>>> (4.1p2), but gcc apparently disagrees with me about that.
>
> (you are probably referring to a different version of the standard than
> n4618)
I'm using n4659.pdf, dated 2-17-03-21.
> n4618 3.4p1 says: "Overload resolution(13.3) takes place after name
> lookup has succeeded"
That's 6.4p1 in n4659.pdf, and the cross-reference is to 16.3 rather
than 13.3. The words are the same, however.
> ... so there appears to be a precedence of name hiding
> (3.3.10) over overload resolution, or at least this is how I understand it.
Overload resolution doesn't come into play in this version of the code,
since it contains no calls to any function. My version down below does
call f(), and name hiding does determine that it should use the
declaration of f() with a return type of 'int', so overload resolution
still ends up with no role to play in this code. However, this code
contains no definition for any function that matches that declaration.
The very existence of overloads that differ only by their return type is
prohibited by 16.1p2, regardless of hiding or overload resolution.
Therefore, it is not permitted for there to be any actual function named
f() which is compatible with the block-scope declaration of f().
>>> I modified f() to print some output, and modified main() to print the
>>> value returned by f() - both printouts worked. The returned value was
>>> 6295680.
>
> Interesting experiment; the way I understand this is that this happens
> because of 2 step program generation: /compilation/ succeeds (because of
> the above), and then /linking/ succeeds too by finding 'void f()' as a
> match for 'int f()', which is weird [*].
> In fact the same result of yours happens if 'void f()' is moved to a
> separate compilation unit (where there would be no question of overload
> resolution).
The key point is
"Two names that are the same (Clause 6) and that are declared in
different scopes shall denote the same variable, function, type,
template or namespace if
— both names have external linkage or ..." (6.5p9)
The definition of f() and the block scope declaration of f() are both
declarations of the same name, which has external linkage.
and "... the types specified by all declarations referring to a given
variable or function shall be identical... A violation of this rule on
type identity does not require a diagnostic." (6.5p10)
...