1*d0d076feSFangrui Song // RUN: %clang_cc1 -fsyntax-only -verify %s
2*d0d076feSFangrui Song // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
3*d0d076feSFangrui Song // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
42f96e9f5SJeffrey Yasskin
52f96e9f5SJeffrey Yasskin // C++98 [basic.lookup.classref]p1:
62f96e9f5SJeffrey Yasskin // In a class member access expression (5.2.5), if the . or -> token is
72f96e9f5SJeffrey Yasskin // immediately followed by an identifier followed by a <, the identifier must
82f96e9f5SJeffrey Yasskin // be looked up to determine whether the < is the beginning of a template
92f96e9f5SJeffrey Yasskin // argument list (14.2) or a less-than operator. The identifier is first
102f96e9f5SJeffrey Yasskin // looked up in the class of the object expression. If the identifier is not
112f96e9f5SJeffrey Yasskin // found, it is then looked up in the context of the entire postfix-expression
122f96e9f5SJeffrey Yasskin // and shall name a class or function template. If the lookup in the class of
132f96e9f5SJeffrey Yasskin // the object expression finds a template, the name is also looked up in the
142f96e9f5SJeffrey Yasskin // context of the entire postfix-expression and
152f96e9f5SJeffrey Yasskin // -- if the name is not found, the name found in the class of the object
162f96e9f5SJeffrey Yasskin // expression is used, otherwise
172f96e9f5SJeffrey Yasskin // -- if the name is found in the context of the entire postfix-expression
182f96e9f5SJeffrey Yasskin // and does not name a class template, the name found in the class of the
192f96e9f5SJeffrey Yasskin // object expression is used, otherwise
202f96e9f5SJeffrey Yasskin // -- if the name found is a class template, it must refer to the same
212f96e9f5SJeffrey Yasskin // entity as the one found in the class of the object expression,
222f96e9f5SJeffrey Yasskin // otherwise the program is ill-formed.
232f96e9f5SJeffrey Yasskin
242f96e9f5SJeffrey Yasskin // From PR 7247
252f96e9f5SJeffrey Yasskin template<typename T>
261a88adbbSCharles Li struct set{};
271a88adbbSCharles Li #if __cplusplus <= 199711L
281a88adbbSCharles Li // expected-note@-2 {{lookup from the current scope refers here}}
291a88adbbSCharles Li #endif
302f96e9f5SJeffrey Yasskin struct Value {
312f96e9f5SJeffrey Yasskin template<typename T>
setValue321a88adbbSCharles Li void set(T value) {}
331a88adbbSCharles Li #if __cplusplus <= 199711L
341a88adbbSCharles Li // expected-note@-2 {{lookup in the object type 'Value' refers here}}
351a88adbbSCharles Li #endif
362f96e9f5SJeffrey Yasskin
resolves_to_sameValue372f96e9f5SJeffrey Yasskin void resolves_to_same() {
382f96e9f5SJeffrey Yasskin Value v;
392f96e9f5SJeffrey Yasskin v.set<double>(3.2);
402f96e9f5SJeffrey Yasskin }
412f96e9f5SJeffrey Yasskin };
resolves_to_different()422f96e9f5SJeffrey Yasskin void resolves_to_different() {
432f96e9f5SJeffrey Yasskin {
442f96e9f5SJeffrey Yasskin Value v;
452f96e9f5SJeffrey Yasskin // The fact that the next line is a warning rather than an error is an
462f96e9f5SJeffrey Yasskin // extension.
471a88adbbSCharles Li v.set<double>(3.2);
481a88adbbSCharles Li #if __cplusplus <= 199711L
491a88adbbSCharles Li // expected-warning@-2 {{lookup of 'set' in member access expression is ambiguous; using member of 'Value'}}
501a88adbbSCharles Li #endif
512f96e9f5SJeffrey Yasskin }
522f96e9f5SJeffrey Yasskin {
532f96e9f5SJeffrey Yasskin int set; // Non-template.
542f96e9f5SJeffrey Yasskin Value v;
552f96e9f5SJeffrey Yasskin v.set<double>(3.2);
562f96e9f5SJeffrey Yasskin }
572f96e9f5SJeffrey Yasskin }
58de0a43f7SDouglas Gregor
59de0a43f7SDouglas Gregor namespace rdar9915664 {
60de0a43f7SDouglas Gregor struct A {
61de0a43f7SDouglas Gregor template<typename T> void a();
62de0a43f7SDouglas Gregor };
63de0a43f7SDouglas Gregor
64de0a43f7SDouglas Gregor struct B : A { };
65de0a43f7SDouglas Gregor
66de0a43f7SDouglas Gregor struct C : A { };
67de0a43f7SDouglas Gregor
68de0a43f7SDouglas Gregor struct D : B, C {
getArdar9915664::D69de0a43f7SDouglas Gregor A &getA() { return static_cast<B&>(*this); }
70de0a43f7SDouglas Gregor
test_ardar9915664::D71de0a43f7SDouglas Gregor void test_a() {
72de0a43f7SDouglas Gregor getA().a<int>();
73de0a43f7SDouglas Gregor }
74de0a43f7SDouglas Gregor };
75de0a43f7SDouglas Gregor }
7650a3cdddSDouglas Gregor
7750a3cdddSDouglas Gregor namespace PR11856 {
7850a3cdddSDouglas Gregor template<typename T> T end(T);
7950a3cdddSDouglas Gregor
8050a3cdddSDouglas Gregor template <typename T>
Foo()8150a3cdddSDouglas Gregor void Foo() {
8250a3cdddSDouglas Gregor T it1;
8350a3cdddSDouglas Gregor if (it1->end < it1->end) {
8450a3cdddSDouglas Gregor }
8550a3cdddSDouglas Gregor }
8650a3cdddSDouglas Gregor
8750a3cdddSDouglas Gregor template<typename T> T *end(T*);
8850a3cdddSDouglas Gregor
8950a3cdddSDouglas Gregor class X { };
9050a3cdddSDouglas Gregor template <typename T>
Foo2()9150a3cdddSDouglas Gregor void Foo2() {
9250a3cdddSDouglas Gregor T it1;
9350a3cdddSDouglas Gregor if (it1->end < it1->end) {
9450a3cdddSDouglas Gregor }
9550a3cdddSDouglas Gregor
9650a3cdddSDouglas Gregor X *x;
9750a3cdddSDouglas Gregor if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}}
9850a3cdddSDouglas Gregor }
9950a3cdddSDouglas Gregor }
10050a3cdddSDouglas Gregor }
101