New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bad diagnostic when member reference collides with global template function #12228
Comments
clang, gcc and edg all agree that "it1->end <" starts a template-id. Is it possible they're all wrong? After the "it1->", we're expecting an id-expression (that is, either an unqualified-id or a qualified-id). Now... [basic.lookup.classref]p2 says: "If the id-expression in a class member access (5.2.5) is an unqualified-id, and the type of the object expression is of a class type C, the unqualified-id is looked up in the scope of class C." So in the unqualified-id case, we can't find a template-id unless it's a member of the class. (In the case where the object expression is of a non-class type, the id-expression is required to name a pseudo-dtor, so that is irrelevant here.) If the name is a qualified-id, then we are parsing a class-name-or-namespace-name before a ::. [basic.lookup.qual]p1 says: "The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a :: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the So this lookup should not find a function template. |
EDG 4.3, at least, does not assume that "it1->end <" starts a template-id. The paragraph that matters here is [basic.lookup.classref]p1: Since "it1" is dependent, presumably the identifier is not found so we consider what happens if we look in the context of the entire postfix-expression. Since we find a function template, we should not conclude that we have the start of a template-id. Fixed in Clang r152520. |
Does 14.2p4 for the dependent case not imply that if we don't say "it1->template end", we shall treat "end" as a non-template and hence we shall treat the "<" as less-than? So even if "::end" would have been a class template, it looks to me that clang should not treat "it1->end <" as the start of a template argument list. |
I see now where the problem is... one wants to be able to say
I suspect that it first consideres the context of the postfix-expression (the object expression is dependent, so it cannot be looked into...) and if it finds a class template, it takes that meaning and continues parsing the qualified-id. If it finds nothing, only then it takes the rules of 14.2p4. And if the user types "it-> template T<Params", it treats it as a member template "T" and doesn't look into the context of the postfix-expression (because the "->" is not "immediately followed" by an identifier). Sorry for the noise! xD |
Extended Description
In the following program, Foo() is trying to use a public member variable of "*it1". Because there's a global template with the same name, it interprets the subsequent '<' as starting a template instantiation, and then finds trouble many tokens later when there's no matching '>'.
$ cat test.ii
template T end(T);
template
void Foo() {
T it1;
if (it1->end < it1->end) {
}
}
$ clang -fsyntax-only test.ii
test.ii:6:26: error: expected '>'
if (it1->end < it1->end)
^
test.ii:6:26: error: expected unqualified-id
2 errors generated.
$
The error should at least mention the template it was trying to find a parameter for.
A possible fixit is to add parentheses around "it1->end".
This will come up more often in C++11, where there's a std::end<>() that lots of people will 'using' into their global namespaces.
The text was updated successfully, but these errors were encountered: