summaryrefslogtreecommitdiffstats
path: root/test/CXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-01-07 06:00:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-01-07 06:00:46 +0000
commit02db2fa1a919655cb54a160131c3ca6a3fa215b5 (patch)
tree739cca0952f0b9344e93b1bc928cf57f2b900d39 /test/CXX
parent1a1eb1e55e1bccc461ae696bc445541f6fef3cd0 (diff)
DR674, PR38883, PR40238: Qualified friend lookup should look for a
template specialization if there is no matching non-template function. This exposed a couple of related bugs: - we would sometimes substitute into a friend template instead of a suitable non-friend declaration; this would now crash because we'd decide the specialization of the friend is a redeclaration of itself - ADL failed to properly handle the case where an invisible local extern declaration redeclares an invisible friend Both are fixed herein: in particular, we now never make invisible friends or local extern declarations visible to name lookup unless they are the only declaration of the entity. (We already mostly did this for local extern declarations.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@350505 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CXX')
-rw-r--r--test/CXX/class.access/class.friend/p1.cpp5
-rw-r--r--test/CXX/class.access/class.friend/p11.cpp11
-rw-r--r--test/CXX/class/class.friend/p1.cpp4
-rw-r--r--test/CXX/drs/dr1xx.cpp5
-rw-r--r--test/CXX/drs/dr5xx.cpp8
-rw-r--r--test/CXX/drs/dr6xx.cpp42
6 files changed, 48 insertions, 27 deletions
diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp
index b6a1bcdab9..b335b0a8c8 100644
--- a/test/CXX/class.access/class.friend/p1.cpp
+++ b/test/CXX/class.access/class.friend/p1.cpp
@@ -11,12 +11,11 @@
// friends members of the befriending class.
struct S { static void f(); }; // expected-note 2 {{'S' declared here}}
-S* g() { return 0; }
+S* g() { return 0; } // expected-note 2 {{'g' declared here}}
struct X {
friend struct S;
- friend S* g(); // expected-note 2 {{'g' declared here}}
- // FIXME: The above two notes would be better attached to line 11.
+ friend S* g();
};
void test1() {
diff --git a/test/CXX/class.access/class.friend/p11.cpp b/test/CXX/class.access/class.friend/p11.cpp
index 0d25c59c9b..0deead19a0 100644
--- a/test/CXX/class.access/class.friend/p11.cpp
+++ b/test/CXX/class.access/class.friend/p11.cpp
@@ -19,17 +19,16 @@ namespace test1 {
}
namespace test2 {
- void bar(); // expected-note {{'::test2::bar' declared here}}
+ void bar(); // expected-note 3{{'::test2::bar' declared here}}
- void foo() { // expected-note {{'::test2::foo' declared here}}
+ void foo() { // expected-note 2{{'::test2::foo' declared here}}
struct S1 {
friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}}
};
void foo(); // expected-note {{local declaration nearly matches}}
struct S2 {
- friend void foo(); // expected-note{{'::test2::foo' declared here}}
- // TODO: the above note should go on line 24
+ friend void foo();
};
{
@@ -47,8 +46,6 @@ namespace test2 {
struct S4 {
friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}}
- // expected-note@-1 {{'::test2::bar' declared here}}
- // TODO: the above note should go on line 22
};
{ void bar(); }
@@ -81,8 +78,6 @@ namespace test2 {
struct S9 {
struct Inner {
friend void baz(); // expected-error {{no matching function 'baz' found in local scope; did you mean 'bar'?}}
- // expected-note@-1 {{'::test2::bar' declared here}}
- // TODO: the above note should go on line 22
};
};
diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp
index 037fc3dadb..08498c0733 100644
--- a/test/CXX/class/class.friend/p1.cpp
+++ b/test/CXX/class/class.friend/p1.cpp
@@ -51,9 +51,9 @@ class A {
friend class A::AInner; // this is okay as an extension
friend class AInner; // okay, refers to ::AInner
- friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}}
+ friend void Derived::missing_member(); // expected-error {{friend declaration of 'missing_member' does not match any declaration in 'Derived'}}
- friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}}
+ friend void Derived::base_member(); // expected-error {{friend declaration of 'base_member' does not match any declaration in 'Derived'}}
friend int Base::typedeffed_member(); // okay: should look through typedef
diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp
index a92501128b..26ab67d54d 100644
--- a/test/CXX/drs/dr1xx.cpp
+++ b/test/CXX/drs/dr1xx.cpp
@@ -401,13 +401,12 @@ namespace dr136 { // dr136: 3.4
extern "C" void k(int, int, int, int); // expected-note {{previous declaration is here}}
namespace NSA {
struct A {
- friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}} \
- // expected-note {{previous declaration is here}}
+ friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
};
}
namespace NSB {
struct A {
- friend void dr136::k(int, int, int = 0, int); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+ friend void dr136::k(int, int, int = 0, int); // expected-error {{missing default argument on parameter}}
};
}
struct B {
diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp
index c20a873fc1..2099612e23 100644
--- a/test/CXX/drs/dr5xx.cpp
+++ b/test/CXX/drs/dr5xx.cpp
@@ -740,17 +740,17 @@ namespace dr573 { // dr573: no
namespace dr574 { // dr574: yes
struct A {
- A &operator=(const A&) const; // expected-note {{does not match because it is const}}
+ A &operator=(const A&) const; // expected-note {{different qualifiers}}
};
struct B {
- B &operator=(const B&) volatile; // expected-note {{nearly matches}}
+ B &operator=(const B&) volatile; // expected-note {{different qualifiers}}
};
#if __cplusplus >= 201103L
struct C {
- C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}}
+ C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}}
};
struct D {
- D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}}
+ D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}}
};
void test(C c, D d) {
c = c;
diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp
index f4eccfead2..b4247b2260 100644
--- a/test/CXX/drs/dr6xx.cpp
+++ b/test/CXX/drs/dr6xx.cpp
@@ -839,7 +839,7 @@ namespace dr673 { // dr673: yes
F *f; // expected-error {{unknown type name}}
}
-namespace dr674 { // dr674: no
+namespace dr674 { // dr674: 8
template<typename T> int f(T);
int g(int);
@@ -849,22 +849,50 @@ namespace dr674 { // dr674: no
template<typename T> int h(T);
class X {
- // FIXME: This should deduce dr674::f<int>.
- friend int dr674::f(int); // expected-error {{does not match any}}
+ friend int dr674::f(int);
friend int dr674::g(int);
friend int dr674::h<>(int);
- int n;
+ int n; // expected-note 2{{private}}
};
template<typename T> int f(T) { return X().n; }
int g(int) { return X().n; }
- template<typename T> int g(T) { return X().n; }
- int h(int) { return X().n; }
+ template<typename T> int g(T) { return X().n; } // expected-error {{private}}
+ int h(int) { return X().n; } // expected-error {{private}}
template<typename T> int h(T) { return X().n; }
template int f(int);
- template int g(int);
+ template int g(int); // expected-note {{in instantiation of}}
template int h(int);
+
+
+ struct Y {
+ template<typename T> int f(T);
+
+ int g(int);
+ template<typename T> int g(T);
+
+ int h(int);
+ template<typename T> int h(T);
+ };
+
+ class Z {
+ friend int Y::f(int);
+ friend int Y::g(int);
+ friend int Y::h<>(int);
+ int n; // expected-note 2{{private}}
+ };
+
+ template<typename T> int Y::f(T) { return Z().n; }
+ int Y::g(int) { return Z().n; }
+ template<typename T> int Y::g(T) { return Z().n; } // expected-error {{private}}
+ int Y::h(int) { return Z().n; } // expected-error {{private}}
+ template<typename T> int Y::h(T) { return Z().n; }
+
+ // FIXME: Should the <> be required here?
+ template int Y::f<>(int);
+ template int Y::g<>(int); // expected-note {{in instantiation of}}
+ template int Y::h<>(int);
}
namespace dr675 { // dr675: dup 739