Reid Kleckner | 0902a51 | 2014-07-10 23:44:52 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -Wmicrosoft -fms-compatibility -verify |
| 2 | // RUN: not %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -Wmicrosoft -fms-compatibility -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s |
| 3 | |
| 4 | struct X; |
| 5 | namespace name_at_tu_scope { |
| 6 | struct Y { |
| 7 | friend struct X; // expected-warning-re {{unqualified friend declaration {{.*}} is a Microsoft extension}} |
| 8 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"::" |
| 9 | }; |
| 10 | } |
| 11 | |
| 12 | namespace enclosing_friend_decl { |
| 13 | struct B; |
| 14 | namespace ns { |
| 15 | struct A { |
| 16 | friend struct B; // expected-warning-re {{unqualified friend declaration {{.*}} is a Microsoft extension}} |
| 17 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"enclosing_friend_decl::" |
| 18 | protected: |
| 19 | A(); |
| 20 | }; |
| 21 | } |
| 22 | struct B { |
| 23 | static void f() { ns::A x; } |
| 24 | }; |
| 25 | } |
| 26 | |
| 27 | namespace enclosing_friend_qualified { |
| 28 | struct B; |
| 29 | namespace ns { |
| 30 | struct A { |
| 31 | friend struct enclosing_friend_qualified::B; // Adding name specifiers fixes it. |
| 32 | protected: |
| 33 | A(); |
| 34 | }; |
| 35 | } |
| 36 | struct B { |
| 37 | static void f() { ns::A x; } |
| 38 | }; |
| 39 | } |
| 40 | |
| 41 | namespace enclosing_friend_no_tag { |
| 42 | struct B; |
| 43 | namespace ns { |
| 44 | struct A { |
| 45 | friend B; // Removing the tag decl fixes it. |
| 46 | protected: |
| 47 | A(); |
| 48 | }; |
| 49 | } |
| 50 | struct B { |
| 51 | static void f() { ns::A x; } |
| 52 | }; |
| 53 | } |
| 54 | |
| 55 | namespace enclosing_friend_func { |
| 56 | void f(); |
| 57 | namespace ns { |
| 58 | struct A { |
| 59 | // Amusingly, in MSVC, this declares ns::f(), and doesn't find the outer f(). |
| 60 | friend void f(); |
| 61 | protected: |
| 62 | A(); // expected-note {{declared protected here}} |
| 63 | }; |
| 64 | } |
| 65 | void f() { ns::A x; } // expected-error {{calling a protected constructor of class 'enclosing_friend_func::ns::A'}} |
| 66 | } |
| 67 | |
| 68 | namespace test_nns_fixit_hint { |
| 69 | namespace name1 { |
| 70 | namespace name2 { |
| 71 | struct X; |
| 72 | struct name2; |
| 73 | namespace name3 { |
| 74 | struct Y { |
| 75 | friend struct X; // expected-warning-re {{unqualified friend declaration {{.*}} is a Microsoft extension}} |
| 76 | // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"name1::name2::" |
| 77 | }; |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | // A friend declaration injects a forward declaration into the nearest enclosing |
| 84 | // non-member scope. |
| 85 | namespace friend_as_a_forward_decl { |
| 86 | |
| 87 | class A { |
| 88 | class Nested { |
| 89 | friend class B; |
| 90 | B *b; |
| 91 | }; |
| 92 | B *b; |
| 93 | }; |
| 94 | B *global_b; |
| 95 | |
| 96 | void f() { |
| 97 | class Local { |
| 98 | friend class Z; |
| 99 | Z *b; |
| 100 | }; |
| 101 | Z *b; |
| 102 | } |
| 103 | |
| 104 | } |