diff options
Diffstat (limited to 'clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl')
11 files changed, 866 insertions, 0 deletions
| diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp new file mode 100644 index 0000000..bf30ee7 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// We have to avoid ADL for this test. + +template <unsigned N> class test {}; + +class foo {};	// expected-note {{candidate}} +test<0> foo(foo); // expected-note {{candidate}} + +namespace Test0 { +  class foo { int x; }; +  test<1> foo(class foo); + +  namespace A { +    test<2> foo(class ::foo); // expected-note {{candidate}} \ +    // expected-note{{passing argument to parameter here}} + +    void test0() { +      using ::foo; + +      class foo a; +      test<0> _ = (foo)(a); +    } + +    void test1() { +      using Test0::foo; + +      class foo a; +      test<1> _ = (foo)(a); +    }; + +    void test2() { +      class ::foo a; +       +      // Argument-dependent lookup is ambiguous between B:: and ::. +      test<0> _0 = foo(a); // expected-error {{call to 'foo' is ambiguous}} + +      // But basic unqualified lookup is not. +      test<2> _1 = (foo)(a); + +      class Test0::foo b; +      test<2> _2 = (foo)(b); // expected-error {{no viable conversion from 'class Test0::foo' to 'class ::foo'}} +    } +  } +} + +namespace Test1 { +  namespace A { +    class a {}; +  } + +  namespace B { +    typedef class {} b; +  } + +  namespace C { +    int c(); // expected-note {{target of using declaration}} +  } + +  namespace D { +    using typename A::a; +    using typename B::b; +    using typename C::c; // expected-error {{'typename' keyword used on a non-type}} + +    a _1 = A::a(); +    b _2 = B::b(); +  } +} + +namespace test2 { +  class A { +  protected: +    operator int(); +    operator bool(); +  }; + +  class B : private A { +  protected: +    using A::operator int; // expected-note {{declared protected here}} +  public: +    using A::operator bool; +  }; + +  int test() { +    bool b = B(); +    return B(); // expected-error {{'operator int' is a protected member of 'test2::B'}} +  } +} + +namespace test3 { +  class A { +  public: +    ~A(); +  }; + +  class B { +    friend class C; +  private: +    operator A*(); +  }; + +  class C : public B { +  public: +    using B::operator A*; +  }; + +  void test() { +    delete C(); +  } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp new file mode 100644 index 0000000..546c4a4 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { +  namespace ns0 { +    class tag; +    int tag(); +  } + +  namespace ns1 { +    using ns0::tag; +  } + +  namespace ns2 { +    using ns0::tag; +  } + +  using ns1::tag; +  using ns2::tag; +} + +// PR 5752 +namespace test1 { +  namespace ns { +    void foo(); +  } + +  using ns::foo; +  void foo(int); + +  namespace ns { +    using test1::foo; +  } +} + diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp new file mode 100644 index 0000000..c7966ce --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p11: +//   If a function declaration in namespace scope or block scope has +//   the same name and the same parameter types as a function +//   introduced by a using-declaration, the program is +//   ill-formed. [Note: two using-declarations may introduce functions +//   with the same name and the same parameter types. If, for a call +//   to an unqualified function name, function overload resolution +//   selects the functions introduced by such using-declarations, the +//   function call is ill-formed. + +namespace test0 { +  namespace ns { void foo(); } // expected-note {{target of using declaration}} +  int foo(void); // expected-note {{conflicting declaration}} +  using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} +} + +namespace test1 { +  namespace ns { void foo(); } // expected-note {{target of using declaration}} +  using ns::foo; //expected-note {{using declaration}} +  int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} +} + +namespace test2 { +  namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} +  void test0() { +    int foo(void); // expected-note {{conflicting declaration}} +    using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} +  } + +  void test1() { +    using ns::foo; //expected-note {{using declaration}} +    int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} +  } +} + +namespace test3 { +  namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} +  class Test0 { +    void test() { +      int foo(void); // expected-note {{conflicting declaration}} +      using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} +    } +  }; + +  class Test1 { +    void test() { +      using ns::foo; //expected-note {{using declaration}} +      int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} +    } +  }; +} + +namespace test4 { +  namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} +  template <typename> class Test0 { +    void test() { +      int foo(void); // expected-note {{conflicting declaration}} +      using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} +    } +  }; + +  template <typename> class Test1 { +    void test() { +      using ns::foo; //expected-note {{using declaration}} +      int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} +    } +  }; +} + +// FIXME: we should be able to diagnose both of these, but we can't. +namespace test5 { +  namespace ns { void foo(int); } +  template <typename T> class Test0 { +    void test() { +      int foo(T); +      using ns::foo; +    } +  }; + +  template <typename T> class Test1 { +    void test() { +      using ns::foo; +      int foo(T); +    } +  }; + +  template class Test0<int>; +  template class Test1<int>; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp new file mode 100644 index 0000000..cc28bf6 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp @@ -0,0 +1,163 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p12: +//   When a using-declaration brings names from a base class into a +//   derived class scope, member functions in the derived class +//   override and/or hide member functions with the same name and +//   parameter types in a base class (rather than conflicting). + +template <unsigned n> struct Opaque {}; +template <unsigned n> void expect(Opaque<n> _) {} + +// PR5727 +// This just shouldn't crash. +namespace test0 { +  template<typename> struct RefPtr { }; +  template<typename> struct PtrHash { +    static void f() { } +  }; +  template<typename T> struct PtrHash<RefPtr<T> > : PtrHash<T*> { +    using PtrHash<T*>::f; +    static void f() { f(); } +  }; +} + +// Simple hiding. +namespace test1 { +  struct Base { +    Opaque<0> foo(Opaque<0>); +    Opaque<0> foo(Opaque<1>); +    Opaque<0> foo(Opaque<2>); +  }; + +  // using before decls +  struct Test0 : Base { +    using Base::foo; +    Opaque<1> foo(Opaque<1>); +    Opaque<1> foo(Opaque<3>); + +    void test0() { Opaque<0> _ = foo(Opaque<0>()); } +    void test1() { Opaque<1> _ = foo(Opaque<1>()); } +    void test2() { Opaque<0> _ = foo(Opaque<2>()); } +    void test3() { Opaque<1> _ = foo(Opaque<3>()); } +  }; + +  // using after decls +  struct Test1 : Base { +    Opaque<1> foo(Opaque<1>); +    Opaque<1> foo(Opaque<3>); +    using Base::foo; + +    void test0() { Opaque<0> _ = foo(Opaque<0>()); } +    void test1() { Opaque<1> _ = foo(Opaque<1>()); } +    void test2() { Opaque<0> _ = foo(Opaque<2>()); } +    void test3() { Opaque<1> _ = foo(Opaque<3>()); } +  }; + +  // using between decls +  struct Test2 : Base { +    Opaque<1> foo(Opaque<0>); +    using Base::foo; +    Opaque<1> foo(Opaque<2>); +    Opaque<1> foo(Opaque<3>); + +    void test0() { Opaque<1> _ = foo(Opaque<0>()); } +    void test1() { Opaque<0> _ = foo(Opaque<1>()); } +    void test2() { Opaque<1> _ = foo(Opaque<2>()); } +    void test3() { Opaque<1> _ = foo(Opaque<3>()); } +  }; +} + +// Crazy dependent hiding. +namespace test2 { +  struct Base { +    void foo(int); +  }; + +  template <typename T> struct Derived1 : Base { +    using Base::foo; +    void foo(T); + +    void testUnresolved(int i) { foo(i); } +  }; + +  void test0(int i) { +    Derived1<int> d1; +    d1.foo(i); +    d1.testUnresolved(i); +  } + +  // Same thing, except with the order of members reversed. +  template <typename T> struct Derived2 : Base { +    void foo(T); +    using Base::foo; + +    void testUnresolved(int i) { foo(i); } +  }; + +  void test1(int i) { +    Derived2<int> d2; +    d2.foo(i); +    d2.testUnresolved(i); +  } +} + +// Hiding of member templates. +namespace test3 { +  struct Base { +    template <class T> Opaque<0> foo() { return Opaque<0>(); } +    template <int n> Opaque<1> foo() { return Opaque<1>(); } +  }; + +  struct Derived1 : Base { +    using Base::foo; +    template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} +  }; + +  struct Derived2 : Base { +    template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} +    using Base::foo; +  }; + +  struct Derived3 : Base { +    using Base::foo; +    template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} +  }; + +  struct Derived4 : Base { +    template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} +    using Base::foo; +  }; + +  void test() { +    expect<0>(Base().foo<int>()); +    expect<1>(Base().foo<0>()); +    expect<0>(Derived1().foo<int>()); // expected-error {{no matching member function for call to 'foo'}} +    expect<2>(Derived1().foo<0>()); +    expect<0>(Derived2().foo<int>()); // expected-error {{no matching member function for call to 'foo'}} +    expect<2>(Derived2().foo<0>()); +    expect<3>(Derived3().foo<int>()); +    expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} +    expect<3>(Derived4().foo<int>()); +    expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} +  } +} + +// PR7384: access control for member templates. +namespace test4 { +  class Base { +  protected: +    template<typename T> void foo(T); +    template<typename T> void bar(T); // expected-note {{declared protected here}} +  }; + +  struct Derived : Base { +    using Base::foo; +  }; + +  void test() { +    Derived d; +    d.foo<int>(3); +    d.bar<int>(3); // expected-error {{'bar' is a protected member}} +  } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp new file mode 100644 index 0000000..dd44bfc --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p3: +//   For the purpose of overload resolution, the functions which are +//   introduced by a using-declaration into a derived class will be +//   treated as though they were members of the derived class. In +//   particular, the implicit this parameter shall be treated as if it +//   were a pointer to the derived class rather than to the base +//   class. This has no effect on the type of the function, and in all +//   other respects the function remains a member of the base class. + +namespace test0 { +  struct Opaque0 {}; +  struct Opaque1 {}; + +  struct Base { +    Opaque0 test0(int*); +    Opaque0 test1(const int*); +    Opaque0 test2(int*); +    Opaque0 test3(int*) const; +  }; + +  struct Derived : Base { +    using Base::test0; +    Opaque1 test0(const int*); + +    using Base::test1; +    Opaque1 test1(int*); + +    using Base::test2; +    Opaque1 test2(int*) const; + +    using Base::test3; +    Opaque1 test3(int*); +  }; + +  void test0() { +    Opaque0 a = Derived().test0((int*) 0); +    Opaque1 b = Derived().test0((const int*) 0); +  } + +  void test1() { +    Opaque1 a = Derived().test1((int*) 0); +    Opaque0 b = Derived().test1((const int*) 0); +  } + +  void test2() { +    Opaque0 a = ((Derived*) 0)->test2((int*) 0); +    Opaque1 b = ((const Derived*) 0)->test2((int*) 0); +  } + +  void test3() { +    Opaque1 a = ((Derived*) 0)->test3((int*) 0); +    Opaque0 b = ((const Derived*) 0)->test3((int*) 0); +  } +} + +// Typedef redeclaration. +namespace rdar8018262 { +  typedef void (*fp)(); + +  namespace N { +    typedef void (*fp)(); +  } + +  using N::fp; + +  fp fp_1; +} + +// Things to test: +//   member operators +//   conversion operators +//   call operators +//   call-surrogate conversion operators +//   everything, but in dependent contexts diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp new file mode 100644 index 0000000..f61437e --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// C++0x N2914. + +struct B { +  void f(char); +  void g(char); +  enum E { e }; +  union { int x; }; +}; + +class C { +  int g(); +}; + +class D2 : public B { +  using B::f; +  using B::e; +  using B::x; +  using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}} +}; + +namespace test1 { +  struct Base { +    int foo(); +  }; + +  struct Unrelated { +    int foo(); +  }; + +  struct Subclass : Base { +  }; + +  namespace InnerNS { +    int foo(); +  } + +  // We should be able to diagnose these without instantiation. +  template <class T> struct C : Base { +    using InnerNS::foo; // expected-error {{not a class}} +    using Base::bar; // expected-error {{no member named 'bar'}} +    using Unrelated::foo; // expected-error {{not a base class}} +    using C::foo; // expected-error {{refers to its own class}} +    using Subclass::foo; // expected-error {{not a base class}} +  }; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp new file mode 100644 index 0000000..a43d9e0 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp @@ -0,0 +1,213 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p4: +//   A using-declaration used as a member-declaration shall refer to a +//   member of a base class of the class being defined, shall refer to +//   a member of an anonymous union that is a member of a base class +//   of the class being defined, or shall refer to an enumerator for +//   an enumeration type that is a member of a base class of the class +//   being defined. + +// There is no directly analogous paragraph in C++0x, and the feature +// works sufficiently differently there that it needs a separate test. + +namespace test0 { +  namespace NonClass { +    typedef int type; +    struct hiding {}; +    int hiding; +    static union { double union_member; }; +    enum tagname { enumerator }; +  } + +  class Test0 { +    using NonClass::type; // expected-error {{not a class}} +    using NonClass::hiding; // expected-error {{not a class}} +    using NonClass::union_member; // expected-error {{not a class}} +    using NonClass::enumerator; // expected-error {{not a class}} +  }; +} + +struct Opaque0 {}; + +namespace test1 { +  struct A { +    typedef int type; +    struct hiding {}; // expected-note {{previous use is here}} +    Opaque0 hiding; +    union { double union_member; }; +    enum tagname { enumerator }; +  }; + +  struct B : A { +    using A::type; +    using A::hiding; +    using A::union_member; +    using A::enumerator; +    using A::tagname; + +    void test0() { +      type t = 0; +    } + +    void test1() { +      typedef struct A::hiding local; +      struct hiding _ = local(); +    } + +    void test2() { +      union hiding _; // expected-error {{tag type that does not match previous}} +    } + +    void test3() { +      char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; +    } + +    void test4() { +      enum tagname _ = enumerator; +    } + +    void test5() { +      Opaque0 _ = hiding; +    } +  }; +} + +namespace test2 { +  struct A { +    typedef int type; +    struct hiding {}; // expected-note {{previous use is here}} +    int hiding; +    union { double union_member; }; +    enum tagname { enumerator }; +  }; + +  template <class T> struct B : A { +    using A::type; +    using A::hiding; +    using A::union_member; +    using A::enumerator; +    using A::tagname; + +    void test0() { +      type t = 0; +    } + +    void test1() { +      typedef struct A::hiding local; +      struct hiding _ = local(); +    } + +    void test2() { +      union hiding _; // expected-error {{tag type that does not match previous}} +    } + +    void test3() { +      char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; +    } + +    void test4() { +      enum tagname _ = enumerator; +    } + +    void test5() { +      Opaque0 _ = hiding; +    } +  }; +} + +namespace test3 { +  struct hiding {}; + +  template <class T> struct A { +    typedef int type; // expected-note {{target of using declaration}} +    struct hiding {}; +    Opaque0 hiding; // expected-note {{target of using declaration}} +    union { double union_member; }; // expected-note {{target of using declaration}} +    enum tagname { enumerator }; // expected-note 2 {{target of using declaration}} +  }; + +  template <class T> struct B : A<T> { +    using A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}} +    using A<T>::hiding; +    using A<T>::union_member; +    using A<T>::enumerator; +    using A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}} + +    // FIXME: re-enable these when the various bugs involving tags are fixed +#if 0 +    void test1() { +      typedef struct A<T>::hiding local; +      struct hiding _ = local(); +    } + +    void test2() { +      typedef struct A<T>::hiding local; +      union hiding _ = local(); +    } +#endif + +    void test3() { +      char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; +    } + +#if 0 +    void test4() { +      enum tagname _ = enumerator; +    } +#endif + +    void test5() { +      Opaque0 _ = hiding; +    } +  }; + +  template struct B<int>; // expected-note {{in instantiation}} + +  template <class T> struct C : A<T> { +    using typename A<T>::type; +    using typename A<T>::hiding; // expected-note {{declared here}} \ +                                 // expected-error {{'typename' keyword used on a non-type}} +    using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}} +    using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}} + +    void test6() { +      type t = 0; +    } + +    void test7() { +      Opaque0 _ = hiding; // expected-error {{does not refer to a value}} +    } +  }; + +  template struct C<int>; // expected-note {{in instantiation}} +} + +namespace test4 { +  struct Base { +    int foo(); +  }; + +  struct Unrelated { +    int foo(); +  }; + +  struct Subclass : Base { +  }; + +  namespace InnerNS { +    int foo(); +  } + +  // We should be able to diagnose these without instantiation. +  template <class T> struct C : Base { +    using InnerNS::foo; // expected-error {{not a class}} +    using Base::bar; // expected-error {{no member named 'bar'}} +    using Unrelated::foo; // expected-error {{not a base class}} +    using C::foo; // legal in C++03 +    using Subclass::foo; // legal in C++03 + +    int bar(); //expected-note {{target of using declaration}} +    using C::bar; // expected-error {{refers to its own class}} +  }; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp new file mode 100644 index 0000000..edaa975 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// C++0x N2914. + +struct A { +  template<class T> void f(T); +  template<class T> struct X { }; +}; + +struct B : A { +  using A::f<double>; // expected-error{{using declaration can not refer to a template specialization}} +  using A::X<int>; // expected-error{{using declaration can not refer to a template specialization}} +}; diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp new file mode 100644 index 0000000..c4b8849 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// C++0x N2914. + +namespace A { +  namespace B { } +} + +using A::B; // expected-error{{using declaration can not refer to namespace}} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp new file mode 100644 index 0000000..78b5a41 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// C++0x N2914. + +struct X { +  int i; +  static int a; +}; + +using X::i; // expected-error{{using declaration can not refer to class member}} +using X::s; // expected-error{{using declaration can not refer to class member}} + +void f() { +  using X::i; // expected-error{{using declaration can not refer to class member}} +  using X::s; // expected-error{{using declaration can not refer to class member}} +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp new file mode 100644 index 0000000..4660971 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Opaque0 {}; +struct Opaque1 {}; + +// Redeclarations are okay in a namespace. +namespace test0 { +  namespace ns { +    void foo(Opaque0); // expected-note 2 {{candidate function}} +  } + +  using ns::foo; +  using ns::foo; + +  void test0() { +    foo(Opaque1()); // expected-error {{no matching function for call}} +  } + +  namespace ns { +    void foo(Opaque1); +  } + +  void test1() { +    foo(Opaque1()); // expected-error {{no matching function for call}} +  } + +  using ns::foo; + +  void test2() { +    foo(Opaque1()); +  } + +  using ns::foo; +} + +// Make sure we handle transparent contexts the same way. +namespace test1 { +  namespace ns { +    void foo(Opaque0); // expected-note 2 {{candidate function}} +  } + +  extern "C++" { +    using ns::foo; +  } + +  void test0() { +    foo(Opaque1()); // expected-error {{no matching function for call}} +  } + +  namespace ns { +    void foo(Opaque1); +  } + +  void test1() { +    foo(Opaque1()); // expected-error {{no matching function for call}} +  } + +  extern "C++" { +    using ns::foo; +  } + +  void test2() { +    foo(Opaque1()); +  } +} + +// Make sure we detect invalid redeclarations that can't be detected +// until template instantiation. +namespace test2 { +  template <class T> struct Base { +    typedef Base type; +    void foo(); +  }; + +  template <class T> struct Derived : Base<T> { +    // These are invalid redeclarations, detectable only after +    // instantiation. +    using Base<T>::foo; // expected-note {{previous using decl}} +    using Base<T>::type::foo; //expected-error {{redeclaration of using decl}} +  }; + +  template struct Derived<int>; // expected-note {{in instantiation of template class}} +} + +// Redeclarations are okay in a function. +namespace test3 { +  namespace N { +    int f(int); +    typedef int type; +  } + +  void g() { +    using N::f; +    using N::f; +    using N::type; +    using N::type; +  } +} | 
