LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 11856 - Bad diagnostic when member reference collides with global template function
Summary: Bad diagnostic when member reference collides with global template function
Status: RESOLVED FIXED
Alias: None
Product: clang
Classification: Unclassified
Component: C++ (show other bugs)
Version: trunk
Hardware: PC All
: P enhancement
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-25 15:36 PST by Jeffrey Yasskin
Modified: 2012-03-10 18:48 PST (History)
4 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jeffrey Yasskin 2012-01-25 15:36:01 PST
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<typename T> T end(T);

template <typename T>
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.
Comment 1 Richard Smith 2012-01-25 16:33:50 PST
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.
Comment 2 Douglas Gregor 2012-03-10 17:53:33 PST
(In reply to comment #1)
> 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.
Comment 3 Johannes Schaub 2012-03-10 18:24:55 PST
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.
Comment 4 Johannes Schaub 2012-03-10 18:48:52 PST
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