| // RUN: %clang_cc1 -std=c++20 -fsyntax-only %s -verify |
| |
| #define UIE __attribute__((using_if_exists)) |
| |
| namespace test_basic { |
| namespace NS {} |
| |
| using NS::x UIE; // expected-note{{using declaration annotated with 'using_if_exists' here}} |
| x usex(); // expected-error{{reference to unresolved using declaration}} |
| |
| using NotNS::x UIE; // expected-error{{use of undeclared identifier 'NotNS'}} |
| |
| using NS::NotNS::x UIE; // expected-error{{no member named 'NotNS' in namespace 'test_basic::NS'}} |
| } // namespace test_basic |
| |
| namespace test_redecl { |
| namespace NS {} |
| |
| using NS::x UIE; |
| using NS::x UIE; |
| |
| namespace NS1 {} |
| namespace NS2 {} |
| namespace NS3 { |
| int A(); // expected-note{{target of using declaration}} |
| struct B {}; // expected-note{{target of using declaration}} |
| int C(); // expected-note{{conflicting declaration}} |
| struct D {}; // expected-note{{conflicting declaration}} |
| } // namespace NS3 |
| |
| using NS1::A UIE; |
| using NS2::A UIE; // expected-note{{using declaration annotated with 'using_if_exists' here}} expected-note{{conflicting declaration}} |
| using NS3::A UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} |
| int i = A(); // expected-error{{reference to unresolved using declaration}} |
| |
| using NS1::B UIE; |
| using NS2::B UIE; // expected-note{{conflicting declaration}} expected-note{{using declaration annotated with 'using_if_exists' here}} |
| using NS3::B UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} |
| B myB; // expected-error{{reference to unresolved using declaration}} |
| |
| using NS3::C UIE; |
| using NS2::C UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}} |
| int j = C(); |
| |
| using NS3::D UIE; |
| using NS2::D UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}} |
| D myD; |
| } // namespace test_redecl |
| |
| namespace test_dependent { |
| template <class B> |
| struct S : B { |
| using B::mf UIE; // expected-note 3 {{using declaration annotated with 'using_if_exists' here}} |
| using typename B::mt UIE; // expected-note{{using declaration annotated with 'using_if_exists' here}} |
| }; |
| |
| struct BaseEmpty { |
| }; |
| struct BaseNonEmpty { |
| void mf(); |
| typedef int mt; |
| }; |
| |
| template <class Base> |
| struct UseCtor : Base { |
| using Base::Base UIE; // expected-error{{'using_if_exists' attribute cannot be applied to an inheriting constructor}} |
| }; |
| struct BaseCtor {}; |
| |
| void f() { |
| S<BaseEmpty> empty; |
| S<BaseNonEmpty> nonempty; |
| empty.mf(); // expected-error {{reference to unresolved using declaration}} |
| nonempty.mf(); |
| (&empty)->mf(); // expected-error {{reference to unresolved using declaration}} |
| (&nonempty)->mf(); |
| |
| S<BaseEmpty>::mt y; // expected-error {{reference to unresolved using declaration}} |
| S<BaseNonEmpty>::mt z; |
| |
| S<BaseEmpty>::mf(); // expected-error {{reference to unresolved using declaration}} |
| |
| UseCtor<BaseCtor> usector; |
| } |
| |
| template <class B> |
| struct Implicit : B { |
| using B::mf UIE; // expected-note {{using declaration annotated with 'using_if_exists' here}} |
| using typename B::mt UIE; // expected-note 2 {{using declaration annotated with 'using_if_exists' here}} |
| |
| void use() { |
| mf(); // expected-error {{reference to unresolved using declaration}} |
| mt x; // expected-error {{reference to unresolved using declaration}} |
| } |
| |
| mt alsoUse(); // expected-error {{reference to unresolved using declaration}} |
| }; |
| |
| void testImplicit() { |
| Implicit<BaseNonEmpty> nonempty; |
| Implicit<BaseEmpty> empty; // expected-note {{in instantiation}} |
| nonempty.use(); |
| empty.use(); // expected-note {{in instantiation}} |
| } |
| |
| template <class> |
| struct NonDep : BaseEmpty { |
| using BaseEmpty::x UIE; // expected-note{{using declaration annotated with 'using_if_exists' here}} |
| x y(); // expected-error{{reference to unresolved using declaration}} |
| }; |
| } // namespace test_dependent |
| |
| namespace test_using_pack { |
| template <class... Ts> |
| struct S : Ts... { |
| using typename Ts::x... UIE; // expected-error 2 {{target of using declaration conflicts with declaration already in scope}} expected-note{{conflicting declaration}} expected-note{{target of using declaration}} |
| }; |
| |
| struct E1 {}; |
| struct E2 {}; |
| S<E1, E2> a; |
| |
| struct F1 { |
| typedef int x; // expected-note 2 {{conflicting declaration}} |
| }; |
| struct F2 { |
| typedef int x; // expected-note 2 {{target of using declaration}} |
| }; |
| S<F1, F2> b; |
| |
| S<E1, F2> c; // expected-note{{in instantiation of template class}} |
| S<F1, E2> d; // expected-note{{in instantiation of template class}} |
| |
| template <class... Ts> |
| struct S2 : Ts... { |
| using typename Ts::x... UIE; // expected-error 2 {{target of using declaration conflicts with declaration already in scope}} expected-note 3 {{using declaration annotated with 'using_if_exists' here}} expected-note{{conflicting declaration}} expected-note{{target of using declaration}} |
| |
| x mem(); // expected-error 3 {{reference to unresolved using declaration}} |
| }; |
| |
| S2<E1, E2> e; // expected-note{{in instantiation of template class}} |
| S2<F1, F2> f; |
| S2<E1, F2> g; // expected-note{{in instantiation of template class}} |
| S2<F1, E2> h; // expected-note{{in instantiation of template class}} |
| |
| template <class... Ts> |
| struct S3 : protected Ts... { |
| using Ts::m... UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}} |
| }; |
| struct B1 { |
| enum { m }; // expected-note{{conflicting declaration}} |
| }; |
| struct B2 {}; |
| |
| S3<B1, B2> i; // expected-note{{in instantiation of template}} |
| S<B2, B1> j; |
| |
| } // namespace test_using_pack |
| |
| namespace test_nested { |
| namespace NS {} |
| |
| using NS::x UIE; // expected-note {{using declaration annotated with 'using_if_exists' here}} |
| |
| namespace NS2 { |
| using ::test_nested::x UIE; |
| } |
| |
| NS2::x y; // expected-error {{reference to unresolved using declaration}} |
| } // namespace test_nested |
| |
| namespace test_scope { |
| int x; // expected-note{{conflicting declaration}} |
| void f() { |
| int x; // expected-note{{conflicting declaration}} |
| { |
| using ::x UIE; // expected-note {{using declaration annotated with 'using_if_exists' here}} |
| (void)x; // expected-error {{reference to unresolved using declaration}} |
| } |
| |
| { |
| using test_scope::x; |
| using ::x UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}} |
| (void)x; |
| } |
| |
| (void)x; |
| |
| using ::x UIE; // expected-error{{target of using declaration conflicts with declaration already in scope}} expected-note{{target of using declaration}} |
| (void)x; |
| } |
| } // namespace test_scope |
| |
| namespace test_appertains_to { |
| namespace NS { |
| typedef int x; |
| } |
| |
| // FIXME: This diagnostics is wrong. |
| using alias UIE = NS::x; // expected-error {{'using_if_exists' attribute only applies to named declarations, types, and value declarations}} |
| |
| template <class> |
| using template_alias UIE = NS::x; // expected-error {{'using_if_exists' attribute only applies to named declarations, types, and value declarations}} |
| |
| void f() UIE; // expected-error {{'using_if_exists' attribute only applies to named declarations, types, and value declarations}} |
| |
| using namespace NS UIE; // expected-error {{'using_if_exists' attribute only applies to named declarations, types, and value declarations}} |
| } // namespace test_appertains_to |
| |
| typedef int *fake_FILE; |
| int fake_printf(); |
| |
| namespace std { |
| using ::fake_FILE UIE; |
| using ::fake_printf UIE; |
| using ::fake_fopen UIE; // expected-note {{using declaration annotated with 'using_if_exists' here}} |
| using ::fake_size_t UIE; // expected-note {{using declaration annotated with 'using_if_exists' here}} |
| } // namespace std |
| |
| int main() { |
| std::fake_FILE file; |
| file = std::fake_fopen(); // expected-error {{reference to unresolved using declaration}} expected-error{{incompatible integer to pointer}} |
| std::fake_size_t size; // expected-error {{reference to unresolved using declaration}} |
| size = fake_printf(); |
| size = std::fake_printf(); |
| } |