diff options
Diffstat (limited to 'clang/test/CXX/dcl.dcl/basic.namespace')
19 files changed, 1321 insertions, 0 deletions
| diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp new file mode 100644 index 0000000..069ca0a --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify + +// C++'0x [namespace.memdef] p3: +//   Every name first declared in a namespace is a member of that namespace. If +//   a friend declaration in a non-local class first declares a class or +//   function the friend class or function is a member of the innermost +//   enclosing namespace. + +namespace N { +  struct S0 { +    friend struct F0; +    friend void f0(int); +    struct F0 member_func(); +  }; +  struct F0 { }; +  F0 f0() { return S0().member_func(); } +} +N::F0 f0_var = N::f0(); + +// Ensure we can handle attaching friend declarations to an enclosing namespace +// with multiple contexts. +namespace N { struct S1 { struct IS1; }; } +namespace N { +  struct S1::IS1 { +    friend struct F1; +    friend void f1(int); +    struct F1 member_func(); +  }; +  struct F1 { }; +  F1 f1() { return S1::IS1().member_func(); } +} +N::F1 f1_var = N::f1(); + +//   The name of the friend is not found by unqualified lookup (3.4.1) or by +//   qualified lookup (3.4.3) until a matching declaration is provided in that +//   namespace scope (either before or after the class definition granting +//   friendship). If a friend function is called, its name may be found by the +//   name lookup that considers functions from namespaces and classes +//   associated with the types of the function arguments (3.4.2). If the name +//   in a friend declaration is neither qualified nor a template-id and the +//   declaration is a function or an elaborated-type-specifier, the lookup to +//   determine whether the entity has been previously declared shall not +//   consider any scopes outside the innermost enclosing namespace. + +template<typename T> struct X0 { }; +struct X1 { }; + +struct Y { +  template<typename T> union X0; +  template<typename T> friend union X0; +   +  union X1; +  friend union X1; +}; + +namespace N { +  namespace M { +    template<typename T> class X; +  } +} + +namespace N3 { +  class Y { +    template<typename T> friend class N::M::X; +  }; +} + +// FIXME: Woefully inadequate for testing + +// Friends declared as template-ids aren't subject to the restriction +// on innermost namespaces. +// rdar://problem/8552377 +namespace test5 { +  template <class T> void f(T);   +  namespace ns { +    class A { +      friend void f<int>(int); +      static void foo(); // expected-note 2 {{declared private here}} +    }; + +    // Note that this happens without instantiation. +    template <class T> void f(T) { +      A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} +    } +  } + +  template <class T> void f(T) { +    ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} +  } + +  template void f<int>(int); +  template void f<long>(long); //expected-note {{instantiation}} +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp new file mode 100644 index 0000000..b4ec585 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -emit-llvm-only -verify %s + +// This lame little test was ripped straight from the standard. +namespace { +  int i; // expected-note {{candidate}} +} +void test0() { i++; } + +namespace A { +  namespace { +    int i; // expected-note {{candidate}} +    int j; +  } +  void test1() { i++; } +} + +using namespace A; + +void test2() { +  i++; // expected-error {{reference to 'i' is ambiguous}} +  A::i++; +  j++; +} + + +// Test that all anonymous namespaces in a translation unit are +// considered the same context. +namespace { +  class Test3 {}; // expected-note {{previous definition}} +} +namespace { +  class Test3 {}; // expected-error {{redefinition of 'Test3'}} +} + +namespace test4 { +  namespace { +    class Test4 {}; // expected-note {{previous definition}} +  } +  namespace { +    class Test4 {}; // expected-error {{redefinition of 'Test4'}} +  } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp new file mode 100644 index 0000000..6ffa873 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s + +// Intentionally compiled as C++03 to test the extension warning. + +namespace a {} // original +namespace a {} // ext +inline namespace b {} // inline original expected-warning {{inline namespaces are}} +inline namespace b {} // inline ext expected-warning {{inline namespaces are}} +inline namespace {} // inline unnamed expected-warning {{inline namespaces are}} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp new file mode 100644 index 0000000..411c16c --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR8430 +namespace N { +  class A { }; +} + +namespace M { } + +using namespace M; + +namespace N { +  namespace M { +  }  +} + +namespace M { +  namespace N { +  } +} + +namespace N { +  A *getA(); +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp new file mode 100644 index 0000000..98d12f9 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace NIL {} // expected-note {{previous definition}} +inline namespace NIL {} // expected-error {{cannot be reopened as inline}} +inline namespace IL {} // expected-note {{previous definition}} +namespace IL {} // expected-warning{{inline namespace cannot be re-opened as a non-inline namespace}} + +namespace {} // expected-note {{previous definition}} +inline namespace {} // expected-error {{cannot be reopened as inline}} +namespace X { +  inline namespace {} // expected-note {{previous definition}} +  namespace {} // expected-error {{cannot be reopened as non-inline}} +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp new file mode 100644 index 0000000..3bc4856 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Fun things you can do with inline namespaces: + +inline namespace X { +  void f1(); + +  inline namespace Y { +    void f2(); + +    template <typename T> class C {}; +  } + +  // Specialize and partially specialize somewhere else. +  template <> class C<int> {}; +  template <typename T> class C<T*> {}; +} + +// Qualified and unqualified lookup as if member of enclosing NS. +void foo1() { +  f1(); +  ::f1(); +  X::f1(); +  Y::f1(); // expected-error {{no member named 'f1' in namespace 'X::Y'}} + +  f2(); +  ::f2(); +  X::f2(); +  Y::f2(); +} + +template <> class C<float> {}; +template <typename T> class C<T&> {}; + +template class C<double>; + + +// As well as all the fun with ADL. + +namespace ADL { +  struct Outer {}; + +  inline namespace IL { +    struct Inner {}; + +    void fo(Outer); +  } + +  void fi(Inner); + +  inline namespace IL2 { +    void fi2(Inner); +  } +} + +void foo2() { +  ADL::Outer o; +  ADL::Inner i; +  fo(o); +  fi(i); +  fi2(i); +} + +// Let's not forget overload sets. +struct Distinct {}; +inline namespace Over { +  void over(Distinct); +} +void over(int); + +void foo3() { +  Distinct d; +  ::over(d); +} + +// Don't forget to do correct lookup for redeclarations. +namespace redecl { inline namespace n1 { + +  template <class Tp> class allocator; + +  template <> +  class allocator<void> +  { +  public: +      typedef const void* const_pointer; +  }; + +  template <class Tp> +  class allocator +  { +  public: +      typedef Tp& reference; +   +      void allocate(allocator<void>::const_pointer = 0); +  }; + +} } + +// Normal redeclarations (not for explicit instantiations or +// specializations) are distinct in an inline namespace vs. not in an +// inline namespace. +namespace redecl2 {  +  inline namespace n1 { +    void f(int) { } +    struct X1 { }; +    template<typename T> void f(T) { } +    template<typename T> struct X2 { }; +    int i = 71; +    enum E { e }; +  } + +  void f(int) { } +  struct X1 { }; +  template<typename T> void f(T) { } +  template<typename T> struct X2 { }; +  int i = 71; +  enum E { e }; +} 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; +  } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp new file mode 100644 index 0000000..20a19ab --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// (this actually occurs before paragraph 1) +namespace test0 { +  namespace A {} +  class B { +    using namespace A; // expected-error {{'using namespace' is not allowed in classes}} +  }; +} + + +struct opaque0 {}; +struct opaque1 {}; + +// Test that names appear as if in deepest common ancestor. +namespace test1 { +  namespace A { +    namespace B { +      opaque0 foo(); // expected-note {{candidate}} +    } +  } + +  namespace C { +    opaque1 foo(); // expected-note {{candidate}} + +    opaque1 test() { +      using namespace A::B; +      return foo(); // C::foo +    } +  } + +  opaque1 test() { +    using namespace A::B; +    using namespace C; +    return foo(); // expected-error {{call to 'foo' is ambiguous}} +  } +} + +// Same thing, but with the directives in namespaces. +namespace test2 { +  namespace A { +    namespace B { +      opaque0 foo(); // expected-note {{candidate}} +    } +  } + +  namespace C { +    opaque1 foo(); // expected-note {{candidate}} + +    namespace test { +      using namespace A::B; + +      opaque1 test() { +        return foo(); // C::foo +      } +    } +  } + +  namespace test { +    using namespace A::B; +    using namespace C; +     +    opaque1 test() { +      return foo(); // expected-error {{call to 'foo' is ambiguous}} +    } +  } +} + +// Transitivity. +namespace test3 { +  namespace A { +    namespace B { +      opaque0 foo(); +    } +  } +  namespace C { +    using namespace A; +  } + +  opaque0 test0() { +    using namespace C; +    using namespace B; +    return foo(); +  } + +  namespace D { +    using namespace C; +  } +  namespace A { +    opaque1 foo(); +  } + +  opaque1 test1() { +    using namespace D; +    return foo(); +  } +} + +// Transitivity acts like synthetic using directives. +namespace test4 { +  namespace A { +    namespace B { +      opaque0 foo(); // expected-note {{candidate}} +    } +  } +   +  namespace C { +    using namespace A::B; +  } + +  opaque1 foo(); // expected-note {{candidate}} + +  namespace A { +    namespace D { +      using namespace C; +    } + +    opaque0 test() { +      using namespace D; +      return foo(); +    } +  } + +  opaque0 test() { +    using namespace A::D; +    return foo(); // expected-error {{call to 'foo' is ambiguous}} +  } +} + +// Bug: using directives should be followed when parsing default +// arguments in scoped declarations. +class test5 { +  int inc(int x); +}; +namespace Test5 { +  int default_x = 0; +} +using namespace Test5; +int test5::inc(int x = default_x) { +  return x+1; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp new file mode 100644 index 0000000..4cb91cd --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/8296180> +typedef int pid_t; +namespace ns { +  typedef int pid_t; +} +using namespace ns; +pid_t x; + +struct A { }; +namespace ns { +  typedef ::A A; +} +A a; | 
