Navigation Menu

Skip to content
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

Closed
llvmbot opened this issue Jan 25, 2012 · 4 comments
Closed
Labels
bugzilla Issues migrated from bugzilla c++

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 25, 2012

Bugzilla Link 11856
Resolution FIXED
Resolved on Mar 10, 2012 18:48
Version trunk
OS All
Reporter LLVM Bugzilla Contributor
CC @DougGregor,@zygoloid,@RealLitb

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.

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Jan 26, 2012

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
name preceding that :: considers only namespaces, types, and templates whose specializations are types."

So this lookup should not find a function template.

@DougGregor
Copy link
Contributor

clang, gcc and edg all agree that "it1->end <" starts a template-id. Is it
possible they're all wrong?

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:
"In a class member access expression (5.2.5), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (14.2) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template."

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.

@RealLitb
Copy link
Mannequin

RealLitb mannequin commented Mar 11, 2012

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.

@RealLitb
Copy link
Mannequin

RealLitb mannequin commented Mar 11, 2012

I see now where the problem is... one wants to be able to say

it->T<Params>::~T();

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

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++
Projects
None yet
Development

No branches or pull requests

2 participants