Open elizabethandrews opened 1 year ago
@llvm/issue-subscribers-clang-frontend
The language in dcl.fct.default p9 has changed significantly, it was changed by the P1787 which contained a major set of changes to how we find names. It looks like this was possible part of DR 1907.
The new language says:
When an overload set contains a declaration of a function that inhabits a scope S, any default argument associated with any reachable declaration that inhabits S is available to the call. [Note 7: The candidate might have been found through a using-declarator from which the declaration that provides the default argument is not reachable. — end note]
Which I read a possibly agreeing with clang here but I am not totally sure if that was the intent, DR1907 muddies the waters quite a bit here.
CC @hubert-reinterpretcast please let me know what you think.
DR1907 muddies the waters quite a bit here.
The wording resolving DR 1907 was fairly straightforward (see N4928 [temp.res.general] paragraph 2).
CC @hubert-reinterpretcast please let me know what you think.
namespace N {
int f(int i, int j = 0) { return i + j + 10; }
}
namespace M {
using N::f;
}
namespace N {
int f(int i = 0, int j);
}
void foo() {
int a = N::f(); // Works
using M::f;
int b = f(); // Does not work
}
The using-declarator names the first declaration with a default argument, which inhabits the namespace scope of N. That named declaration is in the overload set. At the point of the call, the second declaration with a default argument is reachable and also inhabits the namespace scope of N. The case can be simplified by "physically" using M::f
in the call.
[Note 7: The candidate might have been found through a using-declarator from which the declaration that provides the default argument is not reachable. — end note]
I believe that the note is trying to highlight a case where the wording matters: later default arguments are available to the call despite being found through a using-declarator that did not "see" said default arguments (otherwise, the overload set include the later declarations as well).
See also core/2020/11/10210.
DR1907 muddies the waters quite a bit here.
The wording resolving DR 1907 was fairly straightforward (see N4928 [temp.res.general] paragraph 2).
Yeah, I think I was previously confused which case "determined that the case should be ill-formed" referred to, but after rereading it it is referring to the first code example and not the second.
So it looks like clang is wrong here.
Clang ignores function redeclaration which provides additional default arguments and throws diagnostic "error: no matching function for call" - https://godbolt.org/z/bnha5jEGG
The test passes if namespace M is defined after the function redeclaration - https://godbolt.org/z/c1qhWf7MP
Both cases should work.
Relevant C++ standard -
“When a declaration of a function is introduced by way of a using-declaration (7.3.3), any default argument information associated with the declaration is made known as well. If the function is redeclared thereafter in the namespace with additional default arguments, the additional arguments are also known at any point following the redeclaration where the using-declaration is in scope.”