diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-02-15 21:53:07 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-02-15 21:53:07 +0000 |
commit | afcfb6bc3a92c494bce8000651df8da7476d25f8 (patch) | |
tree | 62b002698ce995e648e68afe516db3ccffc51937 /clang/test | |
parent | 9982ee5472f87059cee75146293d0742f95bacc8 (diff) | |
download | bcm5719-llvm-afcfb6bc3a92c494bce8000651df8da7476d25f8.tar.gz bcm5719-llvm-afcfb6bc3a92c494bce8000651df8da7476d25f8.zip |
Fix implementation of [temp.local]p4.
When a template-name is looked up, we need to give injected-class-name
declarations of class templates special treatment, as they denote a
template rather than a type.
Previously we achieved this by applying a filter to the lookup results
after completing name lookup, but that is incorrect in various ways, not
least of which is that it lost all information about access and how
members were named, and the filtering caused us to generally lose
all ambiguity errors between templates and non-templates.
We now preserve the lookup results exactly, and the few places that need
to map from a declaration found by name lookup into a declaration of a
template do so explicitly. Deduplication of repeated lookup results of
the same injected-class-name declaration is done by name lookup instead
of after the fact.
This reinstates r354091, which was previously reverted in r354097
because it exposed bugs in lldb and compiler-rt. Those bugs were fixed
in r354173 and r354174 respectively.
llvm-svn: 354176
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CXX/class.access/p4.cpp | 10 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp | 6 | ||||
-rw-r--r-- | clang/test/SemaTemplate/temp.cpp | 39 |
3 files changed, 41 insertions, 14 deletions
diff --git a/clang/test/CXX/class.access/p4.cpp b/clang/test/CXX/class.access/p4.cpp index 6d452d8199e..a2d0da1a832 100644 --- a/clang/test/CXX/class.access/p4.cpp +++ b/clang/test/CXX/class.access/p4.cpp @@ -514,16 +514,12 @@ namespace test17 { } namespace test18 { - template <class T> class A {}; - class B : A<int> { + template <class T> class A {}; // expected-note {{member is declared here}} + class B : A<int> { // expected-note {{constrained by implicitly private inheritance here}} A<int> member; }; - - // FIXME: this access to A should be forbidden (because C++ is dumb), - // but LookupResult can't express the necessary information to do - // the check, so we aggressively suppress access control. class C : B { - A<int> member; + A<int> member; // expected-error {{'A' is a private member of 'test18::A<int>'}} }; } diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp index 849728a448b..ab1b9f7a73e 100644 --- a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -380,10 +380,10 @@ template <class T> struct A { namespace test18 { namespace ns1 { template <class T> struct foo {}; } // expected-note{{candidate ignored: not a function template}} namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}} -using ns1::foo; -using ns2::foo; +using ns1::foo; // expected-note {{found by name lookup}} +using ns2::foo; // expected-note {{found by name lookup}} template <class T> class A { - friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}} + friend void foo<T>() {} // expected-error {{ambiguous}} expected-error{{no candidate function template was found for dependent friend function template specialization}} }; } diff --git a/clang/test/SemaTemplate/temp.cpp b/clang/test/SemaTemplate/temp.cpp index e037f0f0713..a8a2daeac31 100644 --- a/clang/test/SemaTemplate/temp.cpp +++ b/clang/test/SemaTemplate/temp.cpp @@ -8,12 +8,43 @@ namespace test0 { // PR7252 namespace test1 { - namespace A { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}} + namespace A { template<typename T> struct Base { typedef T t; }; } // expected-note 3{{member}} namespace B { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}} template<typename T> struct Derived : A::Base<char>, B::Base<int> { - // FIXME: the syntax error here is unfortunate - typename Derived::Base<float>::t x; // expected-error {{found in multiple base classes of different types}} \ - // expected-error {{expected member name or ';'}} + typename Derived::Base<float>::t x; // expected-error {{found in multiple base classes of different types}} }; + + class X : A::Base<int> {}; // expected-note 2{{private}} + class Y : A::Base<float> {}; + struct Z : A::Base<double> {}; + struct Use1 : X, Y { + Base<double> b1; // expected-error {{private}} + Use1::Base<double> b2; // expected-error {{private}} + }; + struct Use2 : Z, Y { + Base<double> b1; + Use2::Base<double> b2; + }; + struct Use3 : X, Z { + Base<double> b1; + Use3::Base<double> b2; + }; +} + +namespace test2 { + struct A { static int x; }; // expected-note 4{{member}} + struct B { template<typename T> static T x(); }; // expected-note 4{{member}} + struct C { template<typename T> struct x {}; }; // expected-note 3{{member}} + struct D { template<typename T> static T x(); }; // expected-note {{member}} + + template<typename ...T> struct X : T... {}; + + void f() { + X<A, B>::x<int>(); // expected-error {{found in multiple base classes of different types}} + X<A, C>::x<int>(); // expected-error {{found in multiple base classes of different types}} + X<B, C>::x<int>(); // expected-error {{found in multiple base classes of different types}} + X<A, B, C>::x<int>(); // expected-error {{found in multiple base classes of different types}} + X<A, B, D>::x<int>(); // expected-error {{found in multiple base classes of different types}} + } } |