diff options
| author | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 | 
|---|---|---|
| committer | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 | 
| commit | be1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch) | |
| tree | 1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/test/SemaCXX | |
| parent | c4626a62754862d20b41e8a46a3574264ea80e6d (diff) | |
| parent | f1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff) | |
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/test/SemaCXX')
423 files changed, 34722 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/2008-01-11-BadWarning.cpp b/clang/test/SemaCXX/2008-01-11-BadWarning.cpp new file mode 100644 index 0000000..b84e7c1 --- /dev/null +++ b/clang/test/SemaCXX/2008-01-11-BadWarning.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s +// rdar://5683899 +void** f(void **Buckets, unsigned NumBuckets) { +  return Buckets + NumBuckets; +} diff --git a/clang/test/SemaCXX/Inputs/array-bounds-system-header.h b/clang/test/SemaCXX/Inputs/array-bounds-system-header.h new file mode 100644 index 0000000..07cde80 --- /dev/null +++ b/clang/test/SemaCXX/Inputs/array-bounds-system-header.h @@ -0,0 +1,11 @@ +// "System header" for testing that -Warray-bounds is properly suppressed in +// certain cases. + +#define BAD_MACRO_1 \ +    int i[3]; \ +    i[3] = 5 +#define BAD_MACRO_2(_b, _i) \ +    (_b)[(_i)] = 5 +#define QUESTIONABLE_MACRO(_a) \ +    sizeof(_a) > 3 ? (_a)[3] = 5 : 5 +#define NOP(x) (x) diff --git a/clang/test/SemaCXX/Inputs/lit.local.cfg b/clang/test/SemaCXX/Inputs/lit.local.cfg new file mode 100644 index 0000000..e6f55ee --- /dev/null +++ b/clang/test/SemaCXX/Inputs/lit.local.cfg @@ -0,0 +1 @@ +config.suffixes = [] diff --git a/clang/test/SemaCXX/Inputs/malloc.h b/clang/test/SemaCXX/Inputs/malloc.h new file mode 100644 index 0000000..c54d621 --- /dev/null +++ b/clang/test/SemaCXX/Inputs/malloc.h @@ -0,0 +1,3 @@ +extern "C" { +extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ; +} diff --git a/clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h b/clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h new file mode 100644 index 0000000..d2bd4d5 --- /dev/null +++ b/clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h @@ -0,0 +1,19 @@ +#pragma GCC system_header + +// This header file pretends to be <new> from the system library, for the +// purpose of the over-aligned warnings test. + +void* operator new(unsigned long) { +  return 0; +} +void* operator new[](unsigned long) { +  return 0; +} + +void* operator new(unsigned long, void *) { +  return 0; +} + +void* operator new[](unsigned long, void *) { +  return 0; +} diff --git a/clang/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp b/clang/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp new file mode 100644 index 0000000..0c7d354 --- /dev/null +++ b/clang/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++98 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions + + +//MSVC allows forward enum declaration +enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}} +ENUM *var = 0;      +ENUM var2 = (ENUM)3; +enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}} diff --git a/clang/test/SemaCXX/MicrosoftCompatibility.cpp b/clang/test/SemaCXX/MicrosoftCompatibility.cpp new file mode 100644 index 0000000..3634fa3 --- /dev/null +++ b/clang/test/SemaCXX/MicrosoftCompatibility.cpp @@ -0,0 +1,176 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions + + + +namespace ms_conversion_rules { + +void f(float a); +void f(int a); + +void test() +{ +    long a = 0; +    f((long)0); +	f(a); +} + +} + + + +namespace ms_protected_scope { +  struct C { C(); }; + +  int jump_over_variable_init(bool b) { +    if (b) +      goto foo; // expected-warning {{goto into protected scope}} +    C c; // expected-note {{jump bypasses variable initialization}} +  foo: +    return 1; +  } + +struct Y { +  ~Y(); +}; + +void jump_over_var_with_dtor() { +  goto end; // expected-warning{{goto into protected scope}} +  Y y; // expected-note {{jump bypasses variable with a non-trivial destructor}} + end: +    ; +} + +  void jump_over_variable_case(int c) { +    switch (c) { +    case 0: +      int x = 56; // expected-note {{jump bypasses variable initialization}} +    case 1:       // expected-error {{switch case is in protected scope}} +      x = 10; +    } +  } + +  +void exception_jump() { +  goto l2; // expected-error {{goto into protected scope}} +  try { // expected-note {{jump bypasses initialization of try block}} +     l2: ; +  } catch(int) { +  } +} + +int jump_over_indirect_goto() { +  static void *ps[] = { &&a0 }; +  goto *&&a0; // expected-warning {{goto into protected scope}} +  int a = 3; // expected-note {{jump bypasses variable initialization}} + a0: +  return 0; +} +   +} + +namespace PR11826 { +  struct pair { +    pair(int v) { } +    void operator=(pair&& rhs) { } +  }; +  void f() { +    pair p0(3); +    pair p = p0; +  } +} + +namespace PR11826_for_symmetry { +  struct pair { +    pair(int v) { } +    pair(pair&& rhs) { } +  }; +  void f() { +    pair p0(3); +    pair p(4); +    p = p0; +  } +} + +namespace ms_using_declaration_bug { + +class A { +public:  +  int f();  +}; + +class B : public A { +private:    +  using A::f; +}; + +class C : public B {  +private:    +  using B::f; // expected-warning {{using declaration referring to inaccessible member 'ms_using_declaration_bug::B::f' (which refers to accessible member 'ms_using_declaration_bug::A::f') is a Microsoft compatibility extension}} +}; + +} + + +namespace MissingTypename { + +template<class T> class A { +public: +	 typedef int TYPE; +}; + +template<class T> class B { +public: +	 typedef int TYPE; +}; + + +template<class T, class U> +class C : private A<T>, public B<U> { +public: +   typedef A<T> Base1; +   typedef B<U> Base2; +   typedef A<U> Base3; + +   A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}} +   Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}} + +   B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}} +   Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}} + +   A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}} +   Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}} + }; + +class D { +public: +    typedef int Type; +}; + +template <class T> +void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}} +{ +    const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}} +} + +template void function_missing_typename<D>(const D::Type param); + +} + +enum ENUM2 { +	ENUM2_a = (enum ENUM2) 4, +	ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}} +	ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}} +}; + + +namespace PR11791 { +  template<class _Ty> +  void del(_Ty *_Ptr) { +    _Ptr->~_Ty();  // expected-warning {{pseudo-destructors on type void are a Microsoft extension}} +  } + +  void f() { +    int* a = 0; +    del((void*)a);  // expected-note {{in instantiation of function template specialization}} +  } +} diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp new file mode 100644 index 0000000..0b72cd3 --- /dev/null +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -0,0 +1,205 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -verify -fms-extensions -fexceptions -fcxx-exceptions + + +// ::type_info is predeclared with forward class declartion +void f(const type_info &a); + + +// Microsoft doesn't validate exception specification. +namespace microsoft_exception_spec { + +void foo(); // expected-note {{previous declaration}} +void foo() throw(); // expected-warning {{exception specification in declaration does not match previous declaration}} + +void r6() throw(...); // expected-note {{previous declaration}} +void r6() throw(int); // expected-warning {{exception specification in declaration does not match previous declaration}} + +struct Base { +  virtual void f2(); +  virtual void f3() throw(...); +}; + +struct Derived : Base { +  virtual void f2() throw(...); +  virtual void f3(); +}; + +class A { +  virtual ~A() throw();  // expected-note {{overridden virtual function is here}} +}; + +class B : public A { +  virtual ~B();  // expected-warning {{exception specification of overriding function is more lax than base version}} +}; + +} + +// MSVC allows type definition in anonymous union and struct +struct A +{ +  union  +  { +    int a; +    struct B  // expected-warning {{types declared in an anonymous union are a Microsoft extension}} +    {  +      int c; +    } d; + +    union C   // expected-warning {{types declared in an anonymous union are a Microsoft extension}} +    { +      int e; +      int ee; +    } f; + +    typedef int D;  // expected-warning {{types declared in an anonymous union are a Microsoft extension}} +    struct F;  // expected-warning {{types declared in an anonymous union are a Microsoft extension}} +  }; + +  struct +  { +    int a2; + +    struct B2  // expected-warning {{types declared in an anonymous struct are a Microsoft extension}} +    { +      int c2; +    } d2; +     +	union C2  // expected-warning {{types declared in an anonymous struct are a Microsoft extension}} +    { +      int e2; +      int ee2; +    } f2; + +    typedef int D2;  // expected-warning {{types declared in an anonymous struct are a Microsoft extension}} +    struct F2;  // expected-warning {{types declared in an anonymous struct are a Microsoft extension}} +  }; +}; + +// __stdcall handling +struct M { +    int __stdcall addP(); +    float __stdcall subtractP();  +}; + +// __unaligned handling +typedef char __unaligned *aligned_type; + + +template<typename T> void h1(T (__stdcall M::* const )()) { } + +void m1() { +  h1<int>(&M::addP); +  h1(&M::subtractP); +}  + + + + + +void f(long long); +void f(int); +  +int main() +{ +  // This is an ambiguous call in standard C++. +  // This calls f(long long) in Microsoft mode because LL is always signed. +  f(0xffffffffffffffffLL); +  f(0xffffffffffffffffi64); +} + +// Enumeration types with a fixed underlying type. +const int seventeen = 17; +typedef int Int; + +struct X0 { +  enum E1 : Int { SomeOtherValue } field; // expected-warning{{enumeration types with a fixed underlying type are a Microsoft extension}} +  enum E1 : seventeen; +}; + +enum : long long {  // expected-warning{{enumeration types with a fixed underlying type are a Microsoft extension}} +  SomeValue = 0x100000000 +}; + + +class AAA { +__declspec(dllimport) void f(void) { } +void f2(void); +}; + +__declspec(dllimport) void AAA::f2(void) { // expected-error {{dllimport attribute can be applied only to symbol}} + +} + + + +template <class T> +class BB { +public: +   void f(int g = 10 ); // expected-note {{previous definition is here}} +}; + +template <class T> +void BB<T>::f(int g = 0) { } // expected-warning {{redefinition of default argument}} + + + +extern void static_func(); +void static_func(); // expected-note {{previous declaration is here}} + + +static void static_func() // expected-warning {{static declaration of 'static_func' follows non-static declaration}} +{ + +} + +long function_prototype(int a); +long (*function_ptr)(int a); + +void function_to_voidptr_conv() { +   void *a1 = function_prototype; +   void *a2 = &function_prototype; +   void *a3 = function_ptr; +} + + +void pointer_to_integral_type_conv(char* ptr) { +   char ch = (char)ptr; +   short sh = (short)ptr; +   ch = (char)ptr; +   sh = (short)ptr; +}  + + +namespace friend_as_a_forward_decl { + +class A { +  class Nested { +    friend class B; +    B* b; +  }; +  B* b; +}; +B* global_b; + + +void f() +{ +  class Local { +    friend class Z; +    Z* b; +  }; +  Z* b; +} + +} + +struct PR11150 { +  class X { +    virtual void f() = 0; +  }; + +  int array[__is_abstract(X)? 1 : -1]; +}; + +void f() { int __except = 0; } + diff --git a/clang/test/SemaCXX/PR10177.cpp b/clang/test/SemaCXX/PR10177.cpp new file mode 100644 index 0000000..8d745de --- /dev/null +++ b/clang/test/SemaCXX/PR10177.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T, typename U, U> using alias_ref = T; +template<typename T, typename U, U> void func_ref() {} +template<typename T, typename U, U> struct class_ref {}; + +template<int N> +struct U { +  static int a; +}; + +template<int N> struct S; // expected-note 2{{here}} + +template<int N> +int U<N>::a = S<N>::kError; // expected-error 2{{undefined}} + +template<typename T> +void f() { +  // FIXME: The standard suggests that U<0>::a is odr-used by this expression, +  // but it's not entirely clear that's the right behaviour. +  (void)alias_ref<int, int&, U<0>::a>(); +  (void)func_ref<int, int&, U<1>::a>(); // expected-note {{here}} +  (void)class_ref<int, int&, U<2>::a>(); // expected-note {{here}} +}; + +int main() { +  f<int>(); // expected-note 2{{here}} +} + +namespace N { +  template<typename T> struct S { static int n; }; +  template<typename T> int S<T>::n = 5; +  void g(int*); +  template<typename T> int f() { +    int k[S<T>::n]; +    g(k); +    return k[3]; +  } +  int j = f<int>(); +} diff --git a/clang/test/SemaCXX/PR10243.cpp b/clang/test/SemaCXX/PR10243.cpp new file mode 100644 index 0000000..129ff80 --- /dev/null +++ b/clang/test/SemaCXX/PR10243.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S; // expected-note 4{{forward declaration of 'S'}} + +struct T0 { +  S s; // expected-error{{field has incomplete type 'S'}} +  T0() = default; +}; + +struct T1 { +  S s; // expected-error{{field has incomplete type 'S'}} +  T1(T1&) = default; +}; + +struct T2 { +  S s; // expected-error{{field has incomplete type 'S'}} +  T2& operator=(T2&) = default; +}; + +struct T3 { +  S s; // expected-error{{field has incomplete type 'S'}} +  ~T3() = default; +}; diff --git a/clang/test/SemaCXX/PR10447.cpp b/clang/test/SemaCXX/PR10447.cpp new file mode 100644 index 0000000..08644ad --- /dev/null +++ b/clang/test/SemaCXX/PR10447.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -verify %s + +// PR12223 +namespace test1 { +  namespace N { +    extern "C" void f(struct S*); +    void g(S*); +  } +  namespace N { +    void f(struct S *s) { +      g(s); +    } +  } +} + +// PR10447 +namespace test2 { +  extern "C" { +    void f(struct Bar*) { } +    test2::Bar *ptr; +  } +} diff --git a/clang/test/SemaCXX/PR10458.cpp b/clang/test/SemaCXX/PR10458.cpp new file mode 100644 index 0000000..57588eb --- /dev/null +++ b/clang/test/SemaCXX/PR10458.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 + +void f() { +  int arr[] = { 1, 2, 3 }; +  for (auto &i : arr) { // expected-warning {{'auto' type specifier is a C++11 extension}} expected-warning {{range-based for loop is a C++11 extension}} +  } +} diff --git a/clang/test/SemaCXX/PR11358.cpp b/clang/test/SemaCXX/PR11358.cpp new file mode 100644 index 0000000..9c49227 --- /dev/null +++ b/clang/test/SemaCXX/PR11358.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -verify +// PR11358 + +namespace test1 { +  template<typename T> +  struct container { +    class iterator {}; +    iterator begin() { return iterator(); } +  }; + +  template<typename T> +  struct Test { +    typedef container<T> Container; +    void test() { +      Container::iterator i = c.begin(); // expected-error{{missing 'typename'}} +    } +    Container c; +  }; +} + +namespace test2 { +  template <typename Key, typename Value> +  class hash_map { +    class const_iterator { void operator++(); }; +    const_iterator begin() const; +    const_iterator end() const; +  }; + +  template <typename KeyType, typename ValueType> +  void MapTest(hash_map<KeyType, ValueType> map) { +    for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); // expected-error{{missing 'typename'}} +         it != map.end(); it++) { +    } +  } +} + +namespace test3 { +  template<typename T> +  struct container { +    class iterator {}; +  }; + +  template<typename T> +  struct Test { +    typedef container<T> Container; +    void test() { +      Container::iterator const i; // expected-error{{missing 'typename'}} +    } +    Container c; +  }; +} diff --git a/clang/test/SemaCXX/PR12481.cpp b/clang/test/SemaCXX/PR12481.cpp new file mode 100644 index 0000000..9487e4d --- /dev/null +++ b/clang/test/SemaCXX/PR12481.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -x c++ -fsyntax-only %s + +class C1 { }; +class C2 { }; +template<class TrieData> struct BinaryTrie { +  ~BinaryTrie() { +    (void)(({ +      static int x = 5; +    } +    )); +  } +}; +class FooTable { +  BinaryTrie<C1> c1_trie_; +  BinaryTrie<C2> c2_trie_; +}; +FooTable* foo = new FooTable; diff --git a/clang/test/SemaCXX/PR5086-ambig-resolution-enum.cpp b/clang/test/SemaCXX/PR5086-ambig-resolution-enum.cpp new file mode 100644 index 0000000..b5aac5f --- /dev/null +++ b/clang/test/SemaCXX/PR5086-ambig-resolution-enum.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +class C { +public: +        enum E { e1=0 }; +        const char * fun1(int , enum E) const; +        int fun1(unsigned, const char *) const; +}; + +void foo(const C& rc) { +        enum {BUFLEN = 128 }; +        const char *p = rc.fun1(BUFLEN - 2, C::e1); +} diff --git a/clang/test/SemaCXX/PR6562.cpp b/clang/test/SemaCXX/PR6562.cpp new file mode 100644 index 0000000..854d9b0 --- /dev/null +++ b/clang/test/SemaCXX/PR6562.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X { ~X(); }; +template <typename T> +struct A { +  struct B { X x; }; +  struct C : public B { +    C() : B() { } +  }; +}; diff --git a/clang/test/SemaCXX/PR6618.cpp b/clang/test/SemaCXX/PR6618.cpp new file mode 100644 index 0000000..10d4dc8 --- /dev/null +++ b/clang/test/SemaCXX/PR6618.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class bar; // expected-note {{forward declaration of 'bar'}} +struct zed { +  bar g; // expected-error {{field has incomplete type}} +}; +class baz { +  zed h; +}; +void f() { +  enum { +    e = sizeof(baz) +  }; +} diff --git a/clang/test/SemaCXX/PR7410.cpp b/clang/test/SemaCXX/PR7410.cpp new file mode 100644 index 0000000..6d2cda9 --- /dev/null +++ b/clang/test/SemaCXX/PR7410.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct BaseReturn {}; + +struct Base { +  virtual BaseReturn Foo() = 0;  // expected-note{{overridden virtual function is here}} +}; +struct X {}; +struct Derived : Base { +  X Foo();  // expected-error{{virtual function 'Foo' has a different return type ('X') than the function it overrides (which has return type 'BaseReturn')}} +}; + +Derived d; diff --git a/clang/test/SemaCXX/PR7944.cpp b/clang/test/SemaCXX/PR7944.cpp new file mode 100644 index 0000000..51b3f6b --- /dev/null +++ b/clang/test/SemaCXX/PR7944.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR7944 + +#define MACRO(x) x + +struct B { int f() { return 0; } }; +struct A { B* b() { return new B; } }; + +void g() { +  A a; +  MACRO(a.b->f());  // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} +} diff --git a/clang/test/SemaCXX/PR8012.cpp b/clang/test/SemaCXX/PR8012.cpp new file mode 100644 index 0000000..9cfc2b0 --- /dev/null +++ b/clang/test/SemaCXX/PR8012.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +void foo (int operator+); // expected-error{{cannot be the name of a parameter}} diff --git a/clang/test/SemaCXX/PR8385.cpp b/clang/test/SemaCXX/PR8385.cpp new file mode 100644 index 0000000..77a117a --- /dev/null +++ b/clang/test/SemaCXX/PR8385.cpp @@ -0,0 +1,7 @@ +// RUN: not %clang_cc1 -fsyntax-only %s + +// don't crash on this, but don't constrain our diagnostics here as they're +// currently rather poor (we even accept things like "template struct {}"). +// Other, explicit tests, should verify the relevant behavior of template  +// instantiation. +struct{template struct{ diff --git a/clang/test/SemaCXX/PR8755.cpp b/clang/test/SemaCXX/PR8755.cpp new file mode 100644 index 0000000..07778dd --- /dev/null +++ b/clang/test/SemaCXX/PR8755.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <typename T> +struct A { +  typedef int iterator;  // expected-note{{declared here}} +}; + +template <typename T> +void f() { +  class A <T> ::iterator foo;  // expected-error{{elaborated type refers to a typedef}} +} + +void g() { +  f<int>();  // expected-note{{in instantiation of function template}} +} + diff --git a/clang/test/SemaCXX/PR8884.cpp b/clang/test/SemaCXX/PR8884.cpp new file mode 100644 index 0000000..4026465 --- /dev/null +++ b/clang/test/SemaCXX/PR8884.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only  %s +extern "C" { +  class bar { +    friend struct foo; +    static struct foo& baz (); +  }; +  struct foo { +    void zed () { +      bar::baz(); +    } +  }; +} diff --git a/clang/test/SemaCXX/PR9459.cpp b/clang/test/SemaCXX/PR9459.cpp new file mode 100644 index 0000000..2b96f34 --- /dev/null +++ b/clang/test/SemaCXX/PR9459.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Don't crash. + +template<typename>struct ae_same; +template<typename>struct ts{}ap() // expected-error {{expected ';' after struct}} expected-error {{requires a type specifier}} +{ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error {{use of undeclared identifier 'a'}} diff --git a/clang/test/SemaCXX/PR9460.cpp b/clang/test/SemaCXX/PR9460.cpp new file mode 100644 index 0000000..0dd8446 --- /dev/null +++ b/clang/test/SemaCXX/PR9460.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +// Don't crash. + +template<typename aT> +struct basic_string{ +  a; // expected-error {{requires a type specifier}} +  basic_string(aT*); +}; + +struct runtime_error{ +  runtime_error( +basic_string<char> struct{ // expected-error {{cannot combine with previous 'type-name' declaration specifier}} +a(){ // expected-error {{requires a type specifier}} +  runtime_error(0); +} +} +); +}; diff --git a/clang/test/SemaCXX/PR9461.cpp b/clang/test/SemaCXX/PR9461.cpp new file mode 100644 index 0000000..beed348 --- /dev/null +++ b/clang/test/SemaCXX/PR9461.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +// Don't crash. + +template<typename,typename=int,typename=int>struct basic_string; + +typedef basic_string<char> string; + + + +template<typename aT,typename,typename oc> +struct basic_string +{ +int us; +basic_string(const aT*,const oc&a=int()); + +int _S_construct(); + +int _S_construct(int); + +_S_construct(); // expected-error {{requires}} +}; + +template<typename _CharT,typename _Traits,typename _Alloc> +basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT*,const _Alloc&) +:us(_S_construct) +{string a;} + +struct runtime_error{runtime_error(string);}; + +struct system_error:runtime_error{ // expected-note {{to match}} +system_error():time_error("" // expected-error 3 {{expected}} expected-note {{to match}} diff --git a/clang/test/SemaCXX/PR9572.cpp b/clang/test/SemaCXX/PR9572.cpp new file mode 100644 index 0000000..b475b57 --- /dev/null +++ b/clang/test/SemaCXX/PR9572.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class Base { +  virtual ~Base(); // expected-note {{implicitly declared private here}} +}; +struct Foo : public Base { // expected-error {{base class 'Base' has private destructor}} +  const int kBlah = 3; // expected-warning {{is a C++11 extension}} +  Foo(); +}; +struct Bar : public Foo { +  Bar() { } // expected-note {{implicit default destructor for 'Foo' first required here}} +}; +struct Baz { +  Foo f; +  Baz() { } +}; diff --git a/clang/test/SemaCXX/PR9884.cpp b/clang/test/SemaCXX/PR9884.cpp new file mode 100644 index 0000000..ab883c4 --- /dev/null +++ b/clang/test/SemaCXX/PR9884.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class Base { +protected: +  Base(int val); +}; + + +class Derived : public Base { +public: +  Derived(int val); +}; + + +Derived::Derived(int val) +  :  Base( val ) +{ +} diff --git a/clang/test/SemaCXX/PR9902.cpp b/clang/test/SemaCXX/PR9902.cpp new file mode 100644 index 0000000..80086e4 --- /dev/null +++ b/clang/test/SemaCXX/PR9902.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template <class _Tp, class _Up, bool = false> +struct __allocator_traits_rebind +{ +}; + +template <template <class, class...> class _Alloc, class _Tp, class ..._Args, +class _Up> +struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, false> +{ +   typedef _Alloc<_Up, _Args...> type; +}; + +template <class Alloc> +struct allocator_traits +{ +   template <class T> using rebind_alloc = typename __allocator_traits_rebind<Alloc, T>::type; +   template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; +}; + +template <class T> +struct allocator {}; + +int main() +{ +   allocator_traits<allocator<char>>::rebind_alloc<int> a; +} diff --git a/clang/test/SemaCXX/PR9908.cpp b/clang/test/SemaCXX/PR9908.cpp new file mode 100644 index 0000000..fc090cc --- /dev/null +++ b/clang/test/SemaCXX/PR9908.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template <class _Tp, class _Up> +struct __allocator_traits_rebind +{ +    typedef typename _Tp::template rebind<_Up>::other type; +}; + +template <class Alloc> +struct allocator_traits +{ +    typedef Alloc allocator_type; +    template <class T> using rebind_alloc = typename +__allocator_traits_rebind<allocator_type, T>::type; +    template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; +}; + +template <class T> +struct ReboundA {}; + +template <class T> +struct A +{ +    typedef T value_type; + +    template <class U> struct rebind {typedef ReboundA<U> other;}; +}; + +int main() +{ +    allocator_traits<A<char> >::rebind_traits<double> a; +} diff --git a/clang/test/SemaCXX/__null.cpp b/clang/test/SemaCXX/__null.cpp new file mode 100644 index 0000000..56e59c0 --- /dev/null +++ b/clang/test/SemaCXX/__null.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -Wno-null-conversion -fsyntax-only -verify +// RUN: %clang_cc1 -triple i686-unknown-unknown %s -Wno-null-conversion -fsyntax-only -verify + +void f() { +  int* i = __null; +  i = __null; +  int i2 = __null; + +  // Verify statically that __null is the right size +  int a[sizeof(typeof(__null)) == sizeof(void*)? 1 : -1]; +   +  // Verify that null is evaluated as 0. +  int b[__null ? -1 : 1]; +} + +struct A {}; + +void g() { +  (void)(0 ? __null : A()); // expected-error {{non-pointer operand type 'A' incompatible with NULL}} +  (void)(0 ? A(): __null); // expected-error {{non-pointer operand type 'A' incompatible with NULL}} +} diff --git a/clang/test/SemaCXX/__try.cpp b/clang/test/SemaCXX/__try.cpp new file mode 100644 index 0000000..cb5d38a --- /dev/null +++ b/clang/test/SemaCXX/__try.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fborland-extensions -fcxx-exceptions %s + +// This test is from http://docwiki.embarcadero.com/RADStudio/en/Try + +int puts(const char *); + +template<typename T> +int printf(const char *, T); + +const char * strdup(const char *); + +void free(const void *); + +#define EXCEPTION_EXECUTE_HANDLER 1 + +class Exception +{ +public: +  Exception(const char* s = "Unknown"){what = strdup(s);      } +  Exception(const Exception& e ){what = strdup(e.what); } +  ~Exception()                   {free(what);         } +  const char* msg() const             {return what;           } +private: +  const char* what; +}; + +int main() +{ +  float e, f, g; +  try +  { +    try +    { +      f = 1.0; +      g = 0.0; +      try +      { +        puts("Another exception:"); + +        e = f / g; +      } +      __except(EXCEPTION_EXECUTE_HANDLER) +      { +        puts("Caught a C-based exception."); +        throw(Exception("Hardware error: Divide by 0")); +      } +    } +    catch(const Exception& e) +    { +      printf("Caught C++ Exception: %s :\n", e.msg()); +    } +  } +  __finally +  { +    puts("C++ allows __finally too!"); +  } +  return e; +} diff --git a/clang/test/SemaCXX/abstract.cpp b/clang/test/SemaCXX/abstract.cpp new file mode 100644 index 0000000..b164d9e --- /dev/null +++ b/clang/test/SemaCXX/abstract.cpp @@ -0,0 +1,261 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) +#define __CONCAT1(__X, __Y) __X ## __Y + +#define static_assert(__b, __m) \ +  typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1] +#endif + +class C { +  virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f'}} +}; + +static_assert(__is_abstract(C), "C has a pure virtual function"); + +class D : C { +}; + +static_assert(__is_abstract(D), "D inherits from an abstract class"); + +class E : D { +  virtual void f(); +}; + +static_assert(!__is_abstract(E), "E inherits from an abstract class but implements f"); + +C *d = new C; // expected-error {{allocating an object of abstract class type 'C'}} + +C c; // expected-error {{variable type 'C' is an abstract class}} +void t1(C c); // expected-error {{parameter type 'C' is an abstract class}} +void t2(C); // expected-error {{parameter type 'C' is an abstract class}} + +struct S { +  C c; // expected-error {{field type 'C' is an abstract class}} +}; + +void t3(const C&); + +void f() { +  C(); // expected-error {{allocating an object of abstract class type 'C'}} +  t3(C()); // expected-error {{allocating an object of abstract class type 'C'}} +} + +C e1[2]; // expected-error {{array of abstract class type 'C'}} +C (*e2)[2]; // expected-error {{array of abstract class type 'C'}} +C (**e3)[2]; // expected-error {{array of abstract class type 'C'}} + +void t4(C c[2]); // expected-error {{array of abstract class type 'C'}} + +void t5(void (*)(C)); // expected-error {{parameter type 'C' is an abstract class}} + +typedef void (*Func)(C); // expected-error {{parameter type 'C' is an abstract class}} +void t6(Func); + +class F { +  F a() { while (1) {} } // expected-error {{return type 'F' is an abstract class}} +     +  class D { +    void f(F c); // expected-error {{parameter type 'F' is an abstract class}} +  }; + +  union U { +    void u(F c); // expected-error {{parameter type 'F' is an abstract class}} +  }; +     +  virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f'}} +}; + +// Diagnosing in these cases is prohibitively expensive.  We still +// diagnose at the function definition, of course. + +class Abstract; + +void t7(Abstract a); + +void t8() { +  void h(Abstract a); +} + +namespace N { +void h(Abstract a); +} + +class Abstract { +  virtual void f() = 0; +}; + +// <rdar://problem/6854087> +class foo { +public: +  virtual foo *getFoo() = 0; +}; + +class bar : public foo { +public: +  virtual bar *getFoo(); +}; + +bar x; + +// <rdar://problem/6902298> +class A { +public: +  virtual void release() = 0; +  virtual void release(int count) = 0; +  virtual void retain() = 0; +}; + +class B : public A { +public: +  virtual void release(); +  virtual void release(int count); +  virtual void retain(); +}; + +void foo(void) { +  B b; +} + +struct K { + int f; + virtual ~K(); +}; + +struct L : public K { + void f(); +}; + +// PR5222 +namespace PR5222 { +  struct A { +    virtual A *clone() = 0; +  }; +  struct B : public A { +    virtual B *clone() = 0; +  }; +  struct C : public B { +    virtual C *clone(); +  }; + +  C c;   +} + +// PR5550 - instantiating template didn't track overridden methods +namespace PR5550 { +  struct A { +    virtual void a() = 0; +    virtual void b() = 0; +  }; +  template<typename T> struct B : public A { +    virtual void b(); +    virtual void c() = 0; +  }; +  struct C : public B<int> { +    virtual void a(); +    virtual void c(); +  };  +  C x; +} + +namespace PureImplicit { +  // A pure virtual destructor should be implicitly overridden. +  struct A { virtual ~A() = 0; }; +  struct B : A {}; +  B x; + +  // A pure virtual assignment operator should be implicitly overridden. +  struct D; +  struct C { virtual D& operator=(const D&) = 0; }; +  struct D : C {}; +  D y; +} + +namespace test1 { +  struct A { +    virtual void foo() = 0; +  }; + +  struct B : A { +    using A::foo; +  }; + +  struct C : B { +    void foo(); +  }; + +  void test() { +    C c; +  } +} + +// rdar://problem/8302168 +namespace test2 { +  struct X1 { +    virtual void xfunc(void) = 0;  // expected-note {{unimplemented pure virtual method}} +    void g(X1 parm7);        // expected-error {{parameter type 'test2::X1' is an abstract class}} +    void g(X1 parm8[2]);     // expected-error {{array of abstract class type 'test2::X1'}} +  }; + +  template <int N> +  struct X2 { +    virtual void xfunc(void) = 0;  // expected-note {{unimplemented pure virtual method}} +    void g(X2 parm10);        // expected-error {{parameter type 'X2<N>' is an abstract class}} +    void g(X2 parm11[2]);     // expected-error {{array of abstract class type 'X2<N>'}} +  }; +} + +namespace test3 { +  struct A { // expected-note {{not complete until}} +    A x; // expected-error {{field has incomplete type}} +    virtual void abstract() = 0; +  }; + +  struct B { // expected-note {{not complete until}} +    virtual void abstract() = 0; +    B x; // expected-error {{field has incomplete type}} +  }; + +  struct C { +    static C x; // expected-error {{abstract class}} +    virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}} +  }; + +  struct D { +    virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}} +    static D x; // expected-error {{abstract class}} +  }; +} + +namespace test4 { +  template <class T> struct A { +    A x; // expected-error {{abstract class}} +    virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}} +  }; + +  template <class T> struct B { +    virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}} +    B x; // expected-error {{abstract class}} +  }; + +  template <class T> struct C { +    static C x; // expected-error {{abstract class}} +    virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}} +  }; + +  template <class T> struct D { +    virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}} +    static D x; // expected-error {{abstract class}} +  }; +} + +// PR9247: Crash on invalid in clang::Sema::ActOnFinishCXXMemberSpecification +namespace pr9247 { +  struct A { +    virtual void g(const A& input) = 0; +    struct B { +      C* f(int foo); +    }; +  }; +} diff --git a/clang/test/SemaCXX/access-base-class.cpp b/clang/test/SemaCXX/access-base-class.cpp new file mode 100644 index 0000000..f676e19 --- /dev/null +++ b/clang/test/SemaCXX/access-base-class.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace T1 { +   +class A { }; +class B : private A { }; // expected-note {{declared private here}} + +void f(B* b) { +  A *a = b; // expected-error{{cannot cast 'T1::B' to its private base class 'T1::A'}} +} + +} + +namespace T2 {  + +class A { }; +class B : A { }; // expected-note {{implicitly declared private here}} + +void f(B* b) { +  A *a = b; // expected-error {{cannot cast 'T2::B' to its private base class 'T2::A'}} +} + +} + +namespace T3 { + +class A { }; +class B : public A { };  + +void f(B* b) { +  A *a = b; +} + +} + +namespace T4 { + +class A {}; + +class B : private virtual A {}; +class C : public virtual A {}; + +class D : public B, public C {}; + +void f(D *d) { +  // This takes the D->C->B->A path. +  A *a = d; +} + +} + +namespace T5 { +  class A {}; +     +  class B : private A { +    void f(B *b) { +      A *a = b; +    } +  };     +} + +namespace T6 { +  class C; +   +  class A {}; // expected-note{{member is declared here}} +   +  class B : private A { // expected-note {{declared private here}} expected-note {{constrained by private inheritance here}} +    void f(C* c); +  }; +   +  class C : public B {  +    void f(C *c) { +      A* a = c; // expected-error {{cannot cast 'T6::C' to its private base class 'T6::A'}} \ +                // expected-error {{'A' is a private member of 'T6::A'}} +    } +  }; +   +  void B::f(C *c) { +    A *a = c; +  } +} + +namespace T7 { +  class A {}; +  class B : public A {}; +  class C : private B {  +    void f(C *c) { +      A* a = c; // okay +    } +  }; +} + diff --git a/clang/test/SemaCXX/access-control-check.cpp b/clang/test/SemaCXX/access-control-check.cpp new file mode 100644 index 0000000..4540e99 --- /dev/null +++ b/clang/test/SemaCXX/access-control-check.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class M { +  int iM; +}; + +class P { +  int iP; // expected-note {{declared private here}} +  int PPR(); // expected-note {{declared private here}} +}; + +class N : M,P { +  N() {} +  int PR() { return iP + PPR(); } // expected-error 2 {{private member of 'P'}} +}; diff --git a/clang/test/SemaCXX/access-member-pointer.cpp b/clang/test/SemaCXX/access-member-pointer.cpp new file mode 100644 index 0000000..676eb10 --- /dev/null +++ b/clang/test/SemaCXX/access-member-pointer.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR7694 + +class A { }; +class B : private A { public: void foo(); }; // expected-note {{declared private here}} +void B::foo() { +  (void)static_cast<void(A::*)()>(&B::foo); +} +void bar() { +  (void)static_cast<void(A::*)()>(&B::foo); // expected-error {{cannot cast 'B' to its private base class 'A'}} +} diff --git a/clang/test/SemaCXX/access.cpp b/clang/test/SemaCXX/access.cpp new file mode 100644 index 0000000..18ad301 --- /dev/null +++ b/clang/test/SemaCXX/access.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class C { +    struct S; // expected-note {{previously declared 'private' here}} +public: +     +    struct S {}; // expected-error {{'S' redeclared with 'public' access}} +}; + +struct S { +    class C; // expected-note {{previously declared 'public' here}} +     +private: +    class C { }; // expected-error {{'C' redeclared with 'private' access}} +}; + +class T { +protected: +    template<typename T> struct A; // expected-note {{previously declared 'protected' here}} +     +private: +    template<typename T> struct A {}; // expected-error {{'A' redeclared with 'private' access}} +}; + +// PR5573 +namespace test1 { +  class A { +  private: +    class X; // expected-note {{previously declared 'private' here}} +  public: +    class X; // expected-error {{'X' redeclared with 'public' access}} +    class X {}; +  }; +} diff --git a/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp b/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp new file mode 100644 index 0000000..cfd55ee --- /dev/null +++ b/clang/test/SemaCXX/addr-of-overloaded-function-casting.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +void g(); + +void f(); // expected-note 9{{candidate function}} +void f(int); // expected-note 9{{candidate function}} + +template<class T> void t(T); // expected-note 6{{candidate function}} +template<class T> void t(T*); // expected-note 6{{candidate function}} + +template<class T> void u(T); + +int main() +{ +  { bool b = (void (&)(char))f; } // expected-error{{does not match required type}} +  { bool b = (void (*)(char))f; } // expected-error{{does not match required type}} +   +  { bool b = (void (&)(int))f; } //ok +  { bool b = (void (*)(int))f; } //ok +   +  { bool b = static_cast<void (&)(char)>(f); } // expected-error{{does not match}} +  { bool b = static_cast<void (*)(char)>(f); } // expected-error{{address of overloaded function}} +   +  { bool b = static_cast<void (&)(int)>(f); } //ok +  { bool b = static_cast<void (*)(int)>(f); } //ok +   +   +  { bool b = reinterpret_cast<void (&)(char)>(f); } // expected-error{{cannot resolve}} +  { bool b = reinterpret_cast<void (*)(char)>(f); } // expected-error{{cannot resolve}} +   +  { bool b = reinterpret_cast<void (*)(char)>(g); } //ok +  { bool b = static_cast<void (*)(char)>(g); } // expected-error{{not allowed}} +   +  { bool b = reinterpret_cast<void (&)(int)>(f); } // expected-error{{cannot resolve}} +  { bool b = reinterpret_cast<void (*)(int)>(f); } // expected-error{{cannot resolve}} + +  { bool b = (int (&)(char))t; } // expected-error{{does not match}} +  { bool b = (int (*)(char))t; } // expected-error{{does not match}} +   +  { bool b = (void (&)(int))t; } //ok +  { bool b = (void (*)(int))t; } //ok +   +  { bool b = static_cast<void (&)(char)>(t); } //ok +  { bool b = static_cast<void (*)(char)>(t); } //ok +   +  { bool b = static_cast<void (&)(int)>(t); } //ok +  { bool b = static_cast<void (*)(int)>(t); } //ok +   +   +  { bool b = reinterpret_cast<void (&)(char)>(t); } // expected-error{{cannot resolve}} +  { bool b = reinterpret_cast<void (*)(char)>(t); } // expected-error{{cannot resolve}} +   +  { bool b = reinterpret_cast<int (*)(char)>(g); } //ok +  { bool b = static_cast<int (*)(char)>(t); } // expected-error{{cannot be static_cast}} +  { bool b = static_cast<int (&)(char)>(t); } // expected-error{{does not match required}} +   +  { bool b = static_cast<void (&)(char)>(f); } // expected-error{{does not match}} +} diff --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp new file mode 100644 index 0000000..096f748 --- /dev/null +++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +int f(double); // expected-note{{candidate function}} +int f(int); // expected-note{{candidate function}} + +int (*pfd)(double) = f; // selects f(double) +int (*pfd2)(double) = &f; // selects f(double) +int (*pfd3)(double) = ((&((f)))); // selects f(double) +int (*pfi)(int) = &f;    // selects f(int) +// FIXME: This error message is not very good. We need to keep better +// track of what went wrong when the implicit conversion failed to +// give a better error message here. +int (*pfe)(...) = &f;    // expected-error{{address of overloaded function 'f' does not match required type 'int (...)'}} +int (&rfi)(int) = f;     // selects f(int) +int (&rfd)(double) = f;  // selects f(double) + +void g(int (*fp)(int));   // expected-note{{candidate function}} +void g(int (*fp)(float)); +void g(int (*fp)(double)); // expected-note{{candidate function}} + +int g1(int); +int g1(char); + +int g2(int); +int g2(double); + +template<typename T> T g3(T); +int g3(int); +int g3(char); + +void g_test() { +  g(g1); +  g(g2); // expected-error{{call to 'g' is ambiguous}} +  g(g3); +} + +template<typename T> T h1(T); +template<typename R, typename A1> R h1(A1); +int h1(char); + +void ha(int (*fp)(int)); +void hb(int (*fp)(double)); + +void h_test() { +  ha(h1); +  hb(h1); +} + +struct A { }; +void f(void (*)(A *)); + +struct B +{ +  void g() { f(d); } +  void d(void *); +  static void d(A *); +}; + +struct C { +  C &getC() { +    return makeAC; // expected-error{{reference to non-static member function must be called}} +  } + +  C &makeAC(); +  const C &makeAC() const; + +  static void f(); // expected-note{{candidate function}} +  static void f(int); // expected-note{{candidate function}} + +  void g() { +    int (&fp)() = f; // expected-error{{address of overloaded function 'f' does not match required type 'int ()'}} +  } +}; + +// PR6886 +namespace test0 { +  void myFunction(void (*)(void *)); + +  class Foo { +    void foo(); + +    static void bar(void*); +    static void bar(); +  }; + +  void Foo::foo() { +    myFunction(bar); +  } +} + +namespace PR7971 { +  struct S { +    void g() { +      f(&g); +    } +    void f(bool (*)(int, char)); +    static bool g(int, char); +  }; +} + +namespace PR8033 { +  template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} \ +  // expected-note{{candidate function}} +  template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} \ +  // expected-note{{candidate function}} +  int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} \ +  // expected-error{{address of overloaded function 'f' is ambiguous}} + +} + +namespace PR8196 { +  template <typename T> struct mcdata { +    typedef int result_type; +  }; +  template <class T>  +    typename mcdata<T>::result_type wrap_mean(mcdata<T> const&); +  void add_property(double(*)(mcdata<double> const &)); // expected-note{{candidate function not viable: no overload of 'wrap_mean' matching}} +  void f() { +    add_property(&wrap_mean); // expected-error{{no matching function for call to 'add_property'}} +  } +} + +namespace PR7425 { +  template<typename T> +  void foo() +  { +  } + +  struct B +  { +    template<typename T> +    B(const T&) +    { +    } +  }; + +  void bar(const B& b) +  { +  } + +  void bar2(const B& b = foo<int>) +  { +  } + +  void test(int argc, char** argv) +  { +    bar(foo<int>); +    bar2(); +  } +} + +namespace test1 { +  void fun(int x) {} + +  void parameter_number() { +    void (*ptr1)(int, int) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(int, int)' with an rvalue of type 'void (*)(int)': different number of parameters (2 vs 1)}} +    void (*ptr2)(int, int); +    ptr2 = &fun;  // expected-error {{assigning to 'void (*)(int, int)' from incompatible type 'void (*)(int)': different number of parameters (2 vs 1)}} +  } + +  void parameter_mismatch() { +    void (*ptr1)(double) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(double)' with an rvalue of type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} +    void (*ptr2)(double); +    ptr2 = &fun; // expected-error {{assigning to 'void (*)(double)' from incompatible type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} +  } + +  void return_type_test() { +    int (*ptr1)(int) = &fun; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an rvalue of type 'void (*)(int)': different return type ('int' vs 'void')}} +    int (*ptr2)(int); +    ptr2 = &fun;  // expected-error {{assigning to 'int (*)(int)' from incompatible type 'void (*)(int)': different return type ('int' vs 'void')}} +  } + +  int foo(double x, double y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} +  int foo(int x, int y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} +  int foo(double x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'double')}} +  double foo(float x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} +  double foo(int x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} +  double foo(float x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'float')}} +  double foo(int x) {return 0;} // expected-note {{candidate function has different return type ('int' expected but has 'double')}} +   +  int (*ptr)(int) = &foo; // expected-error {{address of overloaded function 'foo' does not match required type 'int (int)'}} + +  struct Qualifiers { +    void N() {}; +    void C() const {}; +    void V() volatile {}; +    void R() __restrict {}; +    void CV() const volatile {}; +    void CR() const __restrict {}; +    void VR() volatile __restrict {}; +    void CVR() const volatile __restrict {}; +  }; + + +  void QualifierTest() { +    void (Qualifiers::*X)(); +    X = &Qualifiers::C; // expected-error {{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const': different qualifiers (none vs const)}} +    X = &Qualifiers::V; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile': different qualifiers (none vs volatile)}} +    X = &Qualifiers::R; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() restrict': different qualifiers (none vs restrict)}} +    X = &Qualifiers::CV; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile': different qualifiers (none vs const and volatile)}} +    X = &Qualifiers::CR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const restrict': different qualifiers (none vs const and restrict)}} +    X = &Qualifiers::VR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile restrict': different qualifiers (none vs volatile and restrict)}} +    X = &Qualifiers::CVR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile restrict': different qualifiers (none vs const, volatile, and restrict)}} +  } + +  struct Dummy { +    void N() {}; +  }; + +  void (Qualifiers::*X)() = &Dummy::N; // expected-error{{cannot initialize a variable of type 'void (test1::Qualifiers::*)()' with an rvalue of type 'void (test1::Dummy::*)()': different classes ('test1::Qualifiers' vs 'test1::Dummy')}} +} diff --git a/clang/test/SemaCXX/address-of-temporary.cpp b/clang/test/SemaCXX/address-of-temporary.cpp new file mode 100644 index 0000000..eb5dee5 --- /dev/null +++ b/clang/test/SemaCXX/address-of-temporary.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-error=address-of-temporary -verify %s +struct X {  +  X(); +  X(int); +  X(int, int); +}; + +void f0() { (void)&X(); } // expected-warning{{taking the address of a temporary object}} +void f1() { (void)&X(1); } // expected-warning{{taking the address of a temporary object}} +void f2() { (void)&X(1, 2); } // expected-warning{{taking the address of a temporary object}} +void f3() { (void)&(X)1; } // expected-warning{{taking the address of a temporary object}} + diff --git a/clang/test/SemaCXX/address-of.cpp b/clang/test/SemaCXX/address-of.cpp new file mode 100644 index 0000000..69fcaff --- /dev/null +++ b/clang/test/SemaCXX/address-of.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR clang/3175 + +void bar(int*); + +class c { +  int var; +  static int svar; +  void foo() {  +    bar(&var);  +    bar(&svar);   +  } + +  static void wibble() { +    bar(&var); // expected-error{{invalid use of member 'var' in static member function}} +    bar(&svar);  +  } +}; + +enum E { +  Enumerator +}; + +void test() { +  (void)&Enumerator; // expected-error{{address expression must be an lvalue or a function designator}} +} + +template<int N> +void test2() { +  (void)&N; // expected-error{{address expression must be an lvalue or a function designator}} +} + +// PR clang/3222 +void xpto(); +void (*xyz)(void) = &xpto; + +struct PR11066 { +  static int foo(short); +  static int foo(float); +  void test(); +}; + +void PR11066::test() { +  int (PR11066::*ptr)(int) = & &PR11066::foo; // expected-error{{address expression must be an lvalue or a function designator}} +} + diff --git a/clang/test/SemaCXX/address-space-conversion.cpp b/clang/test/SemaCXX/address-space-conversion.cpp new file mode 100644 index 0000000..d21d419 --- /dev/null +++ b/clang/test/SemaCXX/address-space-conversion.cpp @@ -0,0 +1,197 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test checks for the various conversions and casting operations +// with address-space-qualified pointers. + +struct A { virtual ~A() {} }; +struct B : A { }; + +typedef void *void_ptr; +typedef void __attribute__((address_space(1))) *void_ptr_1; +typedef void __attribute__((address_space(2))) *void_ptr_2; + +typedef int *int_ptr; +typedef int __attribute__((address_space(1))) *int_ptr_1; +typedef int __attribute__((address_space(2))) *int_ptr_2; + +typedef A *A_ptr; +typedef A __attribute__((address_space(1))) *A_ptr_1; +typedef A __attribute__((address_space(2))) *A_ptr_2; + +typedef B *B_ptr; +typedef B __attribute__((address_space(1))) *B_ptr_1; +typedef B __attribute__((address_space(2))) *B_ptr_2; + +void test_const_cast(int_ptr ip, int_ptr_1 ip1, int_ptr_2 ip2, +                     A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, +                     const int *cip,  +                     const int __attribute__((address_space(1))) *cip1) { +  // Cannot use const_cast to cast between address spaces, add an +  // address space, or remove an address space. +  (void)const_cast<int_ptr>(ip1); // expected-error{{is not allowed}} +  (void)const_cast<int_ptr>(ip2); // expected-error{{is not allowed}} +  (void)const_cast<int_ptr_1>(ip); // expected-error{{is not allowed}} +  (void)const_cast<int_ptr_1>(ip2); // expected-error{{is not allowed}} +  (void)const_cast<int_ptr_2>(ip); // expected-error{{is not allowed}} +  (void)const_cast<int_ptr_2>(ip1); // expected-error{{is not allowed}} + +  (void)const_cast<A_ptr>(ap1); // expected-error{{is not allowed}} +  (void)const_cast<A_ptr>(ap2); // expected-error{{is not allowed}} +  (void)const_cast<A_ptr_1>(ap); // expected-error{{is not allowed}} +  (void)const_cast<A_ptr_1>(ap2); // expected-error{{is not allowed}} +  (void)const_cast<A_ptr_2>(ap); // expected-error{{is not allowed}} +  (void)const_cast<A_ptr_2>(ap1); // expected-error{{is not allowed}} + +  // It's acceptable to cast away constness. +  (void)const_cast<int_ptr>(cip); +  (void)const_cast<int_ptr_1>(cip1); +} + +void test_static_cast(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2, +                      A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, +                      B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2) { +  // Well-formed upcast +  (void)static_cast<A_ptr>(bp); +  (void)static_cast<A_ptr_1>(bp1); +  (void)static_cast<A_ptr_2>(bp2); + +  // Well-formed downcast +  (void)static_cast<B_ptr>(ap); +  (void)static_cast<B_ptr_1>(ap1); +  (void)static_cast<B_ptr_2>(ap2); + +  // Well-formed cast to/from void +  (void)static_cast<void_ptr>(ap); +  (void)static_cast<void_ptr_1>(ap1); +  (void)static_cast<void_ptr_2>(ap2); +  (void)static_cast<A_ptr>(vp); +  (void)static_cast<A_ptr_1>(vp1); +  (void)static_cast<A_ptr_2>(vp2); +   +  // Ill-formed upcasts +  (void)static_cast<A_ptr>(bp1); // expected-error{{is not allowed}} +  (void)static_cast<A_ptr>(bp2); // expected-error{{is not allowed}} +  (void)static_cast<A_ptr_1>(bp); // expected-error{{is not allowed}} +  (void)static_cast<A_ptr_1>(bp2); // expected-error{{is not allowed}} +  (void)static_cast<A_ptr_2>(bp); // expected-error{{is not allowed}} +  (void)static_cast<A_ptr_2>(bp1); // expected-error{{is not allowed}} + +  // Ill-formed downcasts +  (void)static_cast<B_ptr>(ap1); // expected-error{{casts away qualifiers}} +  (void)static_cast<B_ptr>(ap2); // expected-error{{casts away qualifiers}} +  (void)static_cast<B_ptr_1>(ap); // expected-error{{casts away qualifiers}} +  (void)static_cast<B_ptr_1>(ap2); // expected-error{{casts away qualifiers}} +  (void)static_cast<B_ptr_2>(ap); // expected-error{{casts away qualifiers}} +  (void)static_cast<B_ptr_2>(ap1); // expected-error{{casts away qualifiers}} + +  // Ill-formed cast to/from void +  (void)static_cast<void_ptr>(ap1); // expected-error{{is not allowed}} +  (void)static_cast<void_ptr>(ap2); // expected-error{{is not allowed}} +  (void)static_cast<void_ptr_1>(ap); // expected-error{{is not allowed}} +  (void)static_cast<void_ptr_1>(ap2); // expected-error{{is not allowed}} +  (void)static_cast<void_ptr_2>(ap); // expected-error{{is not allowed}} +  (void)static_cast<void_ptr_2>(ap1); // expected-error{{is not allowed}} +  (void)static_cast<A_ptr>(vp1); // expected-error{{casts away qualifiers}} +  (void)static_cast<A_ptr>(vp2); // expected-error{{casts away qualifiers}} +  (void)static_cast<A_ptr_1>(vp); // expected-error{{casts away qualifiers}} +  (void)static_cast<A_ptr_1>(vp2); // expected-error{{casts away qualifiers}} +  (void)static_cast<A_ptr_2>(vp); // expected-error{{casts away qualifiers}} +  (void)static_cast<A_ptr_2>(vp1); // expected-error{{casts away qualifiers}} +} + +void test_dynamic_cast(A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, +                       B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2) { +  // Well-formed upcast +  (void)dynamic_cast<A_ptr>(bp); +  (void)dynamic_cast<A_ptr_1>(bp1); +  (void)dynamic_cast<A_ptr_2>(bp2); + +  // Well-formed downcast +  (void)dynamic_cast<B_ptr>(ap); +  (void)dynamic_cast<B_ptr_1>(ap1); +  (void)dynamic_cast<B_ptr_2>(ap2); + +  // Ill-formed upcasts +  (void)dynamic_cast<A_ptr>(bp1); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<A_ptr>(bp2); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<A_ptr_1>(bp); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<A_ptr_1>(bp2); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<A_ptr_2>(bp); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<A_ptr_2>(bp1); // expected-error{{casts away qualifiers}} + +  // Ill-formed downcasts +  (void)dynamic_cast<B_ptr>(ap1); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<B_ptr>(ap2); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<B_ptr_1>(ap); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<B_ptr_1>(ap2); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<B_ptr_2>(ap); // expected-error{{casts away qualifiers}} +  (void)dynamic_cast<B_ptr_2>(ap1); // expected-error{{casts away qualifiers}} +} + +void test_reinterpret_cast(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2, +                           A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, +                           B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2, +                           const void __attribute__((address_space(1))) *cvp1) { +  // reinterpret_cast can be used to cast to a different address space. +  (void)reinterpret_cast<A_ptr>(ap1); +  (void)reinterpret_cast<A_ptr>(ap2); +  (void)reinterpret_cast<A_ptr>(bp); +  (void)reinterpret_cast<A_ptr>(bp1); +  (void)reinterpret_cast<A_ptr>(bp2); +  (void)reinterpret_cast<A_ptr>(vp); +  (void)reinterpret_cast<A_ptr>(vp1); +  (void)reinterpret_cast<A_ptr>(vp2); +  (void)reinterpret_cast<A_ptr_1>(ap); +  (void)reinterpret_cast<A_ptr_1>(ap2); +  (void)reinterpret_cast<A_ptr_1>(bp); +  (void)reinterpret_cast<A_ptr_1>(bp1); +  (void)reinterpret_cast<A_ptr_1>(bp2); +  (void)reinterpret_cast<A_ptr_1>(vp); +  (void)reinterpret_cast<A_ptr_1>(vp1); +  (void)reinterpret_cast<A_ptr_1>(vp2); + +  // ... but don't try to cast away constness! +  (void)reinterpret_cast<A_ptr_2>(cvp1); // expected-error{{casts away qualifiers}} +} + +void test_cstyle_cast(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2, +                      A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, +                      B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2, +                      const void __attribute__((address_space(1))) *cvp1) { +  // C-style casts are the wild west of casts. +  (void)(A_ptr)(ap1); +  (void)(A_ptr)(ap2); +  (void)(A_ptr)(bp); +  (void)(A_ptr)(bp1); +  (void)(A_ptr)(bp2); +  (void)(A_ptr)(vp); +  (void)(A_ptr)(vp1); +  (void)(A_ptr)(vp2); +  (void)(A_ptr_1)(ap); +  (void)(A_ptr_1)(ap2); +  (void)(A_ptr_1)(bp); +  (void)(A_ptr_1)(bp1); +  (void)(A_ptr_1)(bp2); +  (void)(A_ptr_1)(vp); +  (void)(A_ptr_1)(vp1); +  (void)(A_ptr_1)(vp2); +  (void)(A_ptr_2)(cvp1); +} + +void test_implicit_conversion(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2, +                              A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, +                              B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2) { +  // Well-formed conversions +  void_ptr vpA = ap; +  void_ptr_1 vp_1A = ap1; +  void_ptr_2 vp_2A = ap2; +  A_ptr ap_A = bp; +  A_ptr_1 ap_A1 = bp1; +  A_ptr_2 ap_A2 = bp2; + +  // Ill-formed conversions +  void_ptr vpB = ap1; // expected-error{{cannot initialize a variable of type}} +  void_ptr_1 vp_1B = ap2; // expected-error{{cannot initialize a variable of type}} +  A_ptr ap_B = bp1; // expected-error{{cannot initialize a variable of type}} +  A_ptr_1 ap_B1 = bp2; // expected-error{{cannot initialize a variable of type}} +} diff --git a/clang/test/SemaCXX/address-space-newdelete.cpp b/clang/test/SemaCXX/address-space-newdelete.cpp new file mode 100644 index 0000000..b809cd3 --- /dev/null +++ b/clang/test/SemaCXX/address-space-newdelete.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void* operator new (__SIZE_TYPE__ size, void* ptr); +void* operator new[](__SIZE_TYPE__ size, void* ptr); + +typedef int __attribute__((address_space(1))) int_1; + +void test_new(void *p) { +  (void)new int_1; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +  (void)new __attribute__((address_space(1))) int; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +  (void)new int_1 [5]; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +  (void)new __attribute__((address_space(1))) int [5]; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} + +  // Placement new +  (void)new (p) int_1; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +  (void)new (p) __attribute__((address_space(1))) int; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +  (void)new (p) int_1 [5]; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +  (void)new (p) __attribute__((address_space(1))) int [5]; // expected-error{{'new' cannot allocate objects of type 'int' in address space '1'}} +} + +void test_delete(int_1 *ip1) { +  delete ip1; // expected-error{{'delete' cannot delete objects of type 'int' in address space '1'}} +  delete [] ip1; // expected-error{{'delete' cannot delete objects of type 'int' in address space '1'}} +} diff --git a/clang/test/SemaCXX/address-space-references.cpp b/clang/test/SemaCXX/address-space-references.cpp new file mode 100644 index 0000000..f5a63d2 --- /dev/null +++ b/clang/test/SemaCXX/address-space-references.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef int __attribute__((address_space(1))) int_1; +typedef int __attribute__((address_space(2))) int_2; + +void f0(int_1 &); // expected-note{{candidate function not viable: 1st argument ('int') is in address space 0, but parameter must be in address space 1}} \ +// expected-note{{candidate function not viable: 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')) is in address space 2, but parameter must be in address space 1}} +void f0(const int_1 &); // expected-note{{candidate function not viable: 1st argument ('int') is in address space 0, but parameter must be in address space 1}} \ +// expected-note{{candidate function not viable: 1st argument ('int_2' (aka '__attribute__((address_space(2))) int')) is in address space 2, but parameter must be in address space 1}} + +void test_f0() { +  int i; +  static int_1 i1; +  static int_2 i2; + +  f0(i); // expected-error{{no matching function for call to 'f0'}} +  f0(i1); +  f0(i2); // expected-error{{no matching function for call to 'f0'}} +} diff --git a/clang/test/SemaCXX/aggregate-initialization.cpp b/clang/test/SemaCXX/aggregate-initialization.cpp new file mode 100644 index 0000000..885bf70 --- /dev/null +++ b/clang/test/SemaCXX/aggregate-initialization.cpp @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s  + +// Verify that using an initializer list for a non-aggregate looks for +// constructors.. +// Note that due to a (likely) standard bug, this is technically an aggregate, +// but we do not treat it as one. +struct NonAggr1 { // expected-note 2 {{candidate constructor}} +  NonAggr1(int, int) { } // expected-note {{candidate constructor}} + +  int m; +}; + +struct Base { }; +struct NonAggr2 : public Base { // expected-note 3 {{candidate constructor}} +  int m; +}; + +class NonAggr3 { // expected-note 3 {{candidate constructor}} +  int m; +}; + +struct NonAggr4 { // expected-note 3 {{candidate constructor}} +  int m; +  virtual void f(); +}; + +NonAggr1 na1 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr1'}} +NonAggr2 na2 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr2'}} +NonAggr3 na3 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr3'}} +NonAggr4 na4 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr4'}} + +// PR5817 +typedef int type[][2]; +const type foo = {0}; + +// Vector initialization. +typedef short __v4hi __attribute__ ((__vector_size__ (8))); +__v4hi v1 = { (void *)1, 2, 3 }; // expected-error {{cannot initialize a vector element of type 'short' with an rvalue of type 'void *'}} + +// Array initialization. +int a[] = { (void *)1 }; // expected-error {{cannot initialize an array element of type 'int' with an rvalue of type 'void *'}} + +// Struct initialization. +struct S { int a; } s = { (void *)1 }; // expected-error {{cannot initialize a member subobject of type 'int' with an rvalue of type 'void *'}} + +// Check that we're copy-initializing the structs. +struct A { +  A(); +  A(int); +  ~A(); +   +  A(const A&) = delete; // expected-note 2 {{function has been explicitly marked deleted here}} +}; + +struct B { +  A a; +}; + +struct C { +  const A& a; +}; + +void f() { +  A as1[1] = { }; +  A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}} + +  B b1 = { }; +  B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}} +   +  C c1 = { 1 }; +} + +class Agg { +public: +  int i, j; +}; + +class AggAgg { +public: +  Agg agg1; +  Agg agg2; +}; + +AggAgg aggagg = { 1, 2, 3, 4 }; diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp new file mode 100644 index 0000000..484dd33 --- /dev/null +++ b/clang/test/SemaCXX/alias-template.cpp @@ -0,0 +1,147 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +namespace RedeclAliasTypedef { +  template<typename U> using T = int; +  template<typename U> using T = int; +  template<typename U> using T = T<U>; +} + +namespace IllegalTypeIds { +  template<typename U> using A = void(int n = 0); // expected-error {{default arguments can only be specified for parameters in a function declaration}} +  template<typename U> using B = inline void(int n); // expected-error {{type name does not allow function specifier}} +  template<typename U> using C = virtual void(int n); // expected-error {{type name does not allow function specifier}} +  template<typename U> using D = explicit void(int n); // expected-error {{type name does not allow function specifier}} +  template<typename U> using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}} +  template<typename U> using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}} +  template<typename U> using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}} +  template<typename U> using H = constexpr int; // expected-error {{type name does not allow constexpr specifier}} + +  template<typename U> using Y = void(int n); // ok +  template<typename U> using Z = void(int n) &&; // ok +} + +namespace IllegalSyntax { +  template<typename Z> using ::T = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +  template<typename Z> using operator int = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +  template<typename Z> using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}} +  template<typename Z> using typename ::V = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +  template<typename Z> using typename ::operator bool = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +} + +namespace VariableLengthArrays { +  template<typename Z> using T = int[42]; // ok + +  int n = 32; +  template<typename Z> using T = int[n]; // expected-error {{variable length array declaration not allowed at file scope}} + +  const int m = 42; +  template<typename Z> using U = int[m]; // expected-note {{previous definition}} +  template<typename Z> using U = int[42]; // ok +  template<typename Z> using U = int; // expected-error {{type alias template redefinition with different types ('int' vs 'int [42]')}} +} + +namespace RedeclFunc { +  int f(int, char**); +  template<typename Z> using T = int; +  T<char> f(int, char **); // ok +} + +namespace LookupFilter { +  namespace N { template<typename U> using S = int; } +  using namespace N; +  template<typename U> using S = S<U>*; // ok +} + +namespace InFunctions { +  template<typename...T> struct S0 { +    template<typename Z> using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} +    U<char> u; +  }; + +  template<typename Z> using T1 = int; +  template<typename Z> using T2 = int[-1]; // expected-error {{array size is negative}} +  template<typename...T> struct S3 { // expected-note {{template parameter is declared here}} +    template<typename Z> using T = int; // expected-error {{declaration of 'T' shadows template parameter}} +  }; +  template<typename Z> using Z = Z; +} + +namespace ClassNameRedecl { +  class C0 { +    // FIXME: this diagnostic is pretty poor +    template<typename U> using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}} +  }; +  class C1 { +    // FIXME: this diagnostic is pretty poor +    template<typename U> using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}} +  }; +  class C2 { +    template<typename U> using C0 = C1; // ok +  }; +  template<typename...T> class C3 { +    template<typename U> using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} +  }; +  template<typename T> class C4 { // expected-note {{template parameter is declared here}} +    template<typename U> using T = int; // expected-error {{declaration of 'T' shadows template parameter}} +  }; +  class C5 { +    class c; // expected-note {{previous definition}} +    template<typename U> using c = int; // expected-error {{redefinition of 'c' as different kind of symbol}} +    class d; // expected-note {{previous definition}} +    template<typename U> using d = d; // expected-error {{redefinition of 'd' as different kind of symbol}} +  }; +  class C6 { +    class c { template<typename U> using C6 = int; }; // ok +  }; +} + +class CtorDtorName { +  template<typename T> using X = CtorDtorName; +  X<int>(); // expected-error {{expected member name}} +  ~X<int>(); // expected-error {{destructor cannot be declared using a type alias}} +}; + +namespace TagName { +  template<typename Z> using S = struct { int n; }; // expected-error {{can not be defined}} +  template<typename Z> using T = class { int n; }; // expected-error {{can not be defined}} +  template<typename Z> using U = enum { a, b, c }; // expected-error {{can not be defined}} +  template<typename Z> using V = struct V { int n; }; // expected-error {{redefinition of 'V' as different kind of symbol}} \ +                                                         expected-error {{'TagName::V' can not be defined in a type alias template}} \ +                                                         expected-note {{previous definition is here}} +} + +namespace StdExample { +  template<typename T, typename U> struct pair; + +  template<typename T> using handler_t = void (*)(T); +  extern handler_t<int> ignore; +  extern void (*ignore)(int); +  // FIXME: we recover as if cell is an undeclared variable. the diagnostics are terrible! +  template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} \ +                                                           expected-error {{'T' does not refer to a value}} \ +                                                           expected-note {{declared here}} \ +                                                           expected-error {{expected ';' after alias declaration}} +} + +namespace Access { +  class C0 { +    template<typename Z> using U = int; // expected-note {{declared private here}} +  }; +  C0::U<int> v; // expected-error {{'U' is a private member}} +  class C1 { +  public: +    template<typename Z> using U = int; +  }; +  C1::U<int> w; // ok +} + +namespace VoidArg { +  template<typename Z> using V = void; +  V<int> f(int); // ok +  V<char> g(V<double>); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}} +} + +namespace Curried { +  template<typename T, typename U> struct S; +  template<typename T> template<typename U> using SS = S<T, U>; // expected-error {{extraneous template parameter list in alias template declaration}} +} diff --git a/clang/test/SemaCXX/alignof-sizeof-reference.cpp b/clang/test/SemaCXX/alignof-sizeof-reference.cpp new file mode 100644 index 0000000..ccdf45e --- /dev/null +++ b/clang/test/SemaCXX/alignof-sizeof-reference.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct s0; // expected-note {{forward declaration}} +char ar[sizeof(s0&)]; // expected-error {{invalid application of 'sizeof' to an incomplete type}} +void test() { +  char &r = ar[0]; +  static_assert(alignof(r) == 1, "bad alignment"); +  static_assert(sizeof(r) == 1, "bad size"); +} + +void f();  // expected-note{{possible target for call}} +void f(int);  // expected-note{{possible target for call}} +void g() {  +  sizeof(&f); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} \ +  // expected-warning{{expression result unused}} +} + +template<typename T> void f_template(); // expected-note{{possible target for call}} +template<typename T> void f_template(T*); // expected-note{{possible target for call}} +void rdar9659191() { +  (void)alignof(f_template<int>); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +} diff --git a/clang/test/SemaCXX/altivec.cpp b/clang/test/SemaCXX/altivec.cpp new file mode 100644 index 0000000..39421b7 --- /dev/null +++ b/clang/test/SemaCXX/altivec.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -faltivec -fno-lax-vector-conversions -triple powerpc-unknown-unknown -verify %s + +typedef int V4i __attribute__((vector_size(16))); + +void test_vec_step(vector short arg1) { +  vector bool char vbc; +  vector signed char vsc; +  vector unsigned char vuc; +  vector bool short vbs; +  vector short vs; +  vector unsigned short vus; +  vector pixel vp; +  vector bool int vbi; +  vector int vi; +  vector unsigned int vui; +  vector float vf; + +  vector int *pvi; + +  int res1[vec_step(arg1) == 8 ? 1 : -1]; +  int res2[vec_step(vbc) == 16 ? 1 : -1]; +  int res3[vec_step(vsc) == 16 ? 1 : -1]; +  int res4[vec_step(vuc) == 16 ? 1 : -1]; +  int res5[vec_step(vbs) == 8 ? 1 : -1]; +  int res6[vec_step(vs) == 8 ? 1 : -1]; +  int res7[vec_step(vus) == 8 ? 1 : -1]; +  int res8[vec_step(vp) == 8 ? 1 : -1]; +  int res9[vec_step(vbi) == 4 ? 1 : -1]; +  int res10[vec_step(vi) == 4 ? 1 : -1]; +  int res11[vec_step(vui) == 4 ? 1 : -1]; +  int res12[vec_step(vf) == 4 ? 1 : -1]; +  int res13[vec_step(*pvi) == 4 ? 1 : -1]; +} + +void f(V4i a) +{ +} + +void test1() +{ +  V4i vGCC; +  vector int vAltiVec; + +  f(vAltiVec); +  vGCC = vAltiVec; +  bool res = vGCC > vAltiVec; +  vAltiVec = 0 ? vGCC : vGCC; +} + +template<typename T> +void template_f(T param) { +  param++; +} + +void test2() +{ +  vector int vi; +  ++vi; +  vi++; +  --vi; +  vi--; +  vector float vf; +  vf++; + +  ++vi=vi; +  (++vi)[1]=1; +  template_f(vi); +} + +namespace LValueToRValueConversions { +  struct Struct { +    float f(); +    int n(); +  }; + +  vector float initFloat = (vector float)(Struct().f); // expected-error {{did you mean to call it}} +  vector int initInt = (vector int)(Struct().n); // expected-error {{did you mean to call it}} +} diff --git a/clang/test/SemaCXX/ambig-user-defined-conversions.cpp b/clang/test/SemaCXX/ambig-user-defined-conversions.cpp new file mode 100644 index 0000000..1a3c102 --- /dev/null +++ b/clang/test/SemaCXX/ambig-user-defined-conversions.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { +  struct BASE {  +    operator int &(); // expected-note {{candidate function}} +  };  +  struct BASE1 {  +    operator int &(); // expected-note {{candidate function}} +  };  + +  struct B : public BASE, BASE1 {}; + +  extern B f();  +  B b1; + +  void func(const int ci, const char cc); // expected-note {{candidate function}} +  void func(const char ci, const B b); // expected-note {{candidate function}} +  void func(const B b, const int ci); // expected-note {{candidate function}} + +  const int Test1() { + +    func(b1, f()); // expected-error {{call to 'func' is ambiguous}} +    return f(); // expected-error {{conversion from 'test0::B' to 'const int' is ambiguous}} +  } + +  // This used to crash when comparing the two operands. +  void func2(const char cc); // expected-note {{candidate function}} +  void func2(const int ci); // expected-note {{candidate function}} +  void Test2() { +    func2(b1); // expected-error {{call to 'func2' is ambiguous}} +  } +} + +namespace test1 { +  struct E; +  struct A {  +    A (E&);  +  }; + +  struct E {  +    operator A ();  +  }; + +  struct C {  +    C (E&);   +  }; + +  void f1(A);	// expected-note {{candidate function}} +  void f1(C);	// expected-note {{candidate function}} + +  void Test2() +  { +    E b; +    f1(b);  // expected-error {{call to 'f1' is ambiguous}}	 +            // ambiguous because b -> C via constructor and +            // b -> A via constructor or conversion function. +  } +} + +namespace rdar8876150 { +  struct A { operator bool(); }; +  struct B : A { }; +  struct C : A { }; +  struct D : B, C { }; + +  bool f(D d) { return !d; } // expected-error{{ambiguous conversion from derived class 'rdar8876150::D' to base class 'rdar8876150::A':}} +} diff --git a/clang/test/SemaCXX/ambiguous-builtin-unary-operator.cpp b/clang/test/SemaCXX/ambiguous-builtin-unary-operator.cpp new file mode 100644 index 0000000..6e96e03 --- /dev/null +++ b/clang/test/SemaCXX/ambiguous-builtin-unary-operator.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct A { +  operator int&(); +  operator long*& (); +}; + +struct B { +  operator long&(); +  operator int*& (); +}; + +struct C : B, A { }; + +void test(C c) { +  ++c; // expected-error {{use of overloaded operator '++' is ambiguous}}\ +       // expected-note {{built-in candidate operator++(int &)}} \ +       // expected-note {{built-in candidate operator++(long &)}} \ +       // expected-note {{built-in candidate operator++(long *&)}} \ +       // expected-note {{built-in candidate operator++(int *&)}} +} + +struct A1 { operator volatile int&(); }; + +struct B1 { operator volatile long&(); }; + +struct C1 : B1, A1 { }; + +void test(C1 c) { +  ++c;	// expected-error {{use of overloaded operator '++' is ambiguous}} \ +	// expected-note {{built-in candidate operator++(volatile int &)}} \ +	// expected-note {{built-in candidate operator++(volatile long &)}} +} + diff --git a/clang/test/SemaCXX/anonymous-struct.cpp b/clang/test/SemaCXX/anonymous-struct.cpp new file mode 100644 index 0000000..19a88d7 --- /dev/null +++ b/clang/test/SemaCXX/anonymous-struct.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct S { +  S();  // expected-note {{because type 'S' has a user-declared constructor}}     +}; + +struct { // expected-error {{anonymous structs and classes must be class members}} +}; + +struct E { +  struct { +    S x;  // expected-error {{anonymous struct member 'x' has a non-trivial constructor}}  +  }; +  static struct { +  }; +}; diff --git a/clang/test/SemaCXX/anonymous-union.cpp b/clang/test/SemaCXX/anonymous-union.cpp new file mode 100644 index 0000000..2dd7ab8 --- /dev/null +++ b/clang/test/SemaCXX/anonymous-union.cpp @@ -0,0 +1,199 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s +struct X { +  union { +    float f3; +    double d2; +  } named; + +  union { +    int i; +    float f; +     +    union { +      float f2; +      mutable double d; +    }; +  }; + +  void test_unqual_references(); + +  struct { // expected-warning{{anonymous structs are a GNU extension}} +    int a; +    float b; +  }; + +  void test_unqual_references_const() const; + +  mutable union { // expected-error{{anonymous union at class scope must not have a storage specifier}} +    float c1; +    double c2; +  }; +}; + +void X::test_unqual_references() { +  i = 0; +  f = 0.0; +  f2 = f; +  d = f; +  f3 = 0; // expected-error{{use of undeclared identifier 'f3'}} +  a = 0; +} + +void X::test_unqual_references_const() const { +  d = 0.0; +  f2 = 0; // expected-error{{read-only variable is not assignable}} +  a = 0; // expected-error{{read-only variable is not assignable}} +} + +void test_unqual_references(X x, const X xc) { +  x.i = 0; +  x.f = 0.0; +  x.f2 = x.f; +  x.d = x.f; +  x.f3 = 0; // expected-error{{no member named 'f3'}} +  x.a = 0; + +  xc.d = 0.0; +  xc.f = 0; // expected-error{{read-only variable is not assignable}} +  xc.a = 0; // expected-error{{read-only variable is not assignable}} +} + + +struct Redecl { +  int x; // expected-note{{previous declaration is here}} +  class y { }; + +  union { +    int x; // expected-error{{member of anonymous union redeclares 'x'}} +    float y; +    double z; // expected-note{{previous declaration is here}} +    double zz; // expected-note{{previous definition is here}} +  }; + +  int z; // expected-error{{duplicate member 'z'}} +  void zz(); // expected-error{{redefinition of 'zz' as different kind of symbol}} +}; + +union { // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} +  int int_val; +  float float_val; +}; + +static union { +  int int_val2; +  float float_val2; +}; + +void f() { +  int_val2 = 0; +  float_val2 = 0.0; +} + +void g() { +  union { +    int i; +    float f2; +  }; +  i = 0; +  f2 = 0.0; +} + +struct BadMembers { +  union { +    struct X { }; // expected-error {{types cannot be declared in an anonymous union}} +    struct { int x; int y; } y; +     +    void f(); // expected-error{{functions cannot be declared in an anonymous union}} +  private: int x1; // expected-error{{anonymous union cannot contain a private data member}} +  protected: float x2; // expected-error{{anonymous union cannot contain a protected data member}} +  }; +}; + +// <rdar://problem/6481130> +typedef union { }; // expected-warning{{declaration does not declare anything}} + +// <rdar://problem/7562438> +typedef struct objc_module *Foo ; + +typedef struct _s { +    union { +        int a; +        int Foo; +    }; +} s, *ps; + +// <rdar://problem/7987650> +namespace test4 { +  class A { +    struct { // expected-warning{{anonymous structs are a GNU extension}} +      int s0; // expected-note {{declared private here}} +      double s1; // expected-note {{declared private here}} +      union { +        int su0; // expected-note {{declared private here}} +        double su1; // expected-note {{declared private here}} +      }; +    }; +    union { +      int u0; // expected-note {{declared private here}} +      double u1; // expected-note {{declared private here}} +      struct { // expected-warning{{anonymous structs are a GNU extension}} +        int us0; // expected-note {{declared private here}} +        double us1; // expected-note {{declared private here}} +      }; +    }; +  }; + +  void test() { +    A a; +    (void) a.s0;  // expected-error {{private member}} +    (void) a.s1;  // expected-error {{private member}} +    (void) a.su0; // expected-error {{private member}} +    (void) a.su1; // expected-error {{private member}} +    (void) a.u0;  // expected-error {{private member}} +    (void) a.u1;  // expected-error {{private member}} +    (void) a.us0; // expected-error {{private member}} +    (void) a.us1; // expected-error {{private member}} +  } +} + +typedef void *voidPtr; + +void f2() { +    union { int **ctxPtr; void **voidPtr; }; +} + +void foo_PR6741() { +    union { +        char *m_a; +        int *m_b; +    }; +  +    if(1) { +        union { +            char *m_a; +            int *m_b; +        }; +    } +} + +namespace PR8326 { +  template <class T> +  class Foo { +  public: +    Foo() +      : x(0) +      , y(1){ +    } +   +  private: +    const union { // expected-warning{{anonymous union cannot be 'const'}} +      struct { // expected-warning{{anonymous structs are a GNU extension}} +        T x; +        T y; +      }; +      T v[2]; +    }; +  }; + +  Foo<int> baz; +} diff --git a/clang/test/SemaCXX/array-bound-merge.cpp b/clang/test/SemaCXX/array-bound-merge.cpp new file mode 100644 index 0000000..74f58fa --- /dev/null +++ b/clang/test/SemaCXX/array-bound-merge.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR5515 + +extern int a[]; +int a[10]; +extern int b[10]; +int b[]; +extern int c[1]; +int c[] = {1,2}; // expected-error {{excess elements in array initializer}} diff --git a/clang/test/SemaCXX/array-bounds-ptr-arith.cpp b/clang/test/SemaCXX/array-bounds-ptr-arith.cpp new file mode 100644 index 0000000..16e2567 --- /dev/null +++ b/clang/test/SemaCXX/array-bounds-ptr-arith.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -verify -Wno-string-plus-int -Warray-bounds-pointer-arithmetic %s + +void swallow (const char *x) { (void)x; } +void test_pointer_arithmetic(int n) { +  const char hello[] = "Hello world!"; // expected-note 2 {{declared here}} +  const char *helloptr = hello; + +  swallow("Hello world!" + 6); // no-warning +  swallow("Hello world!" - 6); // expected-warning {{refers before the beginning of the array}} +  swallow("Hello world!" + 14); // expected-warning {{refers past the end of the array}} +  swallow("Hello world!" + 13); // no-warning + +  swallow(hello + 6); // no-warning +  swallow(hello - 6); // expected-warning {{refers before the beginning of the array}} +  swallow(hello + 14); // expected-warning {{refers past the end of the array}} +  swallow(hello + 13); // no-warning + +  swallow(helloptr + 6); // no-warning +  swallow(helloptr - 6); // no-warning +  swallow(helloptr + 14); // no-warning +  swallow(helloptr + 13); // no-warning + +  double numbers[2]; // expected-note {{declared here}} +  swallow((char*)numbers + sizeof(double)); // no-warning +  swallow((char*)numbers + 60); // expected-warning {{refers past the end of the array}} + +  char buffer[5]; // expected-note 2 {{declared here}} +  // TODO: Add FixIt notes for adding parens around non-ptr part of arith expr +  swallow(buffer + sizeof("Hello")-1); // expected-warning {{refers past the end of the array}} +  swallow(buffer + (sizeof("Hello")-1)); // no-warning +  if (n > 0 && n <= 6) swallow(buffer + 6 - n); // expected-warning {{refers past the end of the array}} +  if (n > 0 && n <= 6) swallow(buffer + (6 - n)); // no-warning +} diff --git a/clang/test/SemaCXX/array-bounds-system-header.cpp b/clang/test/SemaCXX/array-bounds-system-header.cpp new file mode 100644 index 0000000..34de5b5 --- /dev/null +++ b/clang/test/SemaCXX/array-bounds-system-header.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -isystem %S/Inputs -verify %s +#include <array-bounds-system-header.h> +void test_system_header_macro() { +  BAD_MACRO_1; // no-warning +  char a[3]; // expected-note 2 {{declared here}} +  BAD_MACRO_2(a, 3); // expected-warning {{array index 3}} +  QUESTIONABLE_MACRO(a); +  NOP(a[3] = 5); // expected-warning {{array index 3}} +} diff --git a/clang/test/SemaCXX/array-bounds.cpp b/clang/test/SemaCXX/array-bounds.cpp new file mode 100644 index 0000000..57a9e3d --- /dev/null +++ b/clang/test/SemaCXX/array-bounds.cpp @@ -0,0 +1,255 @@ +// RUN: %clang_cc1 -verify %s + +int foo() { +  int x[2]; // expected-note 4 {{array 'x' declared here}} +  int y[2]; // expected-note 2 {{array 'y' declared here}} +  int z[1]; // expected-note {{array 'z' declared here}} +  int w[1][1]; // expected-note {{array 'w' declared here}} +  int v[1][1][1]; // expected-note {{array 'v' declared here}} +  int *p = &y[2]; // no-warning +  (void) sizeof(x[2]); // no-warning +  y[2] = 2; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +  z[1] = 'x'; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}} +  w[0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}} +  v[0][0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}} +  return x[2] +  // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +         y[-1] + // expected-warning {{array index -1 is before the beginning of the array}} +         x[sizeof(x)] +  // expected-warning {{array index 8 is past the end of the array (which contains 2 elements)}} +         x[sizeof(x) / sizeof(x[0])] +  // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +         x[sizeof(x) / sizeof(x[0]) - 1] + // no-warning +         x[sizeof(x[2])]; // expected-warning {{array index 4 is past the end of the array (which contains 2 elements)}} +} + +// This code example tests that -Warray-bounds works with arrays that +// are template parameters. +template <char *sz> class Qux { +  bool test() { return sz[0] == 'a'; } +}; + +void f1(int a[1]) { +  int val = a[3]; // no warning for function argumnet +} + +void f2(const int (&a)[2]) { // expected-note {{declared here}} +  int val = a[3];  // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} +} + +void test() { +  struct { +    int a[0]; +  } s2; +  s2.a[3] = 0; // no warning for 0-sized array + +  union { +    short a[2]; // expected-note 4 {{declared here}} +    char c[4]; +  } u; +  u.a[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} +  u.c[3] = 1; // no warning +  short *p = &u.a[2]; // no warning +  p = &u.a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} +  *(&u.a[2]) = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +  *(&u.a[3]) = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} +  *(&u.c[3]) = 1; // no warning + +  const int const_subscript = 3; +  int array[2]; // expected-note {{declared here}} +  array[const_subscript] = 0;  // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + +  int *ptr; +  ptr[3] = 0; // no warning for pointer references +  int array2[] = { 0, 1, 2 }; // expected-note 2 {{declared here}} + +  array2[3] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 3 elements)}} +  array2[2+2] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}} + +  const char *str1 = "foo"; +  char c1 = str1[5]; // no warning for pointers + +  const char str2[] = "foo"; // expected-note {{declared here}} +  char c2 = str2[5]; // expected-warning {{array index 5 is past the end of the array (which contains 4 elements)}} + +  int (*array_ptr)[2]; +  (*array_ptr)[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} +} + +template <int I> struct S { +  char arr[I]; // expected-note 2 {{declared here}} +}; +template <int I> void f() { +  S<3> s; +  s.arr[4] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}} +  s.arr[I] = 0; // expected-warning {{array index 5 is past the end of the array (which contains 3 elements)}} +} + +void test_templates() { +  f<5>(); // expected-note {{in instantiation}} +} + +#define SIZE 10 +#define ARR_IN_MACRO(flag, arr, idx) flag ? arr[idx] : 1 + +int test_no_warn_macro_unreachable() { +  int arr[SIZE]; // expected-note {{array 'arr' declared here}} +  return ARR_IN_MACRO(0, arr, SIZE) + // no-warning +         ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index 10 is past the end of the array (which contains 10 elements)}} +} + +// This exhibited an assertion failure for a 32-bit build of Clang. +int test_pr9240() { +  short array[100]; // expected-note {{array 'array' declared here}} +  return array[(unsigned long long) 100]; // expected-warning {{array index 100 is past the end of the array (which contains 100 elements)}} +} + +// PR 9284 - a template parameter can cause an array bounds access to be +// infeasible. +template <bool extendArray> +void pr9284() { +    int arr[3 + (extendArray ? 1 : 0)]; + +    if (extendArray) +        arr[3] = 42; // no-warning +} + +template <bool extendArray> +void pr9284b() { +    int arr[3 + (extendArray ? 1 : 0)]; // expected-note {{array 'arr' declared here}} + +    if (!extendArray) +        arr[3] = 42; // expected-warning{{array index 3 is past the end of the array (which contains 3 elements)}} +} + +void test_pr9284() { +    pr9284<true>(); +    pr9284<false>(); +    pr9284b<true>(); +    pr9284b<false>(); // expected-note{{in instantiation of function template specialization 'pr9284b<false>' requested here}} +} + +int test_pr9296() { +    int array[2]; +    return array[true]; // no-warning +} + +int test_sizeof_as_condition(int flag) { +  int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}} +  if (flag)  +    return sizeof(char) != sizeof(char) ? arr[2] : arr[1]; +  return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +} + +void test_switch() { +  switch (4) { +    case 1: { +      int arr[2]; +      arr[2] = 1; // no-warning +      break; +    } +    case 4: { +      int arr[2]; // expected-note {{array 'arr' declared here}} +      arr[2] = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +      break; +    } +    default: { +      int arr[2]; +      arr[2] = 1; // no-warning +      break; +    } +  } +} + +// Test nested switch statements. +enum enumA { enumA_A, enumA_B, enumA_C, enumA_D, enumA_E }; +enum enumB { enumB_X, enumB_Y, enumB_Z }; +static enum enumB myVal = enumB_X; +void test_nested_switch() { +  switch (enumA_E) { // expected-warning {{no case matching constant}} +    switch (myVal) { // expected-warning {{enumeration values 'enumB_X' and 'enumB_Z' not handled in switch}} +      case enumB_Y: ; +    } +  } +} + +// Test that if all the values of an enum covered, that the 'default' branch +// is unreachable. +enum Values { A, B, C, D }; +void test_all_enums_covered(enum Values v) { +  int x[2]; +  switch (v) { +  case A: return; +  case B: return; +  case C: return; +  case D: return; +  } +  x[2] = 0; // no-warning +} + +namespace tailpad { +  struct foo { +    char c1[1]; // expected-note {{declared here}} +    int x; +    char c2[1]; +  }; + +  class baz { +   public: +    char c1[1]; // expected-note {{declared here}} +    int x; +    char c2[1]; +  }; + +  char bar(struct foo *F, baz *B) { +    return F->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} +           F->c2[3] + // no warning, foo could have tail padding allocated. +           B->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} +           B->c2[3]; // no warning, baz could have tail padding allocated. +  } +} + +namespace metaprogramming { +#define ONE 1 +  struct foo { char c[ONE]; }; // expected-note {{declared here}} +  template <int N> struct bar { char c[N]; }; // expected-note {{declared here}} + +  char test(foo *F, bar<1> *B) { +    return F->c[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} +           B->c[3]; // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} +  } +} + +void bar(int x) {} +int test_more() { +  int foo[5]; // expected-note 5 {{array 'foo' declared here}} +  bar(foo[5]); // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} +  ++foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} +  if (foo[6]) // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}} +    return --foo[6]; // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}} +  else +    return foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} +} + +void test_pr10771() { +    double foo[4096];  // expected-note {{array 'foo' declared here}} + +    ((char*)foo)[sizeof(foo) - 1] = '\0';  // no-warning +    *(((char*)foo) + sizeof(foo) - 1) = '\0';  // no-warning + +    ((char*)foo)[sizeof(foo)] = '\0';  // expected-warning {{array index 32768 is past the end of the array (which contains 32768 elements)}} + +    // TODO: This should probably warn, too. +    *(((char*)foo) + sizeof(foo)) = '\0';  // no-warning +} + +int test_pr11007_aux(const char * restrict, ...); +   +// Test checking with varargs. +void test_pr11007() { +  double a[5]; // expected-note {{array 'a' declared here}} +  test_pr11007_aux("foo", a[1000]); // expected-warning {{array index 1000 is past the end of the array}} +} + +void test_rdar10916006(void) +{ +	int a[128]; // expected-note {{array 'a' declared here}} +	a[(unsigned char)'\xA1'] = 1; // expected-warning {{array index 161 is past the end of the array}} +} diff --git a/clang/test/SemaCXX/arrow-operator.cpp b/clang/test/SemaCXX/arrow-operator.cpp new file mode 100644 index 0000000..6535a0a --- /dev/null +++ b/clang/test/SemaCXX/arrow-operator.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct T {  +  void f(); +}; + +struct A { +  T* operator->(); // expected-note{{candidate function}} +}; + +struct B { +  T* operator->(); // expected-note{{candidate function}} +}; + +struct C : A, B { +}; + +struct D : A { }; + +struct E; // expected-note {{forward declaration of 'E'}} + +void f(C &c, D& d, E& e) { +  c->f(); // expected-error{{use of overloaded operator '->' is ambiguous}} +  d->f(); +  e->f(); // expected-error{{incomplete definition of type}} +} + +// rdar://8875304 +namespace rdar8875304 { +class Point {}; +class Line_Segment{ public: Line_Segment(const Point&){} }; +class Node { public: Point Location(){ Point p; return p; } }; + +void f() +{ +   Node** node1; +   Line_Segment(node1->Location()); // expected-error {{not a structure or union}} +} +} diff --git a/clang/test/SemaCXX/atomic-type.cxx b/clang/test/SemaCXX/atomic-type.cxx new file mode 100644 index 0000000..18707eb --- /dev/null +++ b/clang/test/SemaCXX/atomic-type.cxx @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -verify %s + +template<typename T> struct atomic { +  _Atomic(T) value; +}; + +template<typename T> struct user { +  struct inner { char n[sizeof(T)]; }; +  atomic<inner> i; +}; + +user<int> u; + +// Test overloading behavior of atomics. +struct A { }; + +int &ovl1(_Atomic(int)); +long &ovl1(_Atomic(long)); +float &ovl1(_Atomic(float)); +double &ovl1(_Atomic(A const *const *)); +short &ovl1(_Atomic(A **)); + +void test_overloading(int i, float f, _Atomic(int) ai, _Atomic(float) af, +                      long l, _Atomic(long) al, A const *const *acc, +                      A const ** ac, A **a) { +  int& ir1 = ovl1(i); +  int& ir2 = ovl1(ai); +  long& lr1 = ovl1(l); +  long& lr2 = ovl1(al); +  float &fr1 = ovl1(f); +  float &fr2 = ovl1(af); +  double &dr1 = ovl1(acc); +  double &dr2 = ovl1(ac); +  short &sr1 = ovl1(a); +} diff --git a/clang/test/SemaCXX/attr-after-definition.cpp b/clang/test/SemaCXX/attr-after-definition.cpp new file mode 100644 index 0000000..148a63e --- /dev/null +++ b/clang/test/SemaCXX/attr-after-definition.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct X { }; +struct Y { }; + +bool f0(X) { return true; } // expected-note{{definition}} +bool f1(X) { return true; } + +__attribute__ ((__visibility__("hidden"))) bool f0(X); // expected-warning{{attribute}} +__attribute__ ((__visibility__("hidden"))) bool f1(Y); diff --git a/clang/test/SemaCXX/attr-cxx0x.cpp b/clang/test/SemaCXX/attr-cxx0x.cpp new file mode 100644 index 0000000..4281895 --- /dev/null +++ b/clang/test/SemaCXX/attr-cxx0x.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +int align_illegal alignas(3); //expected-error {{requested alignment is not a power of 2}} +char align_big alignas(int); +int align_small alignas(1); // FIXME: this should be rejected +int align_multiple alignas(1) alignas(8) alignas(1); + +struct align_member { +  int member alignas(8); +}; + +template <unsigned A> struct alignas(A) align_class_template {}; + +// FIXME: these should not error +template <typename... T> alignas(T...) struct align_class_temp_pack_type {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}} +template <unsigned... A> alignas(A...) struct align_class_temp_pack_expr {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}} + +typedef char align_typedef alignas(8); +template<typename T> using align_alias_template = align_typedef; + +static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong"); +static_assert(alignof(align_small) == 1, "j's alignment is wrong"); +static_assert(alignof(align_multiple) == 8, "l's alignment is wrong"); +static_assert(alignof(align_member) == 8, "quuux's alignment is wrong"); +static_assert(sizeof(align_member) == 8, "quuux's size is wrong"); +static_assert(alignof(align_typedef) == 8, "typedef's alignment is wrong"); +static_assert(alignof(align_class_template<8>) == 8, "template's alignment is wrong"); +static_assert(alignof(align_class_template<16>) == 16, "template's alignment is wrong"); +// FIXME: enable these tests +// static_assert(alignof(align_class_temp_pack_type<short, int, long>) == alignof(long), "template's alignment is wrong"); +// static_assert(alignof(align_class_temp_pack_expr<8, 16, 32>) == 32, "template's alignment is wrong"); +static_assert(alignof(align_alias_template<int>) == 8, "alias template's alignment is wrong"); diff --git a/clang/test/SemaCXX/attr-declspec-ignored.cpp b/clang/test/SemaCXX/attr-declspec-ignored.cpp new file mode 100644 index 0000000..0503750 --- /dev/null +++ b/clang/test/SemaCXX/attr-declspec-ignored.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +namespace test1 { +  __attribute__((visibility("hidden")))  __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \ +  // expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}} +  __attribute__((visibility("hidden")))  __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \ +  // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}} +  __attribute__((visibility("hidden")))  __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \ +  // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}}  +  __attribute__((visibility("hidden")))  __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \ +  // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}} +} + +namespace test2 { +  __attribute__((visibility("hidden")))  __attribute__((aligned)) class A {} a; +  __attribute__((visibility("hidden")))  __attribute__((aligned)) struct B {} b; +  __attribute__((visibility("hidden")))  __attribute__((aligned)) union C {} c; +  __attribute__((visibility("hidden")))  __attribute__((aligned)) enum D {D} d; +} diff --git a/clang/test/SemaCXX/attr-deprecated.cpp b/clang/test/SemaCXX/attr-deprecated.cpp new file mode 100644 index 0000000..46568aa --- /dev/null +++ b/clang/test/SemaCXX/attr-deprecated.cpp @@ -0,0 +1,235 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only +class A { +  void f() __attribute__((deprecated)); +  void g(A* a); +  void h(A* a) __attribute__((deprecated)); + +  int b __attribute__((deprecated)); +}; + +void A::g(A* a) +{ +  f(); // expected-warning{{'f' is deprecated}} +  a->f(); // expected-warning{{'f' is deprecated}} +   +  (void)b; // expected-warning{{'b' is deprecated}} +  (void)a->b; // expected-warning{{'b' is deprecated}} +} + +void A::h(A* a) +{ +  f(); +  a->f(); +   +  (void)b; +  (void)a->b; +} + +struct B { +  virtual void f() __attribute__((deprecated)); +  void g(); +}; + +void B::g() { +  f(); +  B::f(); // expected-warning{{'f' is deprecated}} +} + +struct C : B { +  virtual void f(); +  void g(); +}; + +void C::g() { +  f(); +  C::f(); +  B::f(); // expected-warning{{'f' is deprecated}} +} + +void f(B* b, C *c) { +  b->f(); +  b->B::f(); // expected-warning{{'f' is deprecated}} +   +  c->f(); +  c->C::f(); +  c->B::f(); // expected-warning{{'f' is deprecated}} +} + +struct D { +  virtual void f() __attribute__((deprecated)); +}; + +void D::f() { } + +void f(D* d) { +  d->f(); +} + + +// Overloaded namespace members. +namespace test1 { +  void foo(int) __attribute__((deprecated)); +  void test1() { foo(10); } // expected-warning {{deprecated}} +  void foo(short) __attribute__((deprecated)); +  void test2(short s) { foo(s); } // expected-warning {{deprecated}} +  void foo(long); +  void test3(long l) { foo(l); } +  struct A { +    friend void foo(A*) __attribute__((deprecated)); +  }; +  void test4(A *a) { foo(a); } // expected-warning {{deprecated}} + +  namespace ns { +    struct Foo {}; +    void foo(const Foo &f) __attribute__((deprecated)); +  } +  void test5() { +    foo(ns::Foo()); // expected-warning {{deprecated}} +  } +} + +// Overloaded class members. +namespace test2 { +  struct A { +    void foo(int) __attribute__((deprecated)); +    void foo(long); +    static void bar(int) __attribute__((deprecated)); +    static void bar(long); + +    void test2(int i, long l); +  }; +  void test1(int i, long l) { +    A a; +    a.foo(i); // expected-warning {{deprecated}} +    a.foo(l); +    a.bar(i); // expected-warning {{deprecated}} +    a.bar(l); +    A::bar(i); // expected-warning {{deprecated}} +    A::bar(l); +  } + +  void A::test2(int i, long l) { +    foo(i); // expected-warning {{deprecated}} +    foo(l); +    bar(i); // expected-warning {{deprecated}} +    bar(l); +  } +} + +// Overloaded operators. +namespace test3 { +  struct A { +    void operator*(const A &); +    void operator*(int) __attribute__((deprecated)); +    void operator-(const A &) const; +  }; +  void operator+(const A &, const A &); +  void operator+(const A &, int) __attribute__((deprecated)); +  void operator-(const A &, int) __attribute__((deprecated)); + +  void test() { +    A a, b; +    a + b; +    a + 1; // expected-warning {{deprecated}} +    a - b; +    a - 1; // expected-warning {{deprecated}} +    a * b; +    a * 1; // expected-warning {{deprecated}} +  } +} + +// Overloaded operator call. +namespace test4 { +  struct A { +    typedef void (*intfn)(int); +    typedef void (*unintfn)(unsigned); +    operator intfn() __attribute__((deprecated)); +    operator unintfn(); +    void operator ()(A &) __attribute__((deprecated)); +    void operator ()(const A &); +  }; + +  void test() { +    A a; +    a(1); // expected-warning {{deprecated}} +    a(1U); + +    A &b = a; +    const A &c = a; +    a(b); // expected-warning {{deprecated}} +    a(c); +  } +} + +namespace test5 { +  struct A { +    operator int() __attribute__((deprecated)); +    operator long(); +  }; +  void test1(A a) { +    int i = a; // expected-warning {{deprecated}} +    long l = a; +  } + +  void foo(int); +  void foo(void*); +  void bar(long); +  void bar(void*); +  void test2(A a) { +    foo(a); // expected-warning {{deprecated}} +    bar(a); +  } + +  struct B { +    int myInt; +    long myLong; + +    B(A &a) : +      myInt(a), // expected-warning {{deprecated}} +      myLong(a) +    {} +  }; +} + +// rdar://problem/8518751 +namespace test6 { +  enum __attribute__((deprecated)) A { +    a0 +  }; +  void testA() { +    A x; // expected-warning {{'A' is deprecated}} +    x = a0; // expected-warning {{'a0' is deprecated}} +  } +   +  enum B { +    b0 __attribute__((deprecated)), +    b1 +  }; +  void testB() { +    B x; +    x = b0; // expected-warning {{'b0' is deprecated}} +    x = b1; +  } + +  template <class T> struct C { +    enum __attribute__((deprecated)) Enum { +      c0 +    }; +  }; +  void testC() { +    C<int>::Enum x; // expected-warning {{'Enum' is deprecated}} +    x = C<int>::c0; // expected-warning {{'c0' is deprecated}} +  } + +  template <class T> struct D { +    enum Enum { +      d0, +      d1 __attribute__((deprecated)), +    }; +  }; +  void testD() { +    D<int>::Enum x; +    x = D<int>::d0; +    x = D<int>::d1; // expected-warning {{'d1' is deprecated}} +  } +} diff --git a/clang/test/SemaCXX/attr-format.cpp b/clang/test/SemaCXX/attr-format.cpp new file mode 100644 index 0000000..da134a1 --- /dev/null +++ b/clang/test/SemaCXX/attr-format.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -Wformat-nonliteral -verify %s +struct S { +  static void f(const char*, ...) __attribute__((format(printf, 1, 2))); +  static const char* f2(const char*) __attribute__((format_arg(1))); + +  // GCC has a hidden 'this' argument in member functions which is why +  // the format argument is argument 2 here. +  void g(const char*, ...) __attribute__((format(printf, 2, 3))); +  const char* g2(const char*) __attribute__((format_arg(2))); + +  void h(const char*, ...) __attribute__((format(printf, 1, 4))); // \ +      expected-error{{implicit this argument as the format string}} +  void h2(const char*, ...) __attribute__((format(printf, 2, 1))); // \ +      expected-error{{out of bounds}} +  const char* h3(const char*) __attribute__((format_arg(1))); // \ +      expected-error{{invalid for the implicit this argument}} +}; + +// PR5521 +struct A { void a(const char*,...) __attribute((format(printf,2,3))); }; +void b(A x) { +  x.a("%d", 3); +} + +// PR8625: correctly interpret static member calls as not having an implicit +// 'this' argument. +namespace PR8625 { +  struct S { +    static void f(const char*, const char*, ...) +      __attribute__((format(printf, 2, 3))); +  }; +  void test(S s, const char* str) { +    s.f(str, "%s", str); +  } +} diff --git a/clang/test/SemaCXX/attr-nonnull.cpp b/clang/test/SemaCXX/attr-nonnull.cpp new file mode 100644 index 0000000..09c054c --- /dev/null +++ b/clang/test/SemaCXX/attr-nonnull.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct S { +  S(const char *) __attribute__((nonnull(2))); + +  static void f(const char*, const char*) __attribute__((nonnull(1))); + +  // GCC has a hidden 'this' argument in member functions, so the middle +  // argument is the one that must not be null. +  void g(const char*, const char*, const char*) __attribute__((nonnull(3))); + +  void h(const char*) __attribute__((nonnull(1))); // \ +      expected-error{{invalid for the implicit this argument}} +}; + +void test() { +  S s(0); // expected-warning{{null passed}} + +  s.f(0, ""); // expected-warning{{null passed}} +  s.f("", 0); +  s.g("", 0, ""); // expected-warning{{null passed}} +  s.g(0, "", 0); +} + +namespace rdar8769025 { +  __attribute__((nonnull)) void f0(int *&p); +  __attribute__((nonnull)) void f1(int * const &p); +  __attribute__((nonnull(2))) void f2(int i, int * const &p); + +  void test_f1() { +    f1(0); // expected-warning{{null passed to a callee which requires a non-null argument}} +    f2(0, 0); // expected-warning{{null passed to a callee which requires a non-null argument}} +  } +} diff --git a/clang/test/SemaCXX/attr-noreturn.cpp b/clang/test/SemaCXX/attr-noreturn.cpp new file mode 100644 index 0000000..eaf0d0c --- /dev/null +++ b/clang/test/SemaCXX/attr-noreturn.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Reachability tests have to come first because they get suppressed +// if any errors have occurred. +namespace test5 { +  struct A { +    __attribute__((noreturn)) void fail(); +    void nofail(); +  } a; + +  int &test1() { +    a.nofail(); +  } // expected-warning {{control reaches end of non-void function}} + +  int &test2() { +    a.fail(); +  } +} + +// PR5620 +void f0() __attribute__((__noreturn__)); +void f1(void (*)());  +void f2() { f1(f0); } + +// Taking the address of a noreturn function +void test_f0a() { +  void (*fp)() = f0; +  void (*fp1)() __attribute__((noreturn)) = f0; +} + +// Taking the address of an overloaded noreturn function  +void f0(int) __attribute__((__noreturn__)); + +void test_f0b() { +  void (*fp)() = f0; +  void (*fp1)() __attribute__((noreturn)) = f0; +} + +// No-returned function pointers +typedef void (* noreturn_fp)() __attribute__((noreturn)); + +void f3(noreturn_fp); // expected-note{{candidate function}} + +void test_f3() { +  f3(f0); // okay +  f3(f2); // expected-error{{no matching function for call}} +} + + +class xpto { +  int blah() __attribute__((noreturn)); +}; + +int xpto::blah() { +  return 3; // expected-warning {{function 'blah' declared 'noreturn' should not return}} +} diff --git a/clang/test/SemaCXX/attr-regparm.cpp b/clang/test/SemaCXX/attr-regparm.cpp new file mode 100644 index 0000000..91ee613 --- /dev/null +++ b/clang/test/SemaCXX/attr-regparm.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin10 %s + +// PR7025 +struct X0 { +  void __attribute__((regparm(3))) f0(); +  void __attribute__((regparm(3))) f1(); +  void __attribute__((regparm(3))) f2(); // expected-note{{previous declaration is here}} +  void f3(); // expected-note{{previous declaration is here}} +}; + +void X0::f0() { } +void __attribute__((regparm(3))) X0::f1() { } +void __attribute__((regparm(2))) X0::f2() { } // expected-error{{function declared with with regparm(2) attribute was previously declared with the regparm(3) attribute}} +void __attribute__((regparm(2))) X0::f3() { } // expected-error{{function declared with with regparm(2) attribute was previously declared without the regparm attribute}} diff --git a/clang/test/SemaCXX/attr-sentinel.cpp b/clang/test/SemaCXX/attr-sentinel.cpp new file mode 100644 index 0000000..92c6e21 --- /dev/null +++ b/clang/test/SemaCXX/attr-sentinel.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f(int, ...) __attribute__((sentinel)); + +void g() { +  f(1, 2, __null); +} + +typedef __typeof__(sizeof(int)) size_t; + +struct S { +  S(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} +  void a(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} +  void* operator new(size_t,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} +  void operator()(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} +}; + +void class_test() { +  S s(1,2,3); // expected-warning {{missing sentinel in function call}} +  S* s2 = new (1,2,3) S(1, __null); // expected-warning {{missing sentinel in function call}} +  s2->a(1,2,3); // expected-warning {{missing sentinel in function call}} +  s(1,2,3); // expected-warning {{missing sentinel in function call}} +} diff --git a/clang/test/SemaCXX/attr-unavailable.cpp b/clang/test/SemaCXX/attr-unavailable.cpp new file mode 100644 index 0000000..2d82668 --- /dev/null +++ b/clang/test/SemaCXX/attr-unavailable.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int &foo(int); // expected-note {{candidate}} +double &foo(double); // expected-note {{candidate}} +void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ +// expected-note{{function has been explicitly marked unavailable here}} + +void bar(...) __attribute__((__unavailable__)); // expected-note 2{{explicitly marked unavailable}} + +void test_foo(short* sp) { +  int &ir = foo(1); +  double &dr = foo(1.0); +  foo(sp); // expected-error{{call to unavailable function 'foo'}} + +  void (*fp)(...) = &bar; // expected-error{{'bar' is unavailable}} +  void (*fp2)(...) = bar; // expected-error{{'bar' is unavailable}} + +  int &(*fp3)(int) = foo; +  void (*fp4)(...) = foo; // expected-error{{'foo' is unavailable}} +} + +namespace radar9046492 { +// rdar://9046492 +#define FOO __attribute__((unavailable("not available - replaced"))) + +void foo() FOO; // expected-note {{candidate function has been explicitly made unavailable}} +void bar() { +  foo(); // expected-error {{call to unavailable function 'foo': not available - replaced}} +} +} + +void unavail(short* sp)  __attribute__((__unavailable__)); +void unavail(short* sp) { +  // No complains inside an unavailable function. +  int &ir = foo(1); +  double &dr = foo(1.0); +  foo(sp); +  foo(); +} diff --git a/clang/test/SemaCXX/attr-weak.cpp b/clang/test/SemaCXX/attr-weak.cpp new file mode 100644 index 0000000..b6a9e0a --- /dev/null +++ b/clang/test/SemaCXX/attr-weak.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s + +static int test0 __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} +static void test1() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} + +namespace test2 __attribute__((weak)) { // expected-warning {{'weak' attribute only applies to variables and functions}} +} + +namespace { +  int test3 __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} +  void test4() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} +} + +struct Test5 { +  static void test5() __attribute__((weak)); // no error +}; + +namespace { +  struct Test6 { +    static void test6() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} +  }; +} + +template <class T> struct Test7 { +  void test7() __attribute__((weak)) {} +}; +namespace { class Internal; } +template struct Test7<Internal>; +template struct Test7<int>; diff --git a/clang/test/SemaCXX/attr-weakref.cpp b/clang/test/SemaCXX/attr-weakref.cpp new file mode 100644 index 0000000..a345791 --- /dev/null +++ b/clang/test/SemaCXX/attr-weakref.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s + +// GCC will accept anything as the argument of weakref. Should we +// check for an existing decl? +static int a1() __attribute__((weakref ("foo"))); +static int a2() __attribute__((weakref, alias ("foo"))); + +static int a3 __attribute__((weakref ("foo"))); +static int a4 __attribute__((weakref, alias ("foo"))); + +// gcc rejects, clang accepts +static int a5 __attribute__((alias ("foo"), weakref)); + +// this is pointless, but accepted by gcc. We reject it. +static int a6 __attribute__((weakref)); //expected-error {{weakref declaration of 'a6' must also have an alias attribute}} + +// gcc warns, clang rejects +void f(void) { +  static int a __attribute__((weakref ("v2"))); // expected-error {{declaration of 'a' must be in a global context}} +} + +// both gcc and clang reject +class c { +  static int a __attribute__((weakref ("v2"))); // expected-error {{declaration of 'a' must be in a global context}} +  static int b() __attribute__((weakref ("f3"))); // expected-error {{declaration of 'b' must be in a global context}} +}; +int a7() __attribute__((weakref ("f1"))); // expected-error {{weakref declaration must have internal linkage}} +int a8 __attribute__((weakref ("v1"))); // expected-error {{weakref declaration must have internal linkage}} + +// gcc accepts this +int a9 __attribute__((weakref)); // expected-error {{weakref declaration must have internal linkage}} diff --git a/clang/test/SemaCXX/auto-cxx0x.cpp b/clang/test/SemaCXX/auto-cxx0x.cpp new file mode 100644 index 0000000..a8f9e84 --- /dev/null +++ b/clang/test/SemaCXX/auto-cxx0x.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +void f() { +  auto int a; // expected-warning {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}} +  int auto b; // expected-error{{cannot combine with previous 'int' declaration specifier}} +} diff --git a/clang/test/SemaCXX/auto-cxx98.cpp b/clang/test/SemaCXX/auto-cxx98.cpp new file mode 100644 index 0000000..1e28d06 --- /dev/null +++ b/clang/test/SemaCXX/auto-cxx98.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wc++11-compat  +void f() { +  auto int a; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} +  int auto b; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} +  auto c; // expected-warning {{C++11 extension}} expected-error {{requires an initializer}} +  static auto d = 0; // expected-warning {{C++11 extension}} +  auto static e = 0; // expected-warning {{C++11 extension}} +} diff --git a/clang/test/SemaCXX/auto-subst-failure.cpp b/clang/test/SemaCXX/auto-subst-failure.cpp new file mode 100644 index 0000000..b323dfc --- /dev/null +++ b/clang/test/SemaCXX/auto-subst-failure.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +void f() { +  auto a = f(); // expected-error {{variable has incomplete type 'void'}} +  auto &b = f(); // expected-error {{cannot form a reference to 'void'}} +  auto *c = f(); // expected-error {{incompatible initializer of type 'void'}} + +  auto d(f()); // expected-error {{variable has incomplete type 'void'}} +  auto &&e(f()); // expected-error {{cannot form a reference to 'void'}} +  auto *g(f()); // expected-error {{incompatible initializer of type 'void'}} + +  (void)new auto(f()); // expected-error {{allocation of incomplete type 'void'}} +  (void)new auto&(f()); // expected-error {{cannot form a reference to 'void'}} +  (void)new auto*(f()); // expected-error {{incompatible constructor argument of type 'void'}} +} diff --git a/clang/test/SemaCXX/bitfield-layout.cpp b/clang/test/SemaCXX/bitfield-layout.cpp new file mode 100644 index 0000000..adecf55 --- /dev/null +++ b/clang/test/SemaCXX/bitfield-layout.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=x86_64-apple-darwin10 + +#define CHECK_SIZE(name, size) extern int name##1[sizeof(name) == size ? 1 : -1]; +#define CHECK_ALIGN(name, size) extern int name##2[__alignof(name) == size ? 1 : -1]; + +// Simple tests. +struct Test1 { +  char c : 9; // expected-warning {{size of bit-field 'c' (9 bits) exceeds the size of its type; value will be truncated to 8 bits}} +}; +CHECK_SIZE(Test1, 2); +CHECK_ALIGN(Test1, 1); + +struct Test2 { +  char c : 16; // expected-warning {{size of bit-field 'c' (16 bits) exceeds the size of its type; value will be truncated to 8 bits}} +}; +CHECK_SIZE(Test2, 2); +CHECK_ALIGN(Test2, 2); + +struct Test3 { +  char c : 32; // expected-warning {{size of bit-field 'c' (32 bits) exceeds the size of its type; value will be truncated to 8 bits}} +}; +CHECK_SIZE(Test3, 4); +CHECK_ALIGN(Test3, 4); + +struct Test4 { +  char c : 64; // expected-warning {{size of bit-field 'c' (64 bits) exceeds the size of its type; value will be truncated to 8 bits}} +}; +CHECK_SIZE(Test4, 8); +CHECK_ALIGN(Test4, 8); + diff --git a/clang/test/SemaCXX/block-call.cpp b/clang/test/SemaCXX/block-call.cpp new file mode 100644 index 0000000..d519911 --- /dev/null +++ b/clang/test/SemaCXX/block-call.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s -fblocks + +int (*FP)(); +int (^IFP) (); +int (^II) (int); +int main() { +  int (*FPL) (int) = FP; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an lvalue of type 'int (*)()'}}  + +  // For Blocks, the ASTContext::typesAreBlockCompatible() makes sure this is an error. +  int (^PFR) (int) = IFP; // expected-error {{cannot initialize a variable of type 'int (^)(int)' with an lvalue of type 'int (^)()'}} +  PFR = II;       // OK + +  int (^IFP) () = PFR; // OK + + +  const int (^CIC) () = IFP; // OK -  initializing 'const int (^)()' with an expression of type 'int (^)()'}} + +  const int (^CICC) () = CIC; + + +  int * const (^IPCC) () = 0; + +  int * const (^IPCC1) () = IPCC; + +  int * (^IPCC2) () = IPCC;       // expected-error  {{cannot initialize a variable of type 'int *(^)()' with an lvalue of type 'int *const (^)()'}} + +  int (^IPCC3) (const int) = PFR; + +  int (^IPCC4) (int, char (^CArg) (double)); + +  int (^IPCC5) (int, char (^CArg) (double)) = IPCC4; + +  int (^IPCC6) (int, char (^CArg) (float))  = IPCC4; // expected-error {{cannot initialize a variable of type 'int (^)(int, char (^)(float))' with an lvalue of type}} + +  IPCC2 = 0; +  IPCC2 = 1;  +  int (^x)() = 0; +  int (^y)() = 3;   // expected-error {{cannot initialize a variable of type 'int (^)()' with an rvalue of type 'int'}} +  int a = 1; +  int (^z)() = a+4;   // expected-error {{cannot initialize a variable of type 'int (^)()' with an rvalue of type 'int'}} +} + +int blah() { +  int (^IFP) (float); +  char (^PCP)(double, double, char); + +  IFP(1.0); +  IFP (1.0, 2.0); // expected-error {{too many arguments to block call}} + +  char ch = PCP(1.0, 2.0, 'a'); +  return PCP(1.0, 2.0);   // expected-error {{too few arguments to block}} +} diff --git a/clang/test/SemaCXX/blocks-1.cpp b/clang/test/SemaCXX/blocks-1.cpp new file mode 100644 index 0000000..1b15094 --- /dev/null +++ b/clang/test/SemaCXX/blocks-1.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++11 + +extern "C" int exit(int); + +typedef struct { +    unsigned long ps[30]; +    int qs[30]; +} BobTheStruct; + +int main (int argc, const char * argv[]) { +    BobTheStruct inny; +    BobTheStruct outty; +    BobTheStruct (^copyStruct)(BobTheStruct); +    int i; +     +    for(i=0; i<30; i++) { +        inny.ps[i] = i * i * i; +        inny.qs[i] = -i * i * i; +    } +     +    copyStruct = ^(BobTheStruct aBigStruct){ return aBigStruct; };  // pass-by-value intrinsically copies the argument +     +    outty = copyStruct(inny); + +    if ( &inny == &outty ) { +        exit(1); +    } +    for(i=0; i<30; i++) { +        if ( (inny.ps[i] != outty.ps[i]) || (inny.qs[i] != outty.qs[i]) ) { +            exit(1); +        } +    } +     +    return 0; +} + +namespace rdar8134521 { +  void foo() { +    int (^P)(int) = reinterpret_cast<int(^)(int)>(1); +    P = (int(^)(int))(1); +     +    P = reinterpret_cast<int(^)(int)>((void*)1); +    P = (int(^)(int))((void*)1); +  } +} + +namespace rdar11055105 { +  struct A { +    void foo(); +  }; + +  template <class T> void foo(T &x) noexcept(noexcept(x.foo())); + +  void (^block)() = ^{ +    A a; +    foo(a); +  }; +} diff --git a/clang/test/SemaCXX/blocks.cpp b/clang/test/SemaCXX/blocks.cpp new file mode 100644 index 0000000..adbff55 --- /dev/null +++ b/clang/test/SemaCXX/blocks.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks + +void tovoid(void*); + +void tovoid_test(int (^f)(int, int)) { +  tovoid(f); +} + +void reference_lvalue_test(int& (^f)()) { +  f() = 10; +} + +// PR 7165 +namespace test1 { +  void g(void (^)()); +  struct Foo { +    void foo();    +    void test() { +      (void) ^{ foo(); }; +    } +  }; +} + +namespace test2 { +  int repeat(int value, int (^block)(int), unsigned n) { +    while (n--) value = block(value); +    return value; +  } + +  class Power { +    int base; + +  public: +    Power(int base) : base(base) {} +    int calculate(unsigned n) { +      return repeat(1, ^(int v) { return v * base; }, n); +    } +  }; + +  int test() { +    return Power(2).calculate(10); +  } +} + +// rdar: // 8382559 +namespace radar8382559 { +  void func(bool& outHasProperty); + +  int test3() { +    __attribute__((__blocks__(byref))) bool hasProperty = false; +    bool has = true; + +    bool (^b)() = ^ { +     func(hasProperty); +     if (hasProperty) +       hasProperty = 0; +     if (has) +       hasProperty = 1; +     return hasProperty; +     }; +    func(hasProperty); +    func(has); +    b(); +    if (hasProperty) +      hasProperty = 1; +    if (has) +      has = 2; +    return hasProperty = 1; +  } +} diff --git a/clang/test/SemaCXX/bool.cpp b/clang/test/SemaCXX/bool.cpp new file mode 100644 index 0000000..2b3ab68 --- /dev/null +++ b/clang/test/SemaCXX/bool.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +// Bool literals can be enum values. +enum { +  ReadWrite = false, +  ReadOnly = true +}; + +// bool cannot be decremented, and gives a warning on increment +void test(bool b) +{ +  ++b; // expected-warning {{incrementing expression of type bool is deprecated}} +  b++; // expected-warning {{incrementing expression of type bool is deprecated}} +  --b; // expected-error {{cannot decrement expression of type bool}} +  b--; // expected-error {{cannot decrement expression of type bool}} + +  bool *b1 = (int *)0; // expected-error{{cannot initialize}} +} + +// static_assert_arg_is_bool(x) compiles only if x is a bool. +template <typename T> +void static_assert_arg_is_bool(T x) { +  bool* p = &x; +} + +void test2() { +  int n = 2; +  static_assert_arg_is_bool(n && 4);  // expected-warning {{use of logical '&&' with constant operand}} \ +                                      // expected-note {{use '&' for a bitwise operation}} \ +                                      // expected-note {{remove constant to silence this warning}} +  static_assert_arg_is_bool(n || 5);  // expected-warning {{use of logical '||' with constant operand}} \ +                                      // expected-note {{use '|' for a bitwise operation}} +} diff --git a/clang/test/SemaCXX/borland-extensions.cpp b/clang/test/SemaCXX/borland-extensions.cpp new file mode 100644 index 0000000..4831530 --- /dev/null +++ b/clang/test/SemaCXX/borland-extensions.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -fborland-extensions + +// Borland extensions + +// 1. test  -fborland-extensions +int dummy_function() { return 0; } + +// 2. test __pascal +int _pascal f2(); + +float __pascal gi2(int, int);  +template<typename T> T g2(T (__pascal * const )(int, int)) { return 0; } + +struct M { +    int __pascal addP(); +    float __pascal subtractP();  +}; +template<typename T> int h2(T (__pascal M::* const )()) { return 0; } +void m2() { +    int i; float f; +    i = f2(); +    f = gi2(2, i); +    f = g2(gi2); +    i = h2<int>(&M::addP); +    f = h2(&M::subtractP); +}  + +// 3. test other calling conventions +int _cdecl fa3(); +int _fastcall fc3(); +int _stdcall fd3(); + +// 4. test __uuidof() +typedef struct _GUID { +     unsigned long  Data1; +     unsigned short Data2; +     unsigned short Data3; +     unsigned char  Data4[ 8 ]; +} GUID; + +struct __declspec(uuid("{12345678-1234-1234-1234-123456789abc}")) Foo; +struct Data { +     GUID const* Guid; +}; + +void t4() { +    unsigned long  data; + +    const GUID guid_inl = __uuidof(Foo); +    Data ata1 = { &guid_inl}; +    data = ata1.Guid->Data1; +} + diff --git a/clang/test/SemaCXX/builtin-exception-spec.cpp b/clang/test/SemaCXX/builtin-exception-spec.cpp new file mode 100644 index 0000000..324d20e --- /dev/null +++ b/clang/test/SemaCXX/builtin-exception-spec.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -verify %s +#include <malloc.h> + +extern "C" { +void *malloc(__SIZE_TYPE__); +} diff --git a/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp b/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp new file mode 100644 index 0000000..61e3478 --- /dev/null +++ b/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct A {}; + +struct R { +    operator const A*(); +}; + + +struct B  : R { +    operator A*(); +}; + +struct C : B { + +}; + + +void foo(C c, int A::* pmf) { +       				// FIXME. Why so many built-in candidates? +	int i = c->*pmf; 	// expected-error {{use of overloaded operator '->*' is ambiguous}} \ +				// expected-note {{built-in candidate operator->*(const struct A *, const int struct A::*)}} \ +				// expected-note {{built-in candidate operator->*(const struct A *, int struct A::*)}} \ +				// expected-note {{built-in candidate operator->*(struct A *, const int struct A::*)}} \ +				// expected-note {{built-in candidate operator->*(struct A *, int struct A::*)}} +} + diff --git a/clang/test/SemaCXX/builtin-ptrtomember-overload-1.cpp b/clang/test/SemaCXX/builtin-ptrtomember-overload-1.cpp new file mode 100644 index 0000000..2d93c6b --- /dev/null +++ b/clang/test/SemaCXX/builtin-ptrtomember-overload-1.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct A {}; +struct E {}; + +struct R { +    operator A*(); +    operator E*();	// expected-note{{candidate function}} +}; + + +struct S { +    operator A*(); +    operator E*();	// expected-note{{candidate function}} +}; + +struct B  : R { +    operator A*(); +}; + +struct C : B { + +}; + +void foo(C c, int A::* pmf) { +	int i = c->*pmf;  +} + +struct B1  : R, S { +    operator A*(); +}; + +struct C1 : B1 { + +}; + +void foo1(C1 c1, int A::* pmf) { +        int i = c1->*pmf; +        c1->*pmf = 10; +} + +void foo1(C1 c1, int E::* pmf) { +        int i = c1->*pmf;	// expected-error {{use of overloaded operator '->*' is ambiguous}} \ +                                // expected-note {{because of ambiguity in conversion of 'C1' to 'E *'}} \ +                                // expected-note 4 {{built-in candidate operator}} +} diff --git a/clang/test/SemaCXX/builtin-ptrtomember-overload.cpp b/clang/test/SemaCXX/builtin-ptrtomember-overload.cpp new file mode 100644 index 0000000..c7b5173 --- /dev/null +++ b/clang/test/SemaCXX/builtin-ptrtomember-overload.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct A {}; + +struct B { +	operator A*(); +}; + +struct C : B { + +}; + + +void foo(C c, B b, int A::* pmf) { +	int j = c->*pmf;  +	int i = b->*pmf; +} + +struct D { + operator const D *(); +}; + +struct DPtr { + operator volatile int D::*(); +}; + +int test(D d, DPtr dptr) { + return d->*dptr; +} + diff --git a/clang/test/SemaCXX/builtin_objc_msgSend.cpp b/clang/test/SemaCXX/builtin_objc_msgSend.cpp new file mode 100644 index 0000000..0e90d54 --- /dev/null +++ b/clang/test/SemaCXX/builtin_objc_msgSend.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +// rdar://8686888 + +typedef struct objc_selector *SEL; +typedef struct objc_object *id; + +extern "C" __attribute__((visibility("default"))) id objc_msgSend(id self, SEL op, ...) +    __attribute__((visibility("default"))); + +inline void TCFReleaseGC(void * object) +{ + static SEL SEL_release; + objc_msgSend((id)object, SEL_release); +} diff --git a/clang/test/SemaCXX/builtins.cpp b/clang/test/SemaCXX/builtins.cpp new file mode 100644 index 0000000..568ba5d --- /dev/null +++ b/clang/test/SemaCXX/builtins.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +typedef const struct __CFString * CFStringRef; +#define CFSTR __builtin___CFStringMakeConstantString + +void f() { +  (void)CFStringRef(CFSTR("Hello")); +} + +void a() { __builtin_va_list x, y; ::__builtin_va_copy(x, y); } diff --git a/clang/test/SemaCXX/c99-variable-length-array.cpp b/clang/test/SemaCXX/c99-variable-length-array.cpp new file mode 100644 index 0000000..7773c08 --- /dev/null +++ b/clang/test/SemaCXX/c99-variable-length-array.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wvla %s +struct NonPOD { +  NonPOD(); +}; + +struct NonPOD2 { +  NonPOD np; +}; + +struct POD { +  int x; +  int y; +}; + +// We allow VLAs of POD types, only. +void vla(int N) { +  int array1[N]; // expected-warning{{variable length arrays are a C99 feature}} +  POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}} +  NonPOD array3[N]; // expected-error{{variable length array of non-POD element type 'NonPOD'}} +  NonPOD2 array4[N][3]; // expected-error{{variable length array of non-POD element type 'NonPOD2'}} +} + +/// Warn about VLAs in templates. +template<typename T> +void vla_in_template(int N, T t) { +  int array1[N]; // expected-warning{{variable length arrays are a C99 feature}} +} + +struct HasConstantValue { +  static const unsigned int value = 2; +}; + +struct HasNonConstantValue { +  static unsigned int value; +}; + +template<typename T> +void vla_in_template(T t) { +  int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature}} +} + +template void vla_in_template<HasConstantValue>(HasConstantValue); +template void vla_in_template<HasNonConstantValue>(HasNonConstantValue); // expected-note{{instantiation of}} + +template<typename T> struct X0 { }; + +// Cannot use any variably-modified type with a template parameter or +// argument. +void inst_with_vla(int N) { +  int array[N]; // expected-warning{{variable length arrays are a C99 feature}} +  X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int [N]') cannot be used as a template argument}} +} + +template<typename T> +struct X1 { +  template<int (&Array)[T::value]> // expected-error{{non-type template parameter of variably modified type 'int (&)[HasNonConstantValue::value]'}}  \ +  // expected-warning{{variable length arrays are a C99 feature}} +  struct Inner { +     +  }; +}; + +X1<HasConstantValue> x1a; +X1<HasNonConstantValue> x1b; // expected-note{{in instantiation of}} + +// Template argument deduction does not allow deducing a size from a VLA. +template<typename T, unsigned N> +void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: failed template argument deduction}} + +void test_accept_array(int N) { +  int array[N]; // expected-warning{{variable length arrays are a C99 feature}} +  accept_array(array); // expected-error{{no matching function for call to 'accept_array'}} +} + +// Variably-modified types cannot be used in local classes. +void local_classes(int N) { // expected-note {{declared here}} +  struct X { +    int size; +    int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \ +                  // expected-error{{reference to local variable 'N' declared in enclosing function 'local_classes'}} \ +                  // expected-warning{{variable length arrays are a C99 feature}} +  }; +} + +namespace PR7206 { +  void f(int x) { +    struct edge_info { +      float left; +      float right; +    }; +    struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature}} +  } +} + +namespace rdar8020206 { +  template<typename T> +  void f(int i) { +    const unsigned value = i; +    int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature}} +  } + +  template void f<int>(int); // expected-note{{instantiation of}} +} + +namespace rdar8021385 { +  typedef int my_int; +  struct A { typedef int my_int; }; +  template<typename T> +  struct B { +    typedef typename T::my_int my_int; +    void f0() { +      int M = 4; +      my_int a[M]; // expected-warning{{variable length arrays are a C99 feature}} +    } +  }; +  B<A> a; +} + +namespace PR8209 { +  void f(int n) { +    typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature}} +    (void)new vla_type; // expected-error{{variably}} +  } +} + +namespace rdar8733881 { // rdar://8733881 + +static const int k_cVal3 = (int)(1000*0.2f); +  int f() { +    // Ok, fold to a constant size array as an extension. +    char rgch[k_cVal3] = {0}; +  } +} + +namespace PR11744 { +  template<typename T> int f(int n) { +    T arr[3][n]; // expected-warning 3 {{variable length arrays are a C99 feature}} +    return 3; +  } +  int test = f<int>(0); // expected-note {{instantiation of}} +} diff --git a/clang/test/SemaCXX/c99.cpp b/clang/test/SemaCXX/c99.cpp new file mode 100644 index 0000000..13918dc --- /dev/null +++ b/clang/test/SemaCXX/c99.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +void f1(int i[static 5]) { // expected-error{{C99}} +} + +struct Point { int x; int y; }; + +Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature}} +             y: 25 }; // expected-warning{{designated initializers are a C99 feature}} \ +                      // expected-warning{{use of GNU old-style field designator extension}} diff --git a/clang/test/SemaCXX/cast-conversion.cpp b/clang/test/SemaCXX/cast-conversion.cpp new file mode 100644 index 0000000..dd2bc98 --- /dev/null +++ b/clang/test/SemaCXX/cast-conversion.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct R { +  R(int); +}; + +struct A { +  A(R); +}; + +struct B { // expected-note 3 {{candidate constructor (the implicit copy constructor) not viable}} \ +              expected-note 3 {{candidate constructor (the implicit move constructor) not viable}} +  B(A); // expected-note 3 {{candidate constructor not viable}} +}; + +int main () { +  B(10);	// expected-error {{no matching conversion for functional-style cast from 'int' to 'B'}} +  (B)10;	// expected-error {{no matching conversion for C-style cast from 'int' to 'B'}} +  static_cast<B>(10);	// expected-error {{no matching conversion for static_cast from 'int' to 'B'}} \\ +			// expected-warning {{expression result unused}} +} + +template<class T> +struct X0 { +  X0(const T &); +}; + +template<class T> +X0<T> make_X0(const T &Val) { +  return X0<T>(Val); +} + +void test_X0() { +  const char array[2] = { 'a', 'b' }; +  make_X0(array); +} + +// PR5210 recovery +class C { +protected: +  template <int> float* &f0(); // expected-note{{candidate}} +  template <unsigned> float* &f0(); // expected-note{{candidate}} + +  void f1() { +    static_cast<float*>(f0<0>()); // expected-error{{ambiguous}} +  } +}; diff --git a/clang/test/SemaCXX/cast-explicit-ctor.cpp b/clang/test/SemaCXX/cast-explicit-ctor.cpp new file mode 100644 index 0000000..0052856 --- /dev/null +++ b/clang/test/SemaCXX/cast-explicit-ctor.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct B { explicit B(bool); }; +void f() {  +  (void)(B)true; +  (void)B(true);  +} diff --git a/clang/test/SemaCXX/class-base-member-init.cpp b/clang/test/SemaCXX/class-base-member-init.cpp new file mode 100644 index 0000000..e84e57b --- /dev/null +++ b/clang/test/SemaCXX/class-base-member-init.cpp @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +class S { +public: +  S ();  +}; + +struct D : S { +  D() :  +    b1(0), // expected-note {{previous initialization is here}} +    b2(1), +    b1(0), // expected-error {{multiple initializations given for non-static member 'b1'}} +    S(),   // expected-note {{previous initialization is here}} +    S()    // expected-error {{multiple initializations given for base 'S'}} +    {} +  int b1; +  int b2; +}; + +struct A { +  struct { +    int a; +    int b;  +  }; +  A(); +}; + +A::A() : a(10), b(20) { } + +namespace Test1 { +  template<typename T> struct A {}; +  template<typename T> struct B : A<T> { + +    B() : A<T>(), // expected-note {{previous initialization is here}}  +      A<T>() { } // expected-error {{multiple initializations given for base 'A<T>'}} +  }; +} + +namespace Test2 { +  template<typename T> struct A : T { +    A() : T(), // expected-note {{previous initialization is here}} +      T() { } // expected-error {{multiple initializations given for base 'T'}} +  }; +} + +namespace Test3 { +  template<typename T> struct A { +    T t; +     +    A() : t(1), // expected-note {{previous initialization is here}} +      t(2) { } // expected-error {{multiple initializations given for non-static member 't'}} +  }; +} + +namespace test4 { +  class A { +    union { +      struct { +        int a; +        int b; +      }; + +      int c; + +      union { +        int d; +        int e; +      }; +    }; + +    A(char _) : a(0), b(0) {} +    A(short _) : a(0), c(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}} +    A(int _) : d(0), e(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}} +    A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}} +  }; +} + +namespace test5 { +  struct Base { +    Base(int); +  }; +  struct A : Base { +    A() : decltype(Base(1))(3) { +    } +    A(int) : Base(3), // expected-note {{previous initialization is here}} +             decltype(Base(1))(2), // expected-error {{multiple initializations given for base 'decltype(test5::Base(1))' (aka 'test5::Base')}} +             decltype(int())() { // expected-error {{constructor initializer 'decltype(int())' (aka 'int') does not name a class}} +    } +    A(float) : decltype(A())(3) { +    } +  }; +} diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp new file mode 100644 index 0000000..d81944a --- /dev/null +++ b/clang/test/SemaCXX/class-layout.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify  + +#define SA(n, p) int a##n[(p) ? 1 : -1] + +struct A { +  int a; +  char b; +}; + +SA(0, sizeof(A) == 8); + +struct B : A { +  char c; +}; + +SA(1, sizeof(B) == 12); + +struct C { +// Make fields private so C won't be a POD type. +private: +  int a; +  char b; +}; + +SA(2, sizeof(C) == 8); + +struct D : C { +  char c; +}; + +SA(3, sizeof(D) == 8); + +struct __attribute__((packed)) E { +  char b; +  int a; +}; + +SA(4, sizeof(E) == 5); + +struct __attribute__((packed)) F : E { +  char d; +}; + +SA(5, sizeof(F) == 6); + +struct G { G(); }; +struct H : G { }; + +SA(6, sizeof(H) == 1); + +struct I { +  char b; +  int a; +} __attribute__((packed)); + +SA(6_1, sizeof(I) == 5); + +// PR5580 +namespace PR5580 { + +class A { bool iv0 : 1; }; +SA(7, sizeof(A) == 1);   + +class B : A { bool iv0 : 1; }; +SA(8, sizeof(B) == 2); + +struct C { bool iv0 : 1; }; +SA(9, sizeof(C) == 1);   + +struct D : C { bool iv0 : 1; }; +SA(10, sizeof(D) == 2); + +} + +namespace Test1 { + +// Test that we don't assert on this hierarchy. +struct A { }; +struct B : A { virtual void b(); }; +class C : virtual A { int c; }; +struct D : virtual B { }; +struct E : C, virtual D { }; +class F : virtual E { }; +struct G : virtual E, F { }; + +SA(0, sizeof(G) == 24); + +} + +namespace Test2 { + +// Test that this somewhat complex class structure is laid out correctly. +struct A { }; +struct B : A { virtual void b(); }; +struct C : virtual B { }; +struct D : virtual A { }; +struct E : virtual B, D { }; +struct F : E, virtual C { }; +struct G : virtual F, A { }; +struct H { G g; }; + +SA(0, sizeof(H) == 24); + +} diff --git a/clang/test/SemaCXX/class-names.cpp b/clang/test/SemaCXX/class-names.cpp new file mode 100644 index 0000000..2962988 --- /dev/null +++ b/clang/test/SemaCXX/class-names.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class C { }; + +C c; + +void D(int); + +class D {}; + +void foo() +{ +  D(5); +  class D d; +} + +class D; // expected-note {{previous use is here}} + +enum D; // expected-error {{use of 'D' with tag type that does not match previous declaration}} + +class A * A; + +class A * a2; + +void bar() +{ +  A = 0; +} + +void C(int); + +void bar2() +{ +  C(17); +} + +extern int B; +class B; +class B {}; +int B; + +enum E { e1_val }; +E e1; + +void E(int); + +void bar3() { +  E(17); +} + +enum E e2; + +enum E2 { E2 }; diff --git a/clang/test/SemaCXX/class.cpp b/clang/test/SemaCXX/class.cpp new file mode 100644 index 0000000..4dffc8d --- /dev/null +++ b/clang/test/SemaCXX/class.cpp @@ -0,0 +1,197 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s  +class C { +public: +  auto int errx; // expected-error {{storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}} +  register int erry; // expected-error {{storage class specified for a member declaration}} +  extern int errz; // expected-error {{storage class specified for a member declaration}} + +  static void sm() { +    sx = 0; +    this->x = 0; // expected-error {{invalid use of 'this' outside of a non-static member function}} +    x = 0; // expected-error {{invalid use of member 'x' in static member function}} +  } + +  class NestedC { +  public: +    NestedC(int); +    void f() { +      sx = 0; +      x = 0; // expected-error {{use of non-static data member 'x' of 'C' from nested type 'NestedC'}} +      sm(); +      m(); // expected-error {{call to non-static member function 'm' of 'C' from nested type 'NestedC'}} +    } +  }; + +  int b : 1, w : 2; +  int : 1, : 2; +  typedef int E : 1; // expected-error {{typedef member 'E' cannot be a bit-field}} +  static int sb : 1; // expected-error {{static member 'sb' cannot be a bit-field}} +  static int vs; + +  typedef int func(); +  func tm; +  func *ptm; +  func btm : 1; // expected-error {{bit-field 'btm' has non-integral type}} +  NestedC bc : 1; // expected-error {{bit-field 'bc' has non-integral type}} + +  enum E1 { en1, en2 }; + +  int i = 0; // expected-warning {{in-class initialization of non-static data member is a C++11 extension}} +  static int si = 0; // expected-error {{non-const static data member must be initialized out of line}} +  static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}} +  static const int nci = vs; // expected-error {{in-class initializer for static data member is not a constant expression}} +  static const int vi = 0; +  static const volatile int cvi = 0; // ok, illegal in C++11 +  static const E evi = 0; + +  void m() { +    sx = 0; +    this->x = 0; +    y = 0; +    this = 0; // expected-error {{expression is not assignable}} +  } + +  int f1(int p) { +    A z = 6; +    return p + x + this->y + z; +  } + +  typedef int A; + +  virtual int viv; // expected-error {{'virtual' can only appear on non-static member functions}} +  virtual static int vsif(); // expected-error {{'virtual' can only appear on non-static member functions}} +  virtual int vif(); + +private: +  int x,y; +  static int sx; + +  mutable int mi; +  mutable int &mir; // expected-error {{'mutable' cannot be applied to references}} +  mutable void mfn(); // expected-error {{'mutable' cannot be applied to functions}} +  mutable const int mci; // expected-error {{'mutable' and 'const' cannot be mixed}} + +  static const int number = 50; +  static int arr[number]; +}; + +class C2 { +  void f() { +    static int lx; +    class LC1 { +      int m() { return lx; } +    }; +    class LC2 { +      int m() { return lx; } +    }; +  } +}; + +struct C3 { +  int i; +  mutable int j; +}; +void f() +{ +  const C3 c3 = { 1, 2 }; +  (void)static_cast<int*>(&c3.i); // expected-error {{static_cast from 'const int *' to 'int *' is not allowed}} +  // but no error here +  (void)static_cast<int*>(&c3.j); +} + +// Play with mutable a bit more, to make sure it doesn't crash anything. +mutable int gi; // expected-error {{'mutable' can only be applied to member variables}} +mutable void gfn(); // expected-error {{illegal storage class on function}} +void ogfn() +{ +  mutable int ml; // expected-error {{'mutable' can only be applied to member variables}} + +  // PR3020: This used to crash due to double ownership of C4. +  struct C4; +  C4; // expected-warning {{declaration does not declare anything}} +} + +struct C4 { +  void f(); // expected-note{{previous declaration is here}} +  int f; // expected-error{{duplicate member 'f'}} +}; + +// PR5415 - don't hang! +struct S +{ +  void f(); // expected-note 1 {{previous declaration}} +  void S::f() {} // expected-warning {{extra qualification on member}} expected-error {{class member cannot be redeclared}} expected-note {{previous declaration}} expected-note {{previous definition}} +  void f() {} // expected-error {{class member cannot be redeclared}} expected-error {{redefinition}} +}; + +// Don't crash on this bogus code. +namespace pr6629 { +  // TODO: most of these errors are spurious +  template<class T1, class T2> struct foo : +    bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} \ +                       // BOGUS expected-error {{expected '{' after base class list}} \ +                       // BOGUS expected-error {{expected ';' after struct}} \ +                       // BOGUS expected-error {{expected unqualified-id}} +  { }; + +  template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}} +    template <typename U1, typename U2> struct bar { +      typedef bar type; +      static const int value = 0; +    }; +  }; +} + +namespace PR7153 { +  class EnclosingClass { +  public: +    struct A { } mutable *member; +  }; +  +  void f(const EnclosingClass &ec) { +    ec.member = 0; +  } +} + +namespace PR7196 { +  struct A { +    int a; + +    void f() { +      char i[sizeof(a)]; +      enum { x = sizeof(i) }; +      enum { y = sizeof(a) }; +    } +  }; +} + +namespace rdar8066414 { +  class C { +    C() {} +  } // expected-error{{expected ';' after class}} +} + +namespace rdar8367341 { +  float foo(); + +  struct A { +    static const float x = 5.0f; // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} +    static const float y = foo(); // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} expected-error {{in-class initializer for static data member is not a constant expression}} +  }; +} + +namespace with_anon { +struct S { +  union { +    char c; +  }; +}; + +void f() { +    S::c; // expected-error {{invalid use of non-static data member}} +} +} + +struct PR9989 {  +  static int const PR9989_Member = sizeof PR9989_Member;  +}; diff --git a/clang/test/SemaCXX/comma.cpp b/clang/test/SemaCXX/comma.cpp new file mode 100644 index 0000000..79ff7d1 --- /dev/null +++ b/clang/test/SemaCXX/comma.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR6076 +void f(); +void (&g)() = (void(), f); + +int a[1]; +int (&b)[1] = (void(), a); diff --git a/clang/test/SemaCXX/compare.cpp b/clang/test/SemaCXX/compare.cpp new file mode 100644 index 0000000..28e2dd0 --- /dev/null +++ b/clang/test/SemaCXX/compare.cpp @@ -0,0 +1,225 @@ +// Force x86-64 because some of our heuristics are actually based +// on integer sizes. + +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare %s + +int test0(long a, unsigned long b) { +  enum EnumA {A}; +  enum EnumB {B}; +  enum EnumC {C = 0x10000}; +  return +         // (a,b) +         (a == (unsigned long) b) +  // expected-warning {{comparison of integers of different signs}} +         (a == (unsigned int) b) + +         (a == (unsigned short) b) + +         (a == (unsigned char) b) + +         ((long) a == b) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a == b) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a == b) +  // expected-warning {{comparison of integers of different signs}} +         ((signed char) a == b) +  // expected-warning {{comparison of integers of different signs}} +         ((long) a == (unsigned long) b) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a == (unsigned int) b) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a == (unsigned short) b) + +         ((signed char) a == (unsigned char) b) + +         (a < (unsigned long) b) +  // expected-warning {{comparison of integers of different signs}} +         (a < (unsigned int) b) + +         (a < (unsigned short) b) + +         (a < (unsigned char) b) + +         ((long) a < b) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a < b) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a < b) +  // expected-warning {{comparison of integers of different signs}} +         ((signed char) a < b) +  // expected-warning {{comparison of integers of different signs}} +         ((long) a < (unsigned long) b) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a < (unsigned int) b) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a < (unsigned short) b) + +         ((signed char) a < (unsigned char) b) + + +         // (A,b) +         (A == (unsigned long) b) + +         (A == (unsigned int) b) + +         (A == (unsigned short) b) + +         (A == (unsigned char) b) + +         ((long) A == b) + +         ((int) A == b) + +         ((short) A == b) + +         ((signed char) A == b) + +         ((long) A == (unsigned long) b) + +         ((int) A == (unsigned int) b) + +         ((short) A == (unsigned short) b) + +         ((signed char) A == (unsigned char) b) + +         (A < (unsigned long) b) + +         (A < (unsigned int) b) + +         (A < (unsigned short) b) + +         (A < (unsigned char) b) + +         ((long) A < b) + +         ((int) A < b) + +         ((short) A < b) + +         ((signed char) A < b) + +         ((long) A < (unsigned long) b) + +         ((int) A < (unsigned int) b) + +         ((short) A < (unsigned short) b) + +         ((signed char) A < (unsigned char) b) + + +         // (a,B) +         (a == (unsigned long) B) + +         (a == (unsigned int) B) + +         (a == (unsigned short) B) + +         (a == (unsigned char) B) + +         ((long) a == B) + +         ((int) a == B) + +         ((short) a == B) + +         ((signed char) a == B) + +         ((long) a == (unsigned long) B) + +         ((int) a == (unsigned int) B) + +         ((short) a == (unsigned short) B) + +         ((signed char) a == (unsigned char) B) + +         (a < (unsigned long) B) +  // expected-warning {{comparison of integers of different signs}} +         (a < (unsigned int) B) + +         (a < (unsigned short) B) + +         (a < (unsigned char) B) + +         ((long) a < B) + +         ((int) a < B) + +         ((short) a < B) + +         ((signed char) a < B) + +         ((long) a < (unsigned long) B) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a < (unsigned int) B) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a < (unsigned short) B) + +         ((signed char) a < (unsigned char) B) + + +         // (C,b) +         (C == (unsigned long) b) + +         (C == (unsigned int) b) + +         (C == (unsigned short) b) + +         (C == (unsigned char) b) + +         ((long) C == b) + +         ((int) C == b) + +         ((short) C == b) + +         ((signed char) C == b) + +         ((long) C == (unsigned long) b) + +         ((int) C == (unsigned int) b) + +         ((short) C == (unsigned short) b) + +         ((signed char) C == (unsigned char) b) + +         (C < (unsigned long) b) + +         (C < (unsigned int) b) + +         (C < (unsigned short) b) + +         (C < (unsigned char) b) + +         ((long) C < b) + +         ((int) C < b) + +         ((short) C < b) + +         ((signed char) C < b) + +         ((long) C < (unsigned long) b) + +         ((int) C < (unsigned int) b) + +         ((short) C < (unsigned short) b) + +         ((signed char) C < (unsigned char) b) + + +         // (a,C) +         (a == (unsigned long) C) + +         (a == (unsigned int) C) + +         (a == (unsigned short) C) + +         (a == (unsigned char) C) + +         ((long) a == C) + +         ((int) a == C) + +         ((short) a == C) + +         ((signed char) a == C) + +         ((long) a == (unsigned long) C) + +         ((int) a == (unsigned int) C) + +         ((short) a == (unsigned short) C) + +         ((signed char) a == (unsigned char) C) + +         (a < (unsigned long) C) +  // expected-warning {{comparison of integers of different signs}} +         (a < (unsigned int) C) + +         (a < (unsigned short) C) + +         (a < (unsigned char) C) + +         ((long) a < C) + +         ((int) a < C) + +         ((short) a < C) + +         ((signed char) a < C) + +         ((long) a < (unsigned long) C) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a < (unsigned int) C) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a < (unsigned short) C) + +         ((signed char) a < (unsigned char) C) + + +         // (0x80000,b) +         (0x80000 == (unsigned long) b) + +         (0x80000 == (unsigned int) b) + +         (0x80000 == (unsigned short) b) + +         (0x80000 == (unsigned char) b) + +         ((long) 0x80000 == b) + +         ((int) 0x80000 == b) + +         ((short) 0x80000 == b) + +         ((signed char) 0x80000 == b) + +         ((long) 0x80000 == (unsigned long) b) + +         ((int) 0x80000 == (unsigned int) b) + +         ((short) 0x80000 == (unsigned short) b) + +         ((signed char) 0x80000 == (unsigned char) b) + +         (0x80000 < (unsigned long) b) + +         (0x80000 < (unsigned int) b) + +         (0x80000 < (unsigned short) b) + +         (0x80000 < (unsigned char) b) + +         ((long) 0x80000 < b) + +         ((int) 0x80000 < b) + +         ((short) 0x80000 < b) + +         ((signed char) 0x80000 < b) + +         ((long) 0x80000 < (unsigned long) b) + +         ((int) 0x80000 < (unsigned int) b) + +         ((short) 0x80000 < (unsigned short) b) + +         ((signed char) 0x80000 < (unsigned char) b) + + +         // (a,0x80000) +         (a == (unsigned long) 0x80000) + +         (a == (unsigned int) 0x80000) + +         (a == (unsigned short) 0x80000) + +         (a == (unsigned char) 0x80000) + +         ((long) a == 0x80000) + +         ((int) a == 0x80000) + +         ((short) a == 0x80000) + +         ((signed char) a == 0x80000) + +         ((long) a == (unsigned long) 0x80000) + +         ((int) a == (unsigned int) 0x80000) + +         ((short) a == (unsigned short) 0x80000) + +         ((signed char) a == (unsigned char) 0x80000) + +         (a < (unsigned long) 0x80000) +  // expected-warning {{comparison of integers of different signs}} +         (a < (unsigned int) 0x80000) + +         (a < (unsigned short) 0x80000) + +         (a < (unsigned char) 0x80000) + +         ((long) a < 0x80000) + +         ((int) a < 0x80000) + +         ((short) a < 0x80000) + +         ((signed char) a < 0x80000) + +         ((long) a < (unsigned long) 0x80000) +  // expected-warning {{comparison of integers of different signs}} +         ((int) a < (unsigned int) 0x80000) +  // expected-warning {{comparison of integers of different signs}} +         ((short) a < (unsigned short) 0x80000) + +         ((signed char) a < (unsigned char) 0x80000) + + +         10 +    ; +} + +int test1(int i) { +  enum en { zero }; +  return i > zero; +} + +enum E { e }; +void test2(int i, void *vp) { +  if (test1 == vp) { } // expected-warning{{equality comparison between function pointer and void pointer}} +  if (test1 == e) { } // expected-error{{comparison between pointer and integer}} +  if (vp < 0) { } +  if (test1 < e) { } // expected-error{{comparison between pointer and integer}} +} + +// PR7536 +static const unsigned int kMax = 0; +int pr7536() { +  return (kMax > 0); +} + +// -Wsign-compare should not warn when ?: operands have different signedness. +// This will be caught by -Wsign-conversion +void test3() { +  unsigned long a; +  signed long b; +  (void) (true ? a : b); +  (void) (true ? (unsigned int)a : (signed int)b); +  (void) (true ? b : a); +  (void) (true ? (unsigned char)b : (signed char)a); +} diff --git a/clang/test/SemaCXX/complex-init-list.cpp b/clang/test/SemaCXX/complex-init-list.cpp new file mode 100644 index 0000000..e75833a --- /dev/null +++ b/clang/test/SemaCXX/complex-init-list.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic + +// This file tests the clang extension which allows initializing the components +// of a complex number individually using an initialization list. Basically, +// if you have an explicit init list for a complex number that contains two +// initializers, this extension kicks in to turn it into component-wise +// initialization. +//  +// See also the testcase for the C version of this extension in +// test/Sema/complex-init-list.c. + +// Basic testcase +// (No pedantic warning is necessary because _Complex is not part of C++.) +_Complex float valid1 = { 1.0f, 2.0f }; diff --git a/clang/test/SemaCXX/complex-overload.cpp b/clang/test/SemaCXX/complex-overload.cpp new file mode 100644 index 0000000..719a850 --- /dev/null +++ b/clang/test/SemaCXX/complex-overload.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +char *foo(float); + +void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { +  char *cp1 = foo(fv); +  char *cp2 = foo(dv); +  // Note: GCC and EDG reject these two, but they are valid C99 conversions +  char *cp3 = foo(fc); +  char *cp4 = foo(dc); +} + +int *foo(float _Complex); + +void test_foo_2(float fv, double dv, float _Complex fc, double _Complex dc) { +  char *cp1 = foo(fv); +  char *cp2 = foo(dv); +  int *ip = foo(fc); +  int *lp = foo(dc); +} + +long *foo(double _Complex); + +void test_foo_3(float fv, double dv, float _Complex fc, double _Complex dc) { +  char *cp1 = foo(fv); +  char *cp2 = foo(dv); +  int *ip = foo(fc); +  long *lp = foo(dc); +} + +char *promote_or_convert(double _Complex);  // expected-note{{candidate function}} +int *promote_or_convert(long double _Complex); // expected-note{{candidate function}}  + +void test_promote_or_convert(float f, float _Complex fc) { +  char *cp = promote_or_convert(fc); +  int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous}} +} + +char *promote_or_convert2(float); +int *promote_or_convert2(double _Complex); + +void test_promote_or_convert2(float _Complex fc) { +  int *cp = promote_or_convert2(fc); +} + +char *promote_or_convert3(int _Complex); +int *promote_or_convert3(long _Complex); + +void test_promote_or_convert3(short _Complex sc) { +  char *cp = promote_or_convert3(sc); +} diff --git a/clang/test/SemaCXX/composite-pointer-type.cpp b/clang/test/SemaCXX/composite-pointer-type.cpp new file mode 100644 index 0000000..06fc8f4 --- /dev/null +++ b/clang/test/SemaCXX/composite-pointer-type.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class Base { }; +class Derived1 : public Base { }; +class Derived2 : public Base { }; + +void f0(volatile Base *b, Derived1 *d1, const Derived2 *d2) { +  if (b > d1) +    return; +  if (d1 <= b) +    return; +  if (b > d2) +    return; +  if (d1 >= d2) // expected-error{{comparison of distinct}} +    return; +} + +void f1(volatile Base *b, Derived1 *d1, const Derived2 *d2) { +  if (b == d1) +    return; +  if (d1 == b) +    return; +  if (b != d2) +    return; +  if (d1 == d2) // expected-error{{comparison of distinct}} +    return; +} + +// PR4691 +int ptrcmp1(void *a, int *b) { +  return a < b; +} +int ptrcmp2(long *a, int *b) { +  return a < b; // expected-error{{distinct}} +} + +// PR5509 - Multi-level pointers +int f2() { +  typedef int *IntPtr; +  typedef IntPtr *IntPtrPtr; +  typedef IntPtr const *IntPtrConstPtr; +  IntPtrConstPtr i = 0; +  IntPtrPtr j = 0; +  return i != j; +} + +// PR5763 +typedef double Matrix4[4][4]; + +bool f(Matrix4 m1, const Matrix4 m2) { +  return m1 != m2; +} + +// PR6346 +bool f1(bool b, void **p, const void **q) { +  if (p == q) // expected-warning{{comparison of distinct pointer types ('void **' and 'const void **') uses non-standard composite pointer type 'const void *const *'}} +    return false; + +  return b? p : q; // expected-warning{{incompatible operand types ('void **' and 'const void **') use non-standard composite pointer type 'const void *const *'}} +} diff --git a/clang/test/SemaCXX/compound-literal.cpp b/clang/test/SemaCXX/compound-literal.cpp new file mode 100644 index 0000000..fe0e45d --- /dev/null +++ b/clang/test/SemaCXX/compound-literal.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// http://llvm.org/PR7905 +namespace PR7905 { +struct S; // expected-note {{forward declaration}} +void foo1() { +  (void)(S[]) {{3}}; // expected-error {{array has incomplete element type}} +} + +template <typename T> struct M { T m; }; +void foo2() { +  (void)(M<short> []) {{3}}; +} +} diff --git a/clang/test/SemaCXX/condition.cpp b/clang/test/SemaCXX/condition.cpp new file mode 100644 index 0000000..993f8e1 --- /dev/null +++ b/clang/test/SemaCXX/condition.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +void test() { +  int x; +  if (x) ++x; +  if (int x=0) ++x; + +  typedef int arr[10]; +  while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}} +  while (int f()=0) ; // expected-warning {{interpreted as a function declaration}} expected-note {{initializer}} expected-error {{a function type is not allowed here}} + +  struct S {} s; +  if (s) ++x; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} +  while (struct S x=s) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} +  do ; while (s); // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} +  for (;s;) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} +  switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}} + +  while (struct NewS *x=0) ; +  while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}} +  while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}} +  switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \ +  // expected-warning{{enumeration value 'E' not handled in switch}} expected-warning {{switch statement has empty body}} \ +  // expected-note{{put the semicolon on a separate line}} + +  if (int x=0) { // expected-note 2 {{previous definition is here}} +    int x;  // expected-error {{redefinition of 'x'}} +  } +  else +    int x;  // expected-error {{redefinition of 'x'}} +  while (int x=0) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +  while (int x=0) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +  for (int x; int x=0; ) ; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +  for (int x; ; ) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +  for (; int x=0; ) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +  for (; int x=0; ) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +  switch (int x=0) { default: int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +} + +int* get_int_ptr(); + +void test2() { +  float *ip; +  if (int *ip = ip) { +  } +} + +// Make sure we do function/array decay. +void test3() { +  if ("help") +    (void) 0; + +  if (test3) // expected-warning {{address of function 'test3' will always evaluate to 'true'}} \ +                expected-note {{prefix with the address-of operator to silence this warning}} +    (void) 0; +} + +void test4(bool (&x)(void)) { +  while (x); +} diff --git a/clang/test/SemaCXX/conditional-expr.cpp b/clang/test/SemaCXX/conditional-expr.cpp new file mode 100644 index 0000000..4aee913 --- /dev/null +++ b/clang/test/SemaCXX/conditional-expr.cpp @@ -0,0 +1,330 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wsign-conversion %s + +// C++ rules for ?: are a lot stricter than C rules, and have to take into +// account more conversion options. +// This test runs in C++0x mode for the contextual conversion of the condition. + +struct ToBool { explicit operator bool(); }; + +struct B; +struct A { +  A();  +  A(const B&); // expected-note 2 {{candidate constructor}} +};  +struct B { operator A() const; }; // expected-note 2 {{candidate function}} +struct I { operator int(); }; +struct J { operator I(); }; +struct K { operator double(); }; +typedef void (*vfn)(); +struct F { operator vfn(); }; +struct G { operator vfn(); }; + +struct Base { +  int trick(); +  A trick() const; +  void fn1(); +}; +struct Derived : Base { +  void fn2(); +}; +struct Convertible { operator Base&(); }; +struct Priv : private Base {}; // expected-note 4 {{declared private here}} +struct Mid : Base {}; +struct Fin : Mid, Derived {}; +typedef void (Derived::*DFnPtr)(); +struct ToMemPtr { operator DFnPtr(); }; + +struct BadDerived; +struct BadBase { operator BadDerived&(); }; +struct BadDerived : BadBase {}; + +struct Fields { +  int i1, i2, b1 : 3, b2 : 3; +}; +struct MixedFields { +  int i; +  volatile int vi; +  const int ci; +  const volatile int cvi; +}; +struct MixedFieldsDerived : MixedFields { +}; + +enum Enum { EVal }; + +struct Ambig { +  operator short(); // expected-note 2 {{candidate function}} +  operator signed char(); // expected-note 2 {{candidate function}} +}; + +void test() +{ +  // This function tests C++0x 5.16 + +  // p1 (contextually convert to bool) +  int i1 = ToBool() ? 0 : 1; + +  // p2 (one or both void, and throwing) +  i1 ? throw 0 : throw 1; +  i1 ? test() : throw 1; +  i1 ? throw 0 : test(); +  i1 ? test() : test(); +  i1 = i1 ? throw 0 : 0; +  i1 = i1 ? 0 : throw 0; +  i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}} +  i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}} +  (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}} +  (i1 ? i1 : throw 0) = 0; // expected-error {{expression is not assignable}} + +  // p3 (one or both class type, convert to each other) +  // b1 (lvalues) +  Base base; +  Derived derived; +  Convertible conv; +  Base &bar1 = i1 ? base : derived; +  Base &bar2 = i1 ? derived : base; +  Base &bar3 = i1 ? base : conv; +  Base &bar4 = i1 ? conv : base; +  // these are ambiguous +  BadBase bb; +  BadDerived bd; +  (void)(i1 ? bb : bd); // expected-error {{conditional expression is ambiguous; 'BadBase' can be converted to 'BadDerived' and vice versa}} +  (void)(i1 ? bd : bb); // expected-error {{conditional expression is ambiguous}} +  // curiously enough (and a defect?), these are not +  // for rvalues, hierarchy takes precedence over other conversions +  (void)(i1 ? BadBase() : BadDerived()); +  (void)(i1 ? BadDerived() : BadBase()); + +  // b2.1 (hierarchy stuff) +  extern const Base constret(); +  extern const Derived constder(); +  // should use const overload +  A a1((i1 ? constret() : Base()).trick()); +  A a2((i1 ? Base() : constret()).trick()); +  A a3((i1 ? constret() : Derived()).trick()); +  A a4((i1 ? Derived() : constret()).trick()); +  // should use non-const overload +  i1 = (i1 ? Base() : Base()).trick(); +  i1 = (i1 ? Base() : Base()).trick(); +  i1 = (i1 ? Base() : Derived()).trick(); +  i1 = (i1 ? Derived() : Base()).trick(); +  // should fail: const lost +  (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('Base' and 'const Derived')}} +  (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('const Derived' and 'Base')}} + +  Priv priv; +  Fin fin; +  (void)(i1 ? Base() : Priv()); // expected-error{{private base class}} +  (void)(i1 ? Priv() : Base()); // expected-error{{private base class}} +  (void)(i1 ? Base() : Fin()); // expected-error{{ambiguous conversion from derived class 'Fin' to base class 'Base':}} +  (void)(i1 ? Fin() : Base()); // expected-error{{ambiguous conversion from derived class 'Fin' to base class 'Base':}} +  (void)(i1 ? base : priv); // expected-error {{private base class}} +  (void)(i1 ? priv : base); // expected-error {{private base class}} +  (void)(i1 ? base : fin); // expected-error {{ambiguous conversion from derived class 'Fin' to base class 'Base':}} +  (void)(i1 ? fin : base); // expected-error {{ambiguous conversion from derived class 'Fin' to base class 'Base':}} + +  // b2.2 (non-hierarchy) +  i1 = i1 ? I() : i1; +  i1 = i1 ? i1 : I(); +  I i2(i1 ? I() : J()); +  I i3(i1 ? J() : I()); +  // "the type [it] woud have if E2 were converted to an rvalue" +  vfn pfn = i1 ? F() : test; +  pfn = i1 ? test : F(); +  (void)(i1 ? A() : B()); // expected-error {{conversion from 'B' to 'A' is ambiguous}} +  (void)(i1 ? B() : A()); // expected-error {{conversion from 'B' to 'A' is ambiguous}} +  (void)(i1 ? 1 : Ambig()); // expected-error {{conversion from 'Ambig' to 'int' is ambiguous}} +  (void)(i1 ? Ambig() : 1); // expected-error {{conversion from 'Ambig' to 'int' is ambiguous}} +  // By the way, this isn't an lvalue: +  &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}} + +  // p4 (lvalue, same type) +  Fields flds; +  int &ir1 = i1 ? flds.i1 : flds.i2; +  (i1 ? flds.b1 : flds.i2) = 0; +  (i1 ? flds.i1 : flds.b2) = 0; +  (i1 ? flds.b1 : flds.b2) = 0; + +  // p5 (conversion to built-in types) +  // GCC 4.3 fails these +  double d1 = i1 ? I() : K(); +  pfn = i1 ? F() : G(); +  DFnPtr pfm; +  pfm = i1 ? DFnPtr() : &Base::fn1; +  pfm = i1 ? &Base::fn1 : DFnPtr(); + +  // p6 (final conversions) +  i1 = i1 ? i1 : ir1; +  int *pi1 = i1 ? &i1 : 0; +  pi1 = i1 ? 0 : &i1; +  i1 = i1 ? i1 : EVal; +  i1 = i1 ? EVal : i1; +  d1 = i1 ? 'c' : 4.0; +  d1 = i1 ? 4.0 : 'c'; +  Base *pb = i1 ? (Base*)0 : (Derived*)0; +  pb = i1 ? (Derived*)0 : (Base*)0; +  pfm = i1 ? &Base::fn1 : &Derived::fn2; +  pfm = i1 ? &Derived::fn2 : &Base::fn1; +  pfm = i1 ? &Derived::fn2 : 0; +  pfm = i1 ? 0 : &Derived::fn2; +  const int (MixedFieldsDerived::*mp1) = +    i1 ? &MixedFields::ci : &MixedFieldsDerived::i; +  const volatile int (MixedFields::*mp2) = +    i1 ? &MixedFields::ci : &MixedFields::cvi; +  (void)(i1 ? &MixedFields::ci : &MixedFields::vi); +  // Conversion of primitives does not result in an lvalue. +  &(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}} + +  (void)&(i1 ? flds.b1 : flds.i1); // expected-error {{address of bit-field requested}} +  (void)&(i1 ? flds.i1 : flds.b1); // expected-error {{address of bit-field requested}} +   + +  unsigned long test0 = 5; +  test0 = test0 ? (long) test0 : test0; // expected-warning {{operand of ? changes signedness: 'long' to 'unsigned long'}} +  test0 = test0 ? (int) test0 : test0; // expected-warning {{operand of ? changes signedness: 'int' to 'unsigned long'}} +  test0 = test0 ? (short) test0 : test0; // expected-warning {{operand of ? changes signedness: 'short' to 'unsigned long'}} +  test0 = test0 ? test0 : (long) test0; // expected-warning {{operand of ? changes signedness: 'long' to 'unsigned long'}} +  test0 = test0 ? test0 : (int) test0; // expected-warning {{operand of ? changes signedness: 'int' to 'unsigned long'}} +  test0 = test0 ? test0 : (short) test0; // expected-warning {{operand of ? changes signedness: 'short' to 'unsigned long'}} +  test0 = test0 ? test0 : (long) 10; +  test0 = test0 ? test0 : (int) 10; +  test0 = test0 ? test0 : (short) 10; +  test0 = test0 ? (long) 10 : test0; +  test0 = test0 ? (int) 10 : test0; +  test0 = test0 ? (short) 10 : test0; + +  int test1; +  test0 = test0 ? EVal : test0; +  test1 = test0 ? EVal : (int) test0; + +  test0 = test0 ? EVal : test1; // expected-warning {{operand of ? changes signedness: 'int' to 'unsigned long'}} +  test0 = test0 ? test1 : EVal; // expected-warning {{operand of ? changes signedness: 'int' to 'unsigned long'}} + +  test1 = test0 ? EVal : (int) test0; +  test1 = test0 ? (int) test0 : EVal; + +  // Note the thing that this does not test: since DR446, various situations +  // *must* create a separate temporary copy of class objects. This can only +  // be properly tested at runtime, though. +} + +namespace PR6595 { +  struct OtherString { +    OtherString(); +    OtherString(const char*); +  }; + +  struct String { +    String(const char *); +    String(const OtherString&); +    operator const char*() const; +  }; + +  void f(bool Cond, String S, OtherString OS) { +    (void)(Cond? S : ""); +    (void)(Cond? "" : S); +    const char a[1] = {'a'}; +    (void)(Cond? S : a); +    (void)(Cond? a : S); +    (void)(Cond? OS : S); +  } +} + +namespace PR6757 { +  struct Foo1 { +    Foo1(); +    Foo1(const Foo1&); +  }; + +  struct Foo2 { }; + +  struct Foo3 { +    Foo3(); +    Foo3(Foo3&); // expected-note{{would lose const qualifier}} +  }; + +  struct Bar { +    operator const Foo1&() const; +    operator const Foo2&() const; +    operator const Foo3&() const; +  }; + +  void f() { +    (void)(true ? Bar() : Foo1()); // okay +    (void)(true ? Bar() : Foo2()); // okay +    (void)(true ? Bar() : Foo3()); // expected-error{{no viable constructor copying temporary}} +  } +} + +// Reduced from selfhost. +namespace test1 { +  struct A { +    enum Foo { +      fa, fb, fc, fd, fe, ff +    }; + +    Foo x(); +  }; + +  void foo(int); + +  void test(A *a) { +    foo(a ? a->x() : 0); +  } +} + +namespace rdar7998817 { +  class X {  +    X(X&); // expected-note{{declared private here}} + +    struct ref { }; + +  public: +    X(); +    X(ref); +     +    operator ref(); +  }; + +  void f(bool B) { +    X x; +    (void)(B? x // expected-error{{calling a private constructor of class 'rdar7998817::X'}} +           : X()); +  } +} + +namespace PR7598 { +  enum Enum { +    v = 1, +  }; + +  const Enum g() { +    return v; +  } + +  const volatile Enum g2() { +    return v; +  } + +  void f() { +    const Enum v2 = v; +    Enum e = false ? g() : v; +    Enum e2 = false ? v2 : v; +    Enum e3 = false ? g2() : v; +  } + +} + +namespace PR9236 { +#define NULL 0L +  void f() { +    int i; +    (void)(true ? A() : NULL); // expected-error{{non-pointer operand type 'A' incompatible with NULL}} +    (void)(true ? NULL : A()); // expected-error{{non-pointer operand type 'A' incompatible with NULL}} +    (void)(true ? 0 : A()); // expected-error{{incompatible operand types}} +    (void)(true ? nullptr : A()); // expected-error{{non-pointer operand type 'A' incompatible with nullptr}} +    (void)(true ? nullptr : i); // expected-error{{non-pointer operand type 'int' incompatible with nullptr}} +    (void)(true ? __null : A()); // expected-error{{non-pointer operand type 'A' incompatible with NULL}} +    (void)(true ? (void*)0 : A()); // expected-error{{incompatible operand types}} +  } +} diff --git a/clang/test/SemaCXX/const-cast.cpp b/clang/test/SemaCXX/const-cast.cpp new file mode 100644 index 0000000..62851f8 --- /dev/null +++ b/clang/test/SemaCXX/const-cast.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A {}; + +// See if aliasing can confuse this baby. +typedef char c; +typedef c *cp; +typedef cp *cpp; +typedef cpp *cppp; +typedef cppp &cpppr; +typedef const cppp &cpppcr; +typedef const char cc; +typedef cc *ccp; +typedef volatile ccp ccvp; +typedef ccvp *ccvpp; +typedef const volatile ccvpp ccvpcvp; +typedef ccvpcvp *ccvpcvpp; +typedef int iar[100]; +typedef iar &iarr; +typedef int (*f)(int); + +char ***good_const_cast_test(ccvpcvpp var) +{ +  // Cast away deep consts and volatiles. +  char ***var2 = const_cast<cppp>(var); +  char ***const &var3 = var2; +  // Const reference to reference. +  char ***&var4 = const_cast<cpppr>(var3); +  // Drop reference. Intentionally without qualifier change. +  char *** var5 = const_cast<cppp>(var4); +  // Const array to array reference. +  const int ar[100] = {0}; +  int (&rar)[100] = const_cast<iarr>(ar); +  // Array decay. Intentionally without qualifier change. +  int *pi = const_cast<int*>(ar); +  f fp = 0; +  // Don't misidentify fn** as a function pointer. +  f *fpp = const_cast<f*>(&fp); +  int const A::* const A::*icapcap = 0; +  int A::* A::* iapap = const_cast<int A::* A::*>(icapcap); + +  return var4; +} + +short *bad_const_cast_test(char const *volatile *const volatile *var) +{ +  // Different pointer levels. +  char **var2 = const_cast<char**>(var); // expected-error {{const_cast from 'const char *volatile *const volatile *' to 'char **' is not allowed}} +  // Different final type. +  short ***var3 = const_cast<short***>(var); // expected-error {{const_cast from 'const char *volatile *const volatile *' to 'short ***' is not allowed}} +  // Rvalue to reference. +  char ***&var4 = const_cast<cpppr>(&var2); // expected-error {{const_cast from rvalue to reference type 'cpppr'}} +  // Non-pointer. +  char v = const_cast<char>(**var2); // expected-error {{const_cast to 'char', which is not a reference, pointer-to-object, or pointer-to-data-member}} +  const int *ar[100] = {0}; +  // Not even lenient g++ accepts this. +  int *(*rar)[100] = const_cast<int *(*)[100]>(&ar); // expected-error {{const_cast from 'const int *(*)[100]' to 'int *(*)[100]' is not allowed}} +  f fp1 = 0; +  // Function pointers. +  f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} +  void (A::*mfn)() = 0; +  (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}} +  return **var3; +} diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp new file mode 100644 index 0000000..9f80e71 --- /dev/null +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -0,0 +1,1250 @@ +// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -verify -std=c++11 -pedantic %s -Wno-comment + +namespace StaticAssertFoldTest { + +int x; +static_assert(++x, "test"); // expected-error {{not an integral constant expression}} +static_assert(false, "test"); // expected-error {{test}} + +} + +typedef decltype(sizeof(char)) size_t; + +template<typename T> constexpr T id(const T &t) { return t; } +template<typename T> constexpr T min(const T &a, const T &b) { +  return a < b ? a : b; +} +template<typename T> constexpr T max(const T &a, const T &b) { +  return a < b ? b : a; +} +template<typename T, size_t N> constexpr T *begin(T (&xs)[N]) { return xs; } +template<typename T, size_t N> constexpr T *end(T (&xs)[N]) { return xs + N; } + +struct MemberZero { +  constexpr int zero() { return 0; } +}; + +namespace DerivedToVBaseCast { + +  struct U { int n; }; +  struct V : U { int n; }; +  struct A : virtual V { int n; }; +  struct Aa { int n; }; +  struct B : virtual A, Aa {}; +  struct C : virtual A, Aa {}; +  struct D : B, C {}; + +  D d; +  constexpr B *p = &d; +  constexpr C *q = &d; + +  static_assert((void*)p != (void*)q, ""); +  static_assert((A*)p == (A*)q, ""); +  static_assert((Aa*)p != (Aa*)q, ""); + +  constexpr B &pp = d; +  constexpr C &qq = d; +  static_assert((void*)&pp != (void*)&qq, ""); +  static_assert(&(A&)pp == &(A&)qq, ""); +  static_assert(&(Aa&)pp != &(Aa&)qq, ""); + +  constexpr V *v = p; +  constexpr V *w = q; +  constexpr V *x = (A*)p; +  static_assert(v == w, ""); +  static_assert(v == x, ""); + +  static_assert((U*)&d == p, ""); +  static_assert((U*)&d == q, ""); +  static_assert((U*)&d == v, ""); +  static_assert((U*)&d == w, ""); +  static_assert((U*)&d == x, ""); + +  struct X {}; +  struct Y1 : virtual X {}; +  struct Y2 : X {}; +  struct Z : Y1, Y2 {}; +  Z z; +  static_assert((X*)(Y1*)&z != (X*)(Y2*)&z, ""); +} + +namespace ConstCast { + +constexpr int n1 = 0; +constexpr int n2 = const_cast<int&>(n1); +constexpr int *n3 = const_cast<int*>(&n1); +constexpr int n4 = *const_cast<int*>(&n1); +constexpr const int * const *n5 = const_cast<const int* const*>(&n3); +constexpr int **n6 = const_cast<int**>(&n3); +constexpr int n7 = **n5; +constexpr int n8 = **n6; + +} + +namespace TemplateArgumentConversion { +  template<int n> struct IntParam {}; + +  using IntParam0 = IntParam<0>; +  using IntParam0 = IntParam<id(0)>; +  using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} +} + +namespace CaseStatements { +  void f(int n) { +    switch (n) { +    case MemberZero().zero: // expected-error {{did you mean to call it with no arguments?}} expected-note {{previous}} +    case id(0): // expected-error {{duplicate case value '0'}} +      return; +    } +  } +} + +extern int &Recurse1; +int &Recurse2 = Recurse1; // expected-note {{declared here}} +int &Recurse1 = Recurse2; +constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'Recurse2' is not a constant expression}} + +extern const int RecurseA; +const int RecurseB = RecurseA; // expected-note {{declared here}} +const int RecurseA = 10; +constexpr int RecurseC = RecurseB; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'RecurseB' is not a constant expression}} + +namespace MemberEnum { +  struct WithMemberEnum { +    enum E { A = 42 }; +  } wme; + +  static_assert(wme.A == 42, ""); +} + +namespace DefaultArguments { + +const int z = int(); +constexpr int Sum(int a = 0, const int &b = 0, const int *c = &z, char d = 0) { +  return a + b + *c + d; +} +const int four = 4; +constexpr int eight = 8; +constexpr const int twentyseven = 27; +static_assert(Sum() == 0, ""); +static_assert(Sum(1) == 1, ""); +static_assert(Sum(1, four) == 5, ""); +static_assert(Sum(1, eight, &twentyseven) == 36, ""); +static_assert(Sum(1, 2, &four, eight) == 15, ""); + +} + +namespace Ellipsis { + +// Note, values passed through an ellipsis can't actually be used. +constexpr int F(int a, ...) { return a; } +static_assert(F(0) == 0, ""); +static_assert(F(1, 0) == 1, ""); +static_assert(F(2, "test") == 2, ""); +static_assert(F(3, &F) == 3, ""); +int k = 0; // expected-note {{here}} +static_assert(F(4, k) == 3, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'k'}} + +} + +namespace Recursion { +  constexpr int fib(int n) { return n > 1 ? fib(n-1) + fib(n-2) : n; } +  static_assert(fib(11) == 89, ""); + +  constexpr int gcd_inner(int a, int b) { +    return b == 0 ? a : gcd_inner(b, a % b); +  } +  constexpr int gcd(int a, int b) { +    return gcd_inner(max(a, b), min(a, b)); +  } + +  static_assert(gcd(1749237, 5628959) == 7, ""); +} + +namespace FunctionCast { +  // When folding, we allow functions to be cast to different types. Such +  // cast functions cannot be called, even if they're constexpr. +  constexpr int f() { return 1; } +  typedef double (*DoubleFn)(); +  typedef int (*IntFn)(); +  int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}} expected-warning{{C99 feature}} +  int b[(int)IntFn(f)()];    // ok +} + +namespace StaticMemberFunction { +  struct S { +    static constexpr int k = 42; +    static constexpr int f(int n) { return n * k + 2; } +  } s; + +  constexpr int n = s.f(19); +  static_assert(S::f(19) == 800, ""); +  static_assert(s.f(19) == 800, ""); +  static_assert(n == 800, ""); + +  constexpr int (*sf1)(int) = &S::f; +  constexpr int (*sf2)(int) = &s.f; +  constexpr const int *sk = &s.k; +} + +namespace ParameterScopes { + +  const int k = 42; +  constexpr const int &ObscureTheTruth(const int &a) { return a; } +  constexpr const int &MaybeReturnJunk(bool b, const int a) { // expected-note 2{{declared here}} +    return ObscureTheTruth(b ? a : k); +  } +  static_assert(MaybeReturnJunk(false, 0) == 42, ""); // ok +  constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}} + +  constexpr const int MaybeReturnNonstaticRef(bool b, const int a) { +    return ObscureTheTruth(b ? a : k); +  } +  static_assert(MaybeReturnNonstaticRef(false, 0) == 42, ""); // ok +  constexpr int b = MaybeReturnNonstaticRef(true, 0); // ok + +  constexpr int InternalReturnJunk(int n) { +    return MaybeReturnJunk(true, n); // expected-note {{read of variable whose lifetime has ended}} +  } +  constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'InternalReturnJunk(0)'}} + +  constexpr int LToR(int &n) { return n; } +  constexpr int GrabCallersArgument(bool which, int a, int b) { +    return LToR(which ? b : a); +  } +  static_assert(GrabCallersArgument(false, 1, 2) == 1, ""); +  static_assert(GrabCallersArgument(true, 4, 8) == 8, ""); + +} + +namespace Pointers { + +  constexpr int f(int n, const int *a, const int *b, const int *c) { +    return n == 0 ? 0 : *a + f(n-1, b, c, a); +  } + +  const int x = 1, y = 10, z = 100; +  static_assert(f(23, &x, &y, &z) == 788, ""); + +  constexpr int g(int n, int a, int b, int c) { +    return f(n, &a, &b, &c); +  } +  static_assert(g(23, x, y, z) == 788, ""); + +} + +namespace FunctionPointers { + +  constexpr int Double(int n) { return 2 * n; } +  constexpr int Triple(int n) { return 3 * n; } +  constexpr int Twice(int (*F)(int), int n) { return F(F(n)); } +  constexpr int Quadruple(int n) { return Twice(Double, n); } +  constexpr auto Select(int n) -> int (*)(int) { +    return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0; +  } +  constexpr int Apply(int (*F)(int), int n) { return F(n); } // expected-note {{subexpression}} + +  static_assert(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, ""); + +  constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(0, 0)'}} + +} + +namespace PointerComparison { + +int x, y; +static_assert(&x == &y, "false"); // expected-error {{false}} +static_assert(&x != &y, ""); +constexpr bool g1 = &x == &y; +constexpr bool g2 = &x != &y; +constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool g6 = &x > &y; // expected-error {{must be initialized by a constant expression}} + +struct S { int x, y; } s; +static_assert(&s.x == &s.y, "false"); // expected-error {{false}} +static_assert(&s.x != &s.y, ""); +static_assert(&s.x <= &s.y, ""); +static_assert(&s.x >= &s.y, "false"); // expected-error {{false}} +static_assert(&s.x < &s.y, ""); +static_assert(&s.x > &s.y, "false"); // expected-error {{false}} + +static_assert(0 == &y, "false"); // expected-error {{false}} +static_assert(0 != &y, ""); +constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}} + +static_assert(&x == 0, "false"); // expected-error {{false}} +static_assert(&x != 0, ""); +constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}} + +static_assert(&x == &x, ""); +static_assert(&x != &x, "false"); // expected-error {{false}} +static_assert(&x <= &x, ""); +static_assert(&x >= &x, ""); +static_assert(&x < &x, "false"); // expected-error {{false}} +static_assert(&x > &x, "false"); // expected-error {{false}} + +constexpr S* sptr = &s; +constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr); // expected-error {{constant expression}} expected-note {{dynamic_cast}} + +struct U {}; +struct Str { +  int a : dynamic_cast<S*>(sptr) == dynamic_cast<S*>(sptr); // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{dynamic_cast is not allowed in a constant expression}} +  int b : reinterpret_cast<S*>(sptr) == reinterpret_cast<S*>(sptr); // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{reinterpret_cast is not allowed in a constant expression}} +  int c : (S*)(long)(sptr) == (S*)(long)(sptr); // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} +  int d : (S*)(42) == (S*)(42); // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} +  int e : (Str*)(sptr) == (Str*)(sptr); // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} +  int f : &(U&)(*sptr) == &(U&)(*sptr); // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} +  int g : (S*)(void*)(sptr) == sptr; // \ +    expected-warning {{not an integral constant expression}} \ +    expected-note {{cast from 'void *' is not allowed in a constant expression}} +}; + +extern char externalvar[]; +constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; // expected-error {{must be initialized by a constant expression}} +constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}} expected-warning {{unspecified}} +static_assert(0 != "foo", ""); + +} + +namespace MaterializeTemporary { + +constexpr int f(const int &r) { return r; } +constexpr int n = f(1); + +constexpr bool same(const int &a, const int &b) { return &a == &b; } +constexpr bool sameTemporary(const int &n) { return same(n, n); } + +static_assert(n, ""); +static_assert(!same(4, 4), ""); +static_assert(same(n, n), ""); +static_assert(sameTemporary(9), ""); + +} + +constexpr int strcmp_ce(const char *p, const char *q) { +  return (!*p || *p != *q) ? *p - *q : strcmp_ce(p+1, q+1); +} + +namespace StringLiteral { + +template<typename Char> +constexpr int MangleChars(const Char *p) { +  return *p + 3 * (*p ? MangleChars(p+1) : 0); +} + +static_assert(MangleChars("constexpr!") == 1768383, ""); +static_assert(MangleChars(u8"constexpr!") == 1768383, ""); +static_assert(MangleChars(L"constexpr!") == 1768383, ""); +static_assert(MangleChars(u"constexpr!") == 1768383, ""); +static_assert(MangleChars(U"constexpr!") == 1768383, ""); + +constexpr char c0 = "nought index"[0]; +constexpr char c1 = "nice index"[10]; +constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}} expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}} expected-note {{cannot refer to element -1 of array of 15 elements}} +constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast which performs the conversions of a reinterpret_cast}} + +constexpr const char *p = "test" + 2; +static_assert(*p == 's', ""); + +constexpr const char *max_iter(const char *a, const char *b) { +  return *a < *b ? b : a; +} +constexpr const char *max_element(const char *a, const char *b) { +  return (a+1 >= b) ? a : max_iter(a, max_element(a+1, b)); +} + +constexpr char str[] = "the quick brown fox jumped over the lazy dog"; +constexpr const char *max = max_element(begin(str), end(str)); +static_assert(*max == 'z', ""); +static_assert(max == str + 38, ""); + +static_assert(strcmp_ce("hello world", "hello world") == 0, ""); +static_assert(strcmp_ce("hello world", "hello clang") > 0, ""); +static_assert(strcmp_ce("constexpr", "test") < 0, ""); +static_assert(strcmp_ce("", " ") < 0, ""); + +struct S { +  int n : "foo"[4]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +}; + +struct T { +  char c[6]; +  constexpr T() : c{"foo"} {} +}; +constexpr T t; + +static_assert(t.c[0] == 'f', ""); +static_assert(t.c[1] == 'o', ""); +static_assert(t.c[2] == 'o', ""); +static_assert(t.c[3] == 0, ""); +static_assert(t.c[4] == 0, ""); +static_assert(t.c[5] == 0, ""); +static_assert(t.c[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}} + +struct U { +  wchar_t chars[6]; +  int n; +} constexpr u = { { L"test" }, 0 }; +static_assert(u.chars[2] == L's', ""); + +struct V { +  char c[4]; +  constexpr V() : c("hi!") {} +}; +static_assert(V().c[1] == "i"[0], ""); + +} + +namespace Array { + +template<typename Iter> +constexpr auto Sum(Iter begin, Iter end) -> decltype(+*begin) { +  return begin == end ? 0 : *begin + Sum(begin+1, end); +} + +constexpr int xs[] = { 1, 2, 3, 4, 5 }; +constexpr int ys[] = { 5, 4, 3, 2, 1 }; +constexpr int sum_xs = Sum(begin(xs), end(xs)); +static_assert(sum_xs == 15, ""); + +constexpr int ZipFoldR(int (*F)(int x, int y, int c), int n, +                       const int *xs, const int *ys, int c) { +  return n ? F( +               *xs, // expected-note {{read of dereferenced one-past-the-end pointer}} +               *ys, +               ZipFoldR(F, n-1, xs+1, ys+1, c)) // \ +      expected-note {{in call to 'ZipFoldR(&SubMul, 2, &xs[4], &ys[4], 1)'}} \ +      expected-note {{in call to 'ZipFoldR(&SubMul, 1, &xs[5], &ys[5], 1)'}} +           : c; +} +constexpr int MulAdd(int x, int y, int c) { return x * y + c; } +constexpr int InnerProduct = ZipFoldR(MulAdd, 5, xs, ys, 0); +static_assert(InnerProduct == 35, ""); + +constexpr int SubMul(int x, int y, int c) { return (x - y) * c; } +constexpr int DiffProd = ZipFoldR(SubMul, 2, xs+3, ys+3, 1); +static_assert(DiffProd == 8, ""); +static_assert(ZipFoldR(SubMul, 3, xs+3, ys+3, 1), ""); // \ +      expected-error {{constant expression}} \ +      expected-note {{in call to 'ZipFoldR(&SubMul, 3, &xs[3], &ys[3], 1)'}} + +constexpr const int *p = xs + 3; +constexpr int xs4 = p[1]; // ok +constexpr int xs5 = p[2]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr int xs6 = p[3]; // expected-error {{constant expression}} expected-note {{cannot refer to element 6}} +constexpr int xs0 = p[-3]; // ok +constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} + +constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; +static_assert(zs[0][0][0][0] == 1, ""); +static_assert(zs[1][1][1][1] == 16, ""); +static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +static_assert((&zs[0][0][0][2])[-1] == 2, ""); +static_assert(**(**(zs + 1) + 1) == 11, ""); +static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of array of 2 elements in a constant expression}} +static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2) == 11, ""); +constexpr int err_zs_1_2_0_0 = zs[1][2][0][0]; // expected-error {{constant expression}} expected-note {{cannot access array element of pointer past the end}} + +constexpr int fail(const int &p) { +  return (&p)[64]; // expected-note {{cannot refer to element 64 of array of 2 elements}} +} +static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // \ +expected-error {{static_assert expression is not an integral constant expression}} \ +expected-note {{in call to 'fail(zs[1][0][1][0])'}} + +constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; // expected-warning {{C99 feature}} +constexpr int SumNonzero(const int *p) { +  return *p + (*p ? SumNonzero(p+1) : 0); +} +constexpr int CountZero(const int *p, const int *q) { +  return p == q ? 0 : (*p == 0) + CountZero(p+1, q); +} +static_assert(SumNonzero(arr) == 6, ""); +static_assert(CountZero(arr, arr + 40) == 36, ""); + +struct ArrayElem { +  constexpr ArrayElem() : n(0) {} +  int n; +  constexpr int f() { return n; } +}; +struct ArrayRVal { +  constexpr ArrayRVal() {} +  ArrayElem elems[10]; +}; +static_assert(ArrayRVal().elems[3].f() == 0, ""); + +} + +namespace DependentValues { + +struct I { int n; typedef I V[10]; }; +I::V x, y; +template<bool B> struct S { +  int k; +  void f() { +    I::V &cells = B ? x : y; +    I &i = cells[k]; +    switch (i.n) {} +  } +}; + +} + +namespace Class { + +struct A { constexpr A(int a, int b) : k(a + b) {} int k; }; +constexpr int fn(const A &a) { return a.k; } +static_assert(fn(A(4,5)) == 9, ""); + +struct B { int n; int m; } constexpr b = { 0, b.n }; // expected-warning {{uninitialized}} +struct C { +  constexpr C(C *this_) : m(42), n(this_->m) {} // ok +  int m, n; +}; +struct D { +  C c; +  constexpr D() : c(&c) {} +}; +static_assert(D().c.n == 42, ""); + +struct E { +  constexpr E() : p(&p) {} +  void *p; +}; +constexpr const E &e1 = E(); // expected-error {{constant expression}} expected-note {{reference to temporary is not a constant expression}} expected-note {{temporary created here}} +// This is a constant expression if we elide the copy constructor call, and +// is not a constant expression if we don't! But we do, so it is. +constexpr E e2 = E(); +static_assert(e2.p == &e2.p, ""); +constexpr E e3; +static_assert(e3.p == &e3.p, ""); + +extern const class F f; +struct F { +  constexpr F() : p(&f.p) {} +  const void *p; +}; +constexpr F f; + +struct G { +  struct T { +    constexpr T(T *p) : u1(), u2(p) {} +    union U1 { +      constexpr U1() {} +      int a, b = 42; +    } u1; +    union U2 { +      constexpr U2(T *p) : c(p->u1.b) {} +      int c, d; +    } u2; +  } t; +  constexpr G() : t(&t) {} +} constexpr g; + +static_assert(g.t.u1.a == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}} +static_assert(g.t.u1.b == 42, ""); +static_assert(g.t.u2.c == 42, ""); +static_assert(g.t.u2.d == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'd' of union with active member 'c'}} + +struct S { +  int a, b; +  const S *p; +  double d; +  const char *q; + +  constexpr S(int n, const S *p) : a(5), b(n), p(p), d(n), q("hello") {} +}; + +S global(43, &global); + +static_assert(S(15, &global).b == 15, ""); + +constexpr bool CheckS(const S &s) { +  return s.a == 5 && s.b == 27 && s.p == &global && s.d == 27. && s.q[3] == 'l'; +} +static_assert(CheckS(S(27, &global)), ""); + +struct Arr { +  char arr[3]; +  constexpr Arr() : arr{'x', 'y', 'z'} {} +}; +constexpr int hash(Arr &&a) { +  return a.arr[0] + a.arr[1] * 0x100 + a.arr[2] * 0x10000; +} +constexpr int k = hash(Arr()); +static_assert(k == 0x007a7978, ""); + + +struct AggregateInit { +  const char &c; +  int n; +  double d; +  int arr[5]; +  void *p; +}; + +constexpr AggregateInit agg1 = { "hello"[0] }; + +static_assert(strcmp_ce(&agg1.c, "hello") == 0, ""); +static_assert(agg1.n == 0, ""); +static_assert(agg1.d == 0.0, ""); +static_assert(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} +static_assert(agg1.arr[0] == 0, ""); +static_assert(agg1.arr[4] == 0, ""); +static_assert(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end}} +static_assert(agg1.p == nullptr, ""); + +static constexpr const unsigned char uc[] = { "foo" }; +static_assert(uc[0] == 'f', ""); +static_assert(uc[3] == 0, ""); + +namespace SimpleDerivedClass { + +struct B { +  constexpr B(int n) : a(n) {} +  int a; +}; +struct D : B { +  constexpr D(int n) : B(n) {} +}; +constexpr D d(3); +static_assert(d.a == 3, ""); + +} + +struct Bottom { constexpr Bottom() {} }; +struct Base : Bottom { +  constexpr Base(int a = 42, const char *b = "test") : a(a), b(b) {} +  int a; +  const char *b; +}; +struct Base2 : Bottom { +  constexpr Base2(const int &r) : r(r) {} +  int q = 123; +  const int &r; +}; +struct Derived : Base, Base2 { +  constexpr Derived() : Base(76), Base2(a) {} +  int c = r + b[1]; +}; + +constexpr bool operator==(const Base &a, const Base &b) { +  return a.a == b.a && strcmp_ce(a.b, b.b) == 0; +} + +constexpr Base base; +constexpr Base base2(76); +constexpr Derived derived; +static_assert(derived.a == 76, ""); +static_assert(derived.b[2] == 's', ""); +static_assert(derived.c == 76 + 'e', ""); +static_assert(derived.q == 123, ""); +static_assert(derived.r == 76, ""); +static_assert(&derived.r == &derived.a, ""); + +static_assert(!(derived == base), ""); +static_assert(derived == base2, ""); + +constexpr Bottom &bot1 = (Base&)derived; +constexpr Bottom &bot2 = (Base2&)derived; +static_assert(&bot1 != &bot2, ""); + +constexpr Bottom *pb1 = (Base*)&derived; +constexpr Bottom *pb2 = (Base2*)&derived; +static_assert(&pb1 != &pb2, ""); +static_assert(pb1 == &bot1, ""); +static_assert(pb2 == &bot2, ""); + +constexpr Base2 &fail = (Base2&)bot1; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base2'}} +constexpr Base &fail2 = (Base&)*pb2; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base'}} +constexpr Base2 &ok2 = (Base2&)bot2; +static_assert(&ok2 == &derived, ""); + +constexpr Base2 *pfail = (Base2*)pb1; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base2'}} +constexpr Base *pfail2 = (Base*)&bot2; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base'}} +constexpr Base2 *pok2 = (Base2*)pb2; +static_assert(pok2 == &derived, ""); +static_assert(&ok2 == pok2, ""); +static_assert((Base2*)(Derived*)(Base*)pb1 == pok2, ""); +static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, ""); + +constexpr Base *nullB = 42 - 6 * 7; +static_assert((Bottom*)nullB == 0, ""); +static_assert((Derived*)nullB == 0, ""); +static_assert((void*)(Bottom*)nullB == (void*)(Derived*)nullB, ""); + +namespace ConversionOperators { + +struct T { +  constexpr T(int n) : k(5*n - 3) {} +  constexpr operator int() { return k; } +  int k; +}; + +struct S { +  constexpr S(int n) : k(2*n + 1) {} +  constexpr operator int() { return k; } +  constexpr operator T() { return T(k); } +  int k; +}; + +constexpr bool check(T a, T b) { return a == b.k; } + +static_assert(S(5) == 11, ""); +static_assert(check(S(5), 11), ""); + +} + +} + +namespace Temporaries { + +struct S { +  constexpr S() {} +  constexpr int f(); +}; +struct T : S { +  constexpr T(int n) : S(), n(n) {} +  int n; +}; +constexpr int S::f() { +  // 'this' must be the postfix-expression in a class member access expression, +  // so we can't just use +  //   return static_cast<T*>(this)->n; +  return this->*(int(S::*))&T::n; +} +// The T temporary is implicitly cast to an S subobject, but we can recover the +// T full-object via a base-to-derived cast, or a derived-to-base-casted member +// pointer. +static_assert(T(3).f() == 3, ""); + +constexpr int f(const S &s) { +  return static_cast<const T&>(s).n; +} +constexpr int n = f(T(5)); +static_assert(f(T(5)) == 5, ""); + +constexpr bool b(int n) { return &n; } +static_assert(b(0), ""); + +} + +namespace Union { + +union U { +  int a; +  int b; +}; + +constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; // expected-warning 4{{C99 feature}} +static_assert(u[0].a == 0, ""); +static_assert(u[0].b, ""); // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}} +static_assert(u[1].b == 1, ""); +static_assert((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +static_assert(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element 2 of non-array object}} +static_assert((&(u[1]) + 1 + 1)->b == 3, ""); + +constexpr U v = {}; +static_assert(v.a == 0, ""); + +union Empty {}; +constexpr Empty e = {}; + +// Make sure we handle trivial copy constructors for unions. +constexpr U x = {42}; +constexpr U y = x; +static_assert(y.a == 42, ""); +static_assert(y.b == 42, ""); // expected-error {{constant expression}} expected-note {{'b' of union with active member 'a'}} + +} + +namespace MemberPointer { +  struct A { +    constexpr A(int n) : n(n) {} +    int n; +    constexpr int f() { return n + 3; } +  }; +  constexpr A a(7); +  static_assert(A(5).*&A::n == 5, ""); +  static_assert((&a)->*&A::n == 7, ""); +  static_assert((A(8).*&A::f)() == 11, ""); +  static_assert(((&a)->*&A::f)() == 10, ""); + +  struct B : A { +    constexpr B(int n, int m) : A(n), m(m) {} +    int m; +    constexpr int g() { return n + m + 1; } +  }; +  constexpr B b(9, 13); +  static_assert(B(4, 11).*&A::n == 4, ""); +  static_assert(B(4, 11).*&B::m == 11, ""); +  static_assert(B(4, 11).*(int(A::*))&B::m == 11, ""); +  static_assert((&b)->*&A::n == 9, ""); +  static_assert((&b)->*&B::m == 13, ""); +  static_assert((&b)->*(int(A::*))&B::m == 13, ""); +  static_assert((B(4, 11).*&A::f)() == 7, ""); +  static_assert((B(4, 11).*&B::g)() == 16, ""); +  static_assert((B(4, 11).*(int(A::*)()const)&B::g)() == 16, ""); +  static_assert(((&b)->*&A::f)() == 12, ""); +  static_assert(((&b)->*&B::g)() == 23, ""); +  static_assert(((&b)->*(int(A::*)()const)&B::g)() == 23, ""); + +  struct S { +    constexpr S(int m, int n, int (S::*pf)() const, int S::*pn) : +      m(m), n(n), pf(pf), pn(pn) {} +    constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {} + +    constexpr int f() { return this->*pn; } +    virtual int g() const; + +    int m, n; +    int (S::*pf)() const; +    int S::*pn; +  }; + +  constexpr int S::*pm = &S::m; +  constexpr int S::*pn = &S::n; +  constexpr int (S::*pf)() const = &S::f; +  constexpr int (S::*pg)() const = &S::g; + +  constexpr S s(2, 5, &S::f, &S::m); + +  static_assert((s.*&S::f)() == 2, ""); +  static_assert((s.*s.pf)() == 2, ""); + +  static_assert(pf == &S::f, ""); +  static_assert(pf == s.*&S::pf, ""); +  static_assert(pm == &S::m, ""); +  static_assert(pm != pn, ""); +  static_assert(s.pn != pn, ""); +  static_assert(s.pn == pm, ""); +  static_assert(pg != nullptr, ""); +  static_assert(pf != nullptr, ""); +  static_assert((int S::*)nullptr == nullptr, ""); +  static_assert(pg == pg, ""); // expected-error {{constant expression}} expected-note {{comparison of pointer to virtual member function 'g' has unspecified value}} +  static_assert(pf != pg, ""); // expected-error {{constant expression}} expected-note {{comparison of pointer to virtual member function 'g' has unspecified value}} + +  template<int n> struct T : T<n-1> {}; +  template<> struct T<0> { int n; }; +  template<> struct T<30> : T<29> { int m; }; + +  T<17> t17; +  T<30> t30; + +  constexpr int (T<10>::*deepn) = &T<0>::n; +  static_assert(&(t17.*deepn) == &t17.n, ""); +  static_assert(deepn == &T<2>::n, ""); + +  constexpr int (T<15>::*deepm) = (int(T<10>::*))&T<30>::m; +  constexpr int *pbad = &(t17.*deepm); // expected-error {{constant expression}} +  static_assert(&(t30.*deepm) == &t30.m, ""); +  static_assert(deepm == &T<50>::m, ""); +  static_assert(deepm != deepn, ""); + +  constexpr T<5> *p17_5 = &t17; +  constexpr T<13> *p17_13 = (T<13>*)p17_5; +  constexpr T<23> *p17_23 = (T<23>*)p17_13; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'T<17>' to type 'T<23>'}} +  static_assert(&(p17_5->*(int(T<3>::*))deepn) == &t17.n, ""); +  static_assert(&(p17_13->*deepn) == &t17.n, ""); +  constexpr int *pbad2 = &(p17_13->*(int(T<9>::*))deepm); // expected-error {{constant expression}} + +  constexpr T<5> *p30_5 = &t30; +  constexpr T<23> *p30_23 = (T<23>*)p30_5; +  constexpr T<13> *p30_13 = p30_23; +  static_assert(&(p30_5->*(int(T<3>::*))deepn) == &t30.n, ""); +  static_assert(&(p30_13->*deepn) == &t30.n, ""); +  static_assert(&(p30_23->*deepn) == &t30.n, ""); +  static_assert(&(p30_5->*(int(T<2>::*))deepm) == &t30.m, ""); +  static_assert(&(((T<17>*)p30_13)->*deepm) == &t30.m, ""); +  static_assert(&(p30_23->*deepm) == &t30.m, ""); + +  struct Base { int n; }; +  template<int N> struct Mid : Base {}; +  struct Derived : Mid<0>, Mid<1> {}; +  static_assert(&Mid<0>::n == &Mid<1>::n, ""); +  static_assert((int Derived::*)(int Mid<0>::*)&Mid<0>::n != +                (int Derived::*)(int Mid<1>::*)&Mid<1>::n, ""); +  static_assert(&Mid<0>::n == (int Mid<0>::*)&Base::n, ""); +} + +namespace ArrayBaseDerived { + +  struct Base { +    constexpr Base() {} +    int n = 0; +  }; +  struct Derived : Base { +    constexpr Derived() {} +    constexpr const int *f() { return &n; } +  }; + +  constexpr Derived a[10]; +  constexpr Derived *pd3 = const_cast<Derived*>(&a[3]); +  constexpr Base *pb3 = const_cast<Derived*>(&a[3]); +  static_assert(pb3 == pd3, ""); + +  // pb3 does not point to an array element. +  constexpr Base *pb4 = pb3 + 1; // ok, one-past-the-end pointer. +  constexpr int pb4n = pb4->n; // expected-error {{constant expression}} expected-note {{cannot access field of pointer past the end}} +  constexpr Base *err_pb5 = pb3 + 2; // expected-error {{constant expression}} expected-note {{cannot refer to element 2}} expected-note {{here}} +  constexpr int err_pb5n = err_pb5->n; // expected-error {{constant expression}} expected-note {{initializer of 'err_pb5' is not a constant expression}} +  constexpr Base *err_pb2 = pb3 - 1; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} expected-note {{here}} +  constexpr int err_pb2n = err_pb2->n; // expected-error {{constant expression}} expected-note {{initializer of 'err_pb2'}} +  constexpr Base *pb3a = pb4 - 1; + +  // pb4 does not point to a Derived. +  constexpr Derived *err_pd4 = (Derived*)pb4; // expected-error {{constant expression}} expected-note {{cannot access derived class of pointer past the end}} +  constexpr Derived *pd3a = (Derived*)pb3a; +  constexpr int pd3n = pd3a->n; + +  // pd3a still points to the Derived array. +  constexpr Derived *pd6 = pd3a + 3; +  static_assert(pd6 == &a[6], ""); +  constexpr Derived *pd9 = pd6 + 3; +  constexpr Derived *pd10 = pd6 + 4; +  constexpr int pd9n = pd9->n; // ok +  constexpr int err_pd10n = pd10->n; // expected-error {{constant expression}} expected-note {{cannot access base class of pointer past the end}} +  constexpr int pd0n = pd10[-10].n; +  constexpr int err_pdminus1n = pd10[-11].n; // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of}} + +  constexpr Base *pb9 = pd9; +  constexpr const int *(Base::*pfb)() const = +      static_cast<const int *(Base::*)() const>(&Derived::f); +  static_assert((pb9->*pfb)() == &a[9].n, ""); +} + +namespace Complex { + +class complex { +  int re, im; +public: +  constexpr complex(int re = 0, int im = 0) : re(re), im(im) {} +  constexpr complex(const complex &o) : re(o.re), im(o.im) {} +  constexpr complex operator-() const { return complex(-re, -im); } +  friend constexpr complex operator+(const complex &l, const complex &r) { +    return complex(l.re + r.re, l.im + r.im); +  } +  friend constexpr complex operator-(const complex &l, const complex &r) { +    return l + -r; +  } +  friend constexpr complex operator*(const complex &l, const complex &r) { +    return complex(l.re * r.re - l.im * r.im, l.re * r.im + l.im * r.re); +  } +  friend constexpr bool operator==(const complex &l, const complex &r) { +    return l.re == r.re && l.im == r.im; +  } +  constexpr bool operator!=(const complex &r) const { +    return re != r.re || im != r.im; +  } +  constexpr int real() const { return re; } +  constexpr int imag() const { return im; } +}; + +constexpr complex i = complex(0, 1); +constexpr complex k = (3 + 4*i) * (6 - 4*i); +static_assert(complex(1,0).real() == 1, ""); +static_assert(complex(1,0).imag() == 0, ""); +static_assert(((complex)1).imag() == 0, ""); +static_assert(k.real() == 34, ""); +static_assert(k.imag() == 12, ""); +static_assert(k - 34 == 12*i, ""); +static_assert((complex)1 == complex(1), ""); +static_assert((complex)1 != complex(0, 1), ""); +static_assert(complex(1) == complex(1), ""); +static_assert(complex(1) != complex(0, 1), ""); +constexpr complex makeComplex(int re, int im) { return complex(re, im); } +static_assert(makeComplex(1,0) == complex(1), ""); +static_assert(makeComplex(1,0) != complex(0, 1), ""); + +class complex_wrap : public complex { +public: +  constexpr complex_wrap(int re, int im = 0) : complex(re, im) {} +  constexpr complex_wrap(const complex_wrap &o) : complex(o) {} +}; + +static_assert((complex_wrap)1 == complex(1), ""); +static_assert((complex)1 != complex_wrap(0, 1), ""); +static_assert(complex(1) == complex_wrap(1), ""); +static_assert(complex_wrap(1) != complex(0, 1), ""); +constexpr complex_wrap makeComplexWrap(int re, int im) { +  return complex_wrap(re, im); +} +static_assert(makeComplexWrap(1,0) == complex(1), ""); +static_assert(makeComplexWrap(1,0) != complex(0, 1), ""); + +} + +namespace PR11595 { +  struct A { constexpr bool operator==(int x) { return true; } }; +  struct B { B(); A& x; }; +  static_assert(B().x == 3, "");  // expected-error {{constant expression}} expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}} + +  constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}} +    return B().x == k; // expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}} +  } +} + +namespace ExprWithCleanups { +  struct A { A(); ~A(); int get(); }; +  constexpr int get(bool FromA) { return FromA ? A().get() : 1; } +  constexpr int n = get(false); +} + +namespace Volatile { + +volatile constexpr int n1 = 0; // expected-note {{here}} +volatile const int n2 = 0; // expected-note {{here}} +int n3 = 37; // expected-note {{declared here}} + +constexpr int m1 = n1; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} +constexpr int m2 = n2; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} +constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}} +constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}} + +struct T { int n; }; +const T t = { 42 }; // expected-note {{declared here}} + +constexpr int f(volatile int &&r) { +  return r; // expected-note {{read of volatile-qualified type 'volatile int'}} +} +constexpr int g(volatile int &&r) { +  return const_cast<int&>(r); // expected-note {{read of volatile temporary is not allowed in a constant expression}} +} +struct S { +  int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}} +  int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}} +  int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}} +  int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}} +}; + +} + +namespace ExternConstexpr { +  extern constexpr int n = 0; +  extern constexpr int m; // expected-error {{constexpr variable declaration must be a definition}} +  void f() { +    extern constexpr int i; // expected-error {{constexpr variable declaration must be a definition}} +    constexpr int j = 0; +    constexpr int k; // expected-error {{default initialization of an object of const type}} +  } +} + +namespace ComplexConstexpr { +  constexpr _Complex float test1 = {}; +  constexpr _Complex float test2 = {1}; +  constexpr _Complex double test3 = {1,2}; +  constexpr _Complex int test4 = {4}; +  constexpr _Complex int test5 = 4; +  constexpr _Complex int test6 = {5,6}; +  typedef _Complex float fcomplex; +  constexpr fcomplex test7 = fcomplex(); + +  constexpr const double &t2r = __real test3; +  constexpr const double &t2i = __imag test3; +  static_assert(&t2r + 1 == &t2i, ""); +  static_assert(t2r == 1.0, ""); +  static_assert(t2i == 2.0, ""); +  constexpr const double *t2p = &t2r; +  static_assert(t2p[-1] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element -1 of array of 2 elements}} +  static_assert(t2p[0] == 1.0, ""); +  static_assert(t2p[1] == 2.0, ""); +  static_assert(t2p[2] == 0.0, ""); // expected-error {{constant expr}} expected-note {{one-past-the-end pointer}} +  static_assert(t2p[3] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element 3 of array of 2 elements}} +  constexpr _Complex float *p = 0; +  constexpr float pr = __real *p; // expected-error {{constant expr}} expected-note {{cannot access real component of null}} +  constexpr float pi = __imag *p; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of null}} +  constexpr const _Complex double *q = &test3 + 1; +  constexpr double qr = __real *q; // expected-error {{constant expr}} expected-note {{cannot access real component of pointer past the end}} +  constexpr double qi = __imag *q; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of pointer past the end}} + +  static_assert(__real test6 == 5, ""); +  static_assert(__imag test6 == 6, ""); +  static_assert(&__imag test6 == &__real test6 + 1, ""); +} + +namespace InstantiateCaseStmt { +  template<int x> constexpr int f() { return x; } +  template<int x> int g(int c) { switch(c) { case f<x>(): return 1; } return 0; } +  int gg(int c) { return g<4>(c); } +} + +namespace ConvertedConstantExpr { +  extern int &m; +  extern int &n; + +  constexpr int k = 4; +  int &m = const_cast<int&>(k); + +  // If we have nothing more interesting to say, ensure we don't produce a +  // useless note and instead just point to the non-constant subexpression. +  enum class E { +    em = m, +    en = n, // expected-error {{not a constant expression}} +    eo = (m + +          n // expected-error {{not a constant expression}} +          ), +    eq = reinterpret_cast<int>((int*)0) // expected-error {{not a constant expression}} expected-note {{reinterpret_cast}} +  }; +} + +namespace IndirectField { +  struct S { +    struct { // expected-warning {{GNU extension}} +      union { +        struct { // expected-warning {{GNU extension}} +          int a; +          int b; +        }; +        int c; +      }; +      int d; +    }; +    union { +      int e; +      int f; +    }; +    constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {} +    constexpr S(int c, int d, int f) : c(c), d(d), f(f) {} +  }; + +  constexpr S s1(1, 2, 3, 4); +  constexpr S s2(5, 6, 7); + +  // FIXME: The diagnostics here do a very poor job of explaining which unnamed +  // member is active and which is requested. +  static_assert(s1.a == 1, ""); +  static_assert(s1.b == 2, ""); +  static_assert(s1.c == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} +  static_assert(s1.d == 3, ""); +  static_assert(s1.e == 4, ""); +  static_assert(s1.f == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} + +  static_assert(s2.a == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} +  static_assert(s2.b == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} +  static_assert(s2.c == 5, ""); +  static_assert(s2.d == 6, ""); +  static_assert(s2.e == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} +  static_assert(s2.f == 7, ""); +} + +// DR1405: don't allow reading mutable members in constant expressions. +namespace MutableMembers { +  struct MM { +    mutable int n; // expected-note 3{{declared here}} +  } constexpr mm = { 4 }; +  constexpr int mmn = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}} +  int x = (mm.n = 1, 3); +  constexpr int mmn2 = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}} + +  // Here's one reason why allowing this would be a disaster... +  template<int n> struct Id { int k = n; }; +  int f() { +    constexpr MM m = { 0 }; +    ++m.n; +    return Id<m.n>().k; // expected-error {{not a constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}} +  } + +  struct A { int n; }; +  struct B { mutable A a; }; // expected-note {{here}} +  struct C { B b; }; +  constexpr C c[3] = {}; +  constexpr int k = c[1].b.a.n; // expected-error {{constant expression}} expected-note {{mutable}} +} + +namespace Fold { + +  // This macro forces its argument to be constant-folded, even if it's not +  // otherwise a constant expression. +  #define fold(x) (__builtin_constant_p(x) ? (x) : (x)) + +  constexpr int n = (int)(char*)123; // expected-error {{constant expression}} expected-note {{reinterpret_cast}} +  constexpr int m = fold((int)(char*)123); // ok +  static_assert(m == 123, ""); + +  #undef fold + +} + +namespace DR1454 { + +constexpr const int &f(const int &n) { return n; } +constexpr int k1 = f(0); // ok + +struct Wrap { +  const int &value; +}; +constexpr const Wrap &g(const Wrap &w) { return w; } +constexpr int k2 = g({0}).value; // ok + +constexpr const int &i = 0; // expected-error {{constant expression}} expected-note {{temporary}} expected-note 2{{here}} +constexpr const int j = i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}} + +} + +namespace RecursiveOpaqueExpr { +  template<typename Iter> +  constexpr auto LastNonzero(Iter p, Iter q) -> decltype(+*p) { +    return p != q ? (LastNonzero(p+1, q) ?: *p) : 0; // expected-warning {{GNU}} +  } + +  constexpr int arr1[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 0 }; +  static_assert(LastNonzero(begin(arr1), end(arr1)) == 4, ""); + +  constexpr int arr2[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 5 }; +  static_assert(LastNonzero(begin(arr2), end(arr2)) == 5, ""); +} + +namespace VLASizeof { + +  void f(int k) { +    int arr[k]; // expected-warning {{C99}} +    constexpr int n = 1 + +        sizeof(arr) // expected-error {{constant expression}} +        * 3; +  } +} + +namespace CompoundLiteral { +  // FIXME: +  // We don't model the semantics of this correctly: the compound literal is +  // represented as a prvalue in the AST, but actually behaves like an lvalue. +  // We treat the compound literal as a temporary and refuse to produce a +  // pointer to it. This is OK: we're not required to treat this as a constant +  // in C++, and in C we model compound literals as lvalues. +  constexpr int *p = (int*)(int[1]){0}; // expected-warning {{C99}} expected-error {{constant expression}} expected-note 2{{temporary}} +} + +namespace Vector { +  typedef int __attribute__((vector_size(16))) VI4; +  constexpr VI4 f(int n) { +    return VI4 { n * 3, n + 4, n - 5, n / 6 }; +  } +  constexpr auto v1 = f(10); + +  typedef double __attribute__((vector_size(32))) VD4; +  constexpr VD4 g(int n) { +    return (VD4) { n / 2.0, n + 1.5, n - 5.4, n * 0.9 }; // expected-warning {{C99}} +  } +  constexpr auto v2 = g(4); +} diff --git a/clang/test/SemaCXX/constant-expression.cpp b/clang/test/SemaCXX/constant-expression.cpp new file mode 100644 index 0000000..23a4dda --- /dev/null +++ b/clang/test/SemaCXX/constant-expression.cpp @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s +// C++ [expr.const]p1: +//   In several places, C++ requires expressions that evaluate to an integral +//   or enumeration constant: as array bounds, as case expressions, as +//   bit-field lengths, as enumerator initializers, as static member +//   initializers, and as integral or enumeration non-type template arguments. +//   An integral constant-expression can involve only literals, enumerators, +//   const variables or static data members of integral or enumeration types +//   initialized with constant expressions, and sizeof expressions. Floating +//   literals can appear only if they are cast to integral or enumeration types. + +enum Enum { eval = 1 }; +const int cval = 2; +const Enum ceval = eval; +struct Struct { +  static const int sval = 3; +  static const Enum seval = eval; +}; + +template <int itval, Enum etval> struct C { +  enum E { +    v1 = 1, +    v2 = eval, +    v3 = cval, +    v4 = ceval, +    v5 = Struct::sval, +    v6 = Struct::seval, +    v7 = itval, +    v8 = etval, +    v9 = (int)1.5, +    v10 = sizeof(Struct), +    v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 +  }; +  unsigned +    b1 : 1, +    b2 : eval, +    b3 : cval, +    b4 : ceval, +    b5 : Struct::sval, +    b6 : Struct::seval, +    b7 : itval, +    b8 : etval, +    b9 : (int)1.5, +    b10 : sizeof(Struct), +    b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 +    ; +  static const int +    i1 = 1, +    i2 = eval, +    i3 = cval, +    i4 = ceval, +    i5 = Struct::sval, +    i6 = Struct::seval, +    i7 = itval, +    i8 = etval, +    i9 = (int)1.5, +    i10 = sizeof(Struct), +    i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 +    ; +  void f(int cond) { +    switch(cond) { +    case    0 + 1: +    case  100 + eval: +    case  200 + cval: +    case  300 + ceval: +    case  400 + Struct::sval: +    case  500 + Struct::seval: +    case  600 + itval: +    case  700 + etval: +    case  800 + (int)1.5: +    case  900 + sizeof(Struct): +    case 1000 + (true? 1 + cval * Struct::sval ^ +                 itval / (int)1.5 - sizeof(Struct) : 0): +      ; +    } +  } +  typedef C<itval, etval> T0; +}; + +template struct C<1, eval>; +template struct C<cval, ceval>; +template struct C<Struct::sval, Struct::seval>; + +enum { +  a = sizeof(int) == 8, +  b = a? 8 : 4 +}; + +void diags(int n) { +  switch (n) { +    case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} +    case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} +    case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} +    case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} +      ; +  } +} + +namespace IntOrEnum { +  const int k = 0; +  const int &p = k; +  template<int n> struct S {}; +  S<p> s; // expected-error {{not an integral constant expression}} +} + +extern const int recurse1; +// recurse2 cannot be used in a constant expression because it is not +// initialized by a constant expression. The same expression appearing later in +// the TU would be a constant expression, but here it is not. +const int recurse2 = recurse1; +const int recurse1 = 1; +int array1[recurse1]; // ok +int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}} + +namespace FloatConvert { +  typedef int a[(int)42.3]; +  typedef int a[(int)42.997]; +  typedef int b[(int)4e10]; // expected-warning {{variable length}} expected-error {{variable length}} +} diff --git a/clang/test/SemaCXX/constexpr-ackermann.cpp b/clang/test/SemaCXX/constexpr-ackermann.cpp new file mode 100644 index 0000000..c4ea313 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-ackermann.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +constexpr unsigned long long A(unsigned long long m, unsigned long long n) { +  return m == 0 ? n + 1 : n == 0 ? A(m-1, 1) : A(m - 1, A(m, n - 1)); +} + +using X = int[A(3,4)]; +using X = int[125]; diff --git a/clang/test/SemaCXX/constexpr-backtrace-limit.cpp b/clang/test/SemaCXX/constexpr-backtrace-limit.cpp new file mode 100644 index 0000000..9c40eed --- /dev/null +++ b/clang/test/SemaCXX/constexpr-backtrace-limit.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 0 -fconstexpr-depth 4 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST1 +// TEST1: constant expression +// TEST1-NEXT: exceeded maximum depth of 4 +// TEST1-NEXT: in call to 'recurse(2)' +// TEST1-NEXT: in call to 'recurse(3)' +// TEST1-NEXT: in call to 'recurse(4)' +// TEST1-NEXT: in call to 'recurse(5)' + +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 2 -fconstexpr-depth 4 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST2 +// TEST2: constant expression +// TEST2-NEXT: exceeded maximum depth of 4 +// TEST2-NEXT: in call to 'recurse(2)' +// TEST2-NEXT: skipping 2 calls +// TEST2-NEXT: in call to 'recurse(5)' + +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 2 -fconstexpr-depth 8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST3 +// TEST3: constant expression +// TEST3-NEXT: reinterpret_cast +// TEST3-NEXT: in call to 'recurse(0)' +// TEST3-NEXT: skipping 4 calls +// TEST3-NEXT: in call to 'recurse(5)' + +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 8 -fconstexpr-depth 8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST4 +// TEST4: constant expression +// TEST4-NEXT: reinterpret_cast +// TEST4-NEXT: in call to 'recurse(0)' +// TEST4-NEXT: in call to 'recurse(1)' +// TEST4-NEXT: in call to 'recurse(2)' +// TEST4-NEXT: in call to 'recurse(3)' +// TEST4-NEXT: in call to 'recurse(4)' +// TEST4-NEXT: in call to 'recurse(5)' + +constexpr int recurse(int n) { return n ? recurse(n-1) : *(int*)n; } +static_assert(recurse(5), ""); diff --git a/clang/test/SemaCXX/constexpr-depth.cpp b/clang/test/SemaCXX/constexpr-depth.cpp new file mode 100644 index 0000000..feba6fd --- /dev/null +++ b/clang/test/SemaCXX/constexpr-depth.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=128 -fconstexpr-depth 128 +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=2 -fconstexpr-depth 2 +// RUN: %clang -std=c++11 -fsyntax-only -Xclang -verify %s -DMAX=10 -fconstexpr-depth=10 + +constexpr int depth(int n) { return n > 1 ? depth(n-1) : 0; } // expected-note {{exceeded maximum depth}} expected-note +{{}} + +constexpr int kBad = depth(MAX + 1); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'depth(}} +constexpr int kGood = depth(MAX); diff --git a/clang/test/SemaCXX/constexpr-factorial.cpp b/clang/test/SemaCXX/constexpr-factorial.cpp new file mode 100644 index 0000000..b6cdde5 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-factorial.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +constexpr unsigned oddfac(unsigned n) { +  return n == 1 ? 1 : n * oddfac(n-2); +} +constexpr unsigned k = oddfac(123); + +using A = int[k % 256]; +using A = int[43]; diff --git a/clang/test/SemaCXX/constexpr-nqueens.cpp b/clang/test/SemaCXX/constexpr-nqueens.cpp new file mode 100644 index 0000000..b158d6e --- /dev/null +++ b/clang/test/SemaCXX/constexpr-nqueens.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +typedef unsigned long uint64_t; + +struct Board { +  uint64_t State; +  bool Failed; + +  constexpr Board() : State(0), Failed(false) {} +  constexpr Board(const Board &O) : State(O.State), Failed(O.Failed) {} +  constexpr Board(uint64_t State, bool Failed = false) : +    State(State), Failed(Failed) {} +  constexpr Board addQueen(int Row, int Col) { +    return Board(State | ((uint64_t)Row << (Col * 4))); +  } +  constexpr int getQueenRow(int Col) { +    return (State >> (Col * 4)) & 0xf; +  } +  constexpr bool ok(int Row, int Col) { +    return okRecurse(Row, Col, 0); +  } +  constexpr bool okRecurse(int Row, int Col, int CheckCol) { +    return Col == CheckCol ? true : +           getQueenRow(CheckCol) == Row ? false : +           getQueenRow(CheckCol) == Row + (Col - CheckCol) ? false : +           getQueenRow(CheckCol) == Row + (CheckCol - Col) ? false : +           okRecurse(Row, Col, CheckCol + 1); +  } +  constexpr bool at(int Row, int Col) { +    return getQueenRow(Col) == Row; +  } +  constexpr bool check(const char *, int=0, int=0); +}; + +constexpr Board buildBoardRecurse(int N, int Col, const Board &B); +constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B); +constexpr Board tryBoard(const Board &Try, +                         int N, int Col, int Row, const Board &B) { +  return Try.Failed ? buildBoardScan(N, Col, Row, B) : Try; +} +constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) { +  return Row == N ? Board(0, true) : +         B.ok(Row, Col) ? +         tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), +                  N, Col, Row+1, B) : +         buildBoardScan(N, Col, Row + 1, B); +} +constexpr Board buildBoardRecurse(int N, int Col, const Board &B) { +  return Col == N ? B : buildBoardScan(N, Col, 0, B); +} +constexpr Board buildBoard(int N) { +  return buildBoardRecurse(N, 0, Board()); +} + +constexpr Board q8 = buildBoard(8); + +constexpr bool Board::check(const char *p, int Row, int Col) { +  return +    *p == '\n' ? check(p+1, Row+1, 0) : +    *p == 'o' ? at(Row, Col) && check(p+1, Row, Col+1) : +    *p == '-' ? !at(Row, Col) && check(p+1, Row, Col+1) : +    *p == 0 ? true : +    false; +} +static_assert(q8.check( +    "o-------\n" +    "------o-\n" +    "----o---\n" +    "-------o\n" +    "-o------\n" +    "---o----\n" +    "-----o--\n" +    "--o-----\n"), ""); diff --git a/clang/test/SemaCXX/constexpr-printing.cpp b/clang/test/SemaCXX/constexpr-printing.cpp new file mode 100644 index 0000000..9170fa1 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-printing.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -triple x86_64-linux-gnu + +struct S; +constexpr int extract(const S &s); + +struct S { +  constexpr S() : n(extract(*this)), m(0) {} // expected-note {{in call to 'extract(s1)'}} +  constexpr S(int k) : n(k), m(extract(*this)) {} +  int n, m; +}; + +constexpr int extract(const S &s) { return s.n; } // expected-note {{read of uninitialized object is not allowed in a constant expression}} + +constexpr S s1; // ok +void f() { +  constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}} +  constexpr S s2(10); +} + +typedef __attribute__((vector_size(16))) int vector_int; + +struct T { +  constexpr T() : arr() {} +  int arr[4]; +}; +struct U : T { +  constexpr U(const int *p) : T(), another(), p(p) {} +  constexpr U(const U &u) : T(), another(), p(u.p) {} +  T another; +  const int *p; +}; +constexpr U u1(&u1.arr[2]); + +constexpr int test_printing(int a, float b, _Complex int c, _Complex float d, +                            int *e, int &f, vector_int g, U h) { +  return *e; // expected-note {{read of non-constexpr variable 'u2'}} +} +U u2(0); // expected-note {{here}} +static_assert(test_printing(12, 39.762, 3 + 4i, 12.9 + 3.6i, &u2.arr[4], u2.another.arr[2], (vector_int){5, 1, 2, 3}, u1) == 0, ""); // \ +expected-error {{constant expression}} \ +expected-note {{in call to 'test_printing(12, 3.976200e+01, 3+4i, 1.290000e+01+3.600000e+00i, &u2.T::arr[4], u2.another.arr[2], {5, 1, 2, 3}, {{{}}, {{}}, &u1.T::arr[2]})'}} + +struct V { +  // FIXME: when we can generate these as constexpr constructors, remove the +  // explicit definitions. +  constexpr V() : arr{[255] = 42} {} +  constexpr V(const V &v) : arr{[255] = 42} {} +  int arr[256]; +}; +constexpr V v; +constexpr int get(const int *p) { return *p; } // expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr int passLargeArray(V v) { return get(v.arr+256); } // expected-note {{in call to 'get(&v.arr[256])'}} +static_assert(passLargeArray(v) == 0, ""); // expected-error {{constant expression}} expected-note {{in call to 'passLargeArray({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...}})'}} + +union Union { +  constexpr Union(int n) : b(n) {} +  constexpr Union(const Union &u) : b(u.b) {} +  int a, b; +}; +constexpr Union myUnion = 76; + +constexpr int badness(Union u) { return u.a + u.b; } // expected-note {{read of member 'a' of union with active member 'b'}} +static_assert(badness(myUnion), ""); // expected-error {{constant expression}} \ +        expected-note {{in call to 'badness({.b = 76})'}} + +struct MemPtrTest { +  int n; +  void f(); +}; +MemPtrTest mpt; // expected-note {{here}} +constexpr int MemPtr(int (MemPtrTest::*a), void (MemPtrTest::*b)(), int &c) { +  return c; // expected-note {{read of non-constexpr variable 'mpt'}} +} +static_assert(MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.*&MemPtrTest::n), ""); // expected-error {{constant expression}} \ +expected-note {{in call to 'MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.n)'}} + +template<typename CharT> +constexpr CharT get(const CharT *p) { return p[-1]; } // expected-note 5{{}} + +constexpr char c = get("test\0\\\"\t\a\b\234"); // \ +  expected-error {{}} expected-note {{"test\000\\\"\t\a\b\234"}} +constexpr char c8 = get(u8"test\0\\\"\t\a\b\234"); // \ +  expected-error {{}} expected-note {{u8"test\000\\\"\t\a\b\234"}} +constexpr char16_t c16 = get(u"test\0\\\"\t\a\b\234\u1234"); // \ +  expected-error {{}} expected-note {{u"test\000\\\"\t\a\b\234\u1234"}} +constexpr char32_t c32 = get(U"test\0\\\"\t\a\b\234\u1234\U0010ffff"); // \ +  expected-error {{}} expected-note {{U"test\000\\\"\t\a\b\234\u1234\U0010FFFF"}} +constexpr wchar_t wc = get(L"test\0\\\"\t\a\b\234\u1234\xffffffff"); // \ +  expected-error {{}} expected-note {{L"test\000\\\"\t\a\b\234\x1234\xFFFFFFFF"}} + +constexpr char32_t c32_err = get(U"\U00110000"); // expected-error {{invalid universal character}} + +typedef decltype(sizeof(int)) LabelDiffTy; +constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } // expected-note {{subexpression}} +void LabelDiffTest() { +  static_assert(mulBy3((LabelDiffTy)&&a-(LabelDiffTy)&&b) == 3, ""); // expected-error {{constant expression}} expected-note {{call to 'mulBy3(&&a - &&b)'}} +  a:b:return; +} + +constexpr bool test_bool_printing(bool b) { return 1 / !(2*b | !(2*b)); } // expected-note 2{{division by zero}} +constexpr bool test_bool_0 = test_bool_printing(false); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(false)'}} +constexpr bool test_bool_1 = test_bool_printing(true); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(true)'}} diff --git a/clang/test/SemaCXX/constexpr-strlen.cpp b/clang/test/SemaCXX/constexpr-strlen.cpp new file mode 100644 index 0000000..5e28e7f --- /dev/null +++ b/clang/test/SemaCXX/constexpr-strlen.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -pedantic + +# 1 "/usr/include/string.h" 1 3 4 +extern "C" { +  typedef decltype(sizeof(int)) size_t; +  extern size_t strlen(const char *p); +} + +# 10 "SemaCXX/constexpr-strlen.cpp" 2 +constexpr int n = __builtin_strlen("hello"); // ok +constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}} + +// Make sure we can evaluate a call to strlen. +int arr[3]; // expected-note {{here}} +int k = arr[strlen("hello")]; // expected-warning {{array index 5}} diff --git a/clang/test/SemaCXX/constexpr-turing.cpp b/clang/test/SemaCXX/constexpr-turing.cpp new file mode 100644 index 0000000..c515378 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-turing.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +// A direct proof that constexpr is Turing-complete, once DR1454 is implemented. + +const unsigned halt = (unsigned)-1; + +enum Dir { L, R }; +struct Action { +  bool tape; +  Dir dir; +  unsigned next; +}; +using State = Action[2]; + +// An infinite tape! +struct Tape { +  constexpr Tape() : l(0), val(false), r(0) {} +  constexpr Tape(const Tape &old, bool write) : +    l(old.l), val(write), r(old.r) {} +  constexpr Tape(const Tape &old, Dir dir) : +    l(dir == L ? old.l ? old.l->l : 0 : &old), +    val(dir == L ? old.l ? old.l->val : false +                 : old.r ? old.r->val : false), +    r(dir == R ? old.r ? old.r->r : 0 : &old) {} +  const Tape *l; +  bool val; +  const Tape *r; +}; +constexpr Tape update(const Tape &old, bool write) { return Tape(old, write); } +constexpr Tape move(const Tape &old, Dir dir) { return Tape(old, dir); } + +// Run turing machine 'tm' on tape 'tape' from state 'state'. Return number of +// steps taken until halt. +constexpr unsigned run(const State *tm, const Tape &tape, unsigned state) { +  return state == halt ? 1 : +         run(tm, move(update(tape, tm[state][tape.val].tape), +                      tm[state][tape.val].dir), +             tm[state][tape.val].next) + 1; +} + +// 3-state busy beaver. 14 steps. +constexpr State bb3[] = { +  { { true, R, 1 }, { true, L, 2 } }, +  { { true, L, 0 }, { true, R, 1 } }, +  { { true, L, 1 }, { true, R, halt } } +}; +static_assert(run(bb3, Tape(), 0) == 14, ""); + +// 4-state busy beaver. 108 steps. +constexpr State bb4[] = { +  { { true, R, 1 }, { true, L, 1 } }, +  { { true, L, 0 }, { false, L, 2 } }, +  { { true, R, halt }, { true, L, 3 } }, +  { { true, R, 3 }, { false, R, 0 } } }; +static_assert(run(bb4, Tape(), 0) == 108, ""); diff --git a/clang/test/SemaCXX/constexpr-value-init.cpp b/clang/test/SemaCXX/constexpr-value-init.cpp new file mode 100644 index 0000000..e459f09 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-value-init.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify + +struct A { +  constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{uninitialized}} +  int a; +  int b; +}; +struct B { +  A a; +}; + +constexpr A a; // ok, zero initialization preceeds static initialization +void f() { +  constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}} +} + +constexpr B b1; // expected-error {{requires a user-provided default constructor}} +constexpr B b2 = B(); // ok +static_assert(b2.a.a == 1, ""); +static_assert(b2.a.b == 2, ""); + +struct C { +  int c; +}; +struct D : C { int d; }; +constexpr C c1; // expected-error {{requires a user-provided default constructor}} +constexpr C c2 = C(); // ok +constexpr D d1; // expected-error {{requires a user-provided default constructor}} +constexpr D d2 = D(); // ok with DR1452 +static_assert(D().c == 0, ""); +static_assert(D().d == 0, ""); + +struct V : virtual C {}; +template<typename T> struct Z : T { +  constexpr Z() : V() {} +}; +constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{virtual base class}} diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp new file mode 100644 index 0000000..e8b7f0b --- /dev/null +++ b/clang/test/SemaCXX/constructor-initializer.cpp @@ -0,0 +1,282 @@ +// RUN: %clang_cc1 -Wreorder -fsyntax-only -verify %s +class A {  +  int m; +public: +   A() : A::m(17) { } // expected-error {{member initializer 'm' does not name a non-static data member or base class}} +   A(int); +}; + +class B : public A {  +public: +  B() : A(), m(1), n(3.14) { } + +private: +  int m; +  float n;   +}; + + +class C : public virtual B {  +public: +  C() : B() { } +}; + +class D : public C {  +public: +  D() : B(), C() { } +}; + +class E : public D, public B {  +public: +  E() : B(), D() { } // expected-error{{base class initializer 'B' names both a direct base class and an inherited virtual base class}} +}; + + +typedef int INT; + +class F : public B {  +public: +  int B; + +  F() : B(17), +        m(17), // expected-error{{member initializer 'm' does not name a non-static data member or base class}} +        INT(17) // expected-error{{constructor initializer 'INT' (aka 'int') does not name a class}} +  {  +  } +}; + +class G : A { +  G() : A(10); // expected-error{{expected '{'}} +}; + +void f() : a(242) { } // expected-error{{only constructors take base initializers}} + +class H : A { +  H(); +}; + +H::H() : A(10) { } + + +class  X {}; +class Y {}; + +struct S : Y, virtual X { +  S ();  +}; + +struct Z : S {  +  Z() : X(), S(), E()  {} // expected-error {{type 'E' is not a direct or virtual base of 'Z'}} +}; + +class U {  +  union { int a; char* p; }; +  union { int b; double d; }; + +  U() :  a(1), // expected-note {{previous initialization is here}} +         p(0), // expected-error {{initializing multiple members of union}} +         d(1.0)  {} +}; + +struct V {}; +struct Base {}; +struct Base1 {}; + +struct Derived : Base, Base1, virtual V { +  Derived (); +}; + +struct Current : Derived { +  int Derived; +  Current() : Derived(1), ::Derived(), // expected-warning {{field 'Derived' will be initialized after base '::Derived'}} \ +                                       // expected-warning {{base class '::Derived' will be initialized after base 'Derived::V'}} +                          ::Derived::Base(), // expected-error {{type '::Derived::Base' is not a direct or virtual base of 'Current'}} +                           Derived::Base1(), // expected-error {{type 'Derived::Base1' is not a direct or virtual base of 'Current'}} +                           Derived::V(), +                           ::NonExisting(), // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} +                           INT::NonExisting()  {} // expected-error {{expected a class or namespace}} \ +                                                  // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} +}; + +struct M {              // expected-note 2 {{candidate constructor (the implicit copy constructor)}} \ +                        // expected-note {{declared here}} \ +                        // expected-note {{declared here}} +  M(int i, int j);      // expected-note 2 {{candidate constructor}} +}; + +struct N : M  { +  N() : M(1),        // expected-error {{no matching constructor for initialization of 'M'}} +        m1(100) {  } // expected-error {{no matching constructor for initialization of 'M'}} +  M m1; +}; + +struct P : M  { +  P()  {  } // expected-error {{constructor for 'P' must explicitly initialize the base class 'M' which does not have a default constructor}} \ +            // expected-error {{member 'm'}} +  M m; // expected-note {{member is declared here}} +}; + +struct Q { +  Q() : f1(1,2),       // expected-error {{excess elements in scalar initializer}} +        pf(0.0)  { }   // expected-error {{cannot initialize a member subobject of type 'float *' with an rvalue of type 'double'}} +  float f1; + +  float *pf; +}; + +// A silly class used to demonstrate field-is-uninitialized in constructors with +// multiple params. +class TwoInOne { public: TwoInOne(TwoInOne a, TwoInOne b) {} }; +class InitializeUsingSelfTest { +  bool A; +  char* B; +  int C; +  TwoInOne D; +  InitializeUsingSelfTest(int E) +      : A(A),  // expected-warning {{field is uninitialized when used here}} +        B((((B)))),  // expected-warning {{field is uninitialized when used here}} +        C(A && InitializeUsingSelfTest::C),  // expected-warning {{field is uninitialized when used here}} +        D(D,  // expected-warning {{field is uninitialized when used here}} +          D) {}  // expected-warning {{field is uninitialized when used here}} +}; + +int IntWrapper(int i) { return 0; }; +class InitializeUsingSelfExceptions { +  int A; +  int B; +  int C; +  void *P; +  InitializeUsingSelfExceptions(int B) +      : A(IntWrapper(A)),  // Due to a conservative implementation, we do not report warnings inside function/ctor calls even though it is possible to do so. +        B(B),  // Not a warning; B is a local variable. +        C(sizeof(C)),  // sizeof doesn't reference contents, do not warn +        P(&P) {} // address-of doesn't reference contents (the pointer may be dereferenced in the same expression but it would be rare; and weird) +}; + +class CopyConstructorTest { +  bool A, B, C; +  CopyConstructorTest(const CopyConstructorTest& rhs) +      : A(rhs.A), +        B(B),  // expected-warning {{field is uninitialized when used here}} +        C(rhs.C || C) { }  // expected-warning {{field is uninitialized when used here}} +}; + +// Make sure we aren't marking default constructors when we shouldn't be. +template<typename T> +struct NDC { +  T &ref; +   +  NDC() { } +  NDC(T &ref) : ref(ref) { } +}; +   +struct X0 : NDC<int> { +  X0(int &ref) : NDC<int>(ref), ndc(ref) { } +   +  NDC<int> ndc; +}; + +namespace Test0 { + +struct A { A(); }; + +struct B { +  B() { }  +  const A a; +}; + +} + +namespace Test1 { +  struct A { +    enum Kind { Foo } Kind; +    A() : Kind(Foo) {} +  }; +} + +namespace Test2 { + +struct A {  +  A(const A&); +}; + +struct B : virtual A { }; +struct C : A, B { }; + +C f(C c) { +  return c; +} + +} + +// Don't build implicit initializers for anonymous union fields when we already +// have an explicit initializer for another field in the union. +namespace PR7402 { +  struct S { +    union { +      void* ptr_; +      struct { int i_; }; +    }; + +    template <typename T> S(T) : ptr_(0) { } +  }; + +  void f() { +    S s(3); +  } +} + +// <rdar://problem/8308215>: don't crash. +// Lots of questionable recovery here;  errors can change. +namespace test3 { +  class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 3 {{candidate}} expected-note {{passing argument}} +  class B : public A { +  public: +    B(const String& s, int e=0) // expected-error {{unknown type name}}  +      : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}} +    B(const B& e) +      : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{no viable conversion}} expected-error {{does not name}} +    } +  }; +} + +// PR8075 +namespace PR8075 { + +struct S1 { +  enum { FOO = 42 }; +  static const int bar = 42; +  static int baz(); +  S1(int); +}; + +const int S1::bar; + +struct S2 { +  S1 s1; +  S2() : s1(s1.FOO) {} +}; + +struct S3 { +  S1 s1; +  S3() : s1(s1.bar) {} +}; + +struct S4 { +  S1 s1; +  S4() : s1(s1.baz()) {} +}; + +} + +namespace PR12049 { +  int function(); + +  class Class +  { +  public: +      Class() : member(function() {} // expected-note {{to match this '('}} + +      int member; // expected-error {{expected ')'}} +  }; +} diff --git a/clang/test/SemaCXX/constructor-recovery.cpp b/clang/test/SemaCXX/constructor-recovery.cpp new file mode 100644 index 0000000..c1bb436 --- /dev/null +++ b/clang/test/SemaCXX/constructor-recovery.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct C { +  virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}} +}; + +void f() { + C c; +} diff --git a/clang/test/SemaCXX/constructor.cpp b/clang/test/SemaCXX/constructor.cpp new file mode 100644 index 0000000..f3b910d --- /dev/null +++ b/clang/test/SemaCXX/constructor.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +typedef int INT; + +class Foo { +  Foo(); +  (Foo)(float) { } +  explicit Foo(int); // expected-note {{previous declaration is here}} +  Foo(const Foo&); + +  ((Foo))(INT); // expected-error{{cannot be redeclared}} + +  Foo(Foo foo, int i = 17, int j = 42); // expected-error{{copy constructor must pass its first argument by reference}} + +  static Foo(short, short); // expected-error{{constructor cannot be declared 'static'}} +  virtual Foo(double); // expected-error{{constructor cannot be declared 'virtual'}} +  Foo(long) const; // expected-error{{'const' qualifier is not allowed on a constructor}} +   +  int Foo(int, int); // expected-error{{constructor cannot have a return type}} \ +  // expected-error{{member 'Foo' has the same name as its class}} +}; + +Foo::Foo(const Foo&) { } + +typedef struct { +  int version; +} Anon; +extern const Anon anon; +extern "C" const Anon anon2; + +// PR3188: The extern declaration complained about not having an appropriate +// constructor. +struct x; +extern x a; + +// A similar case. +struct y { +  y(int); +}; +extern y b; + +struct Length { +  Length l() const { return *this; } +}; + +// <rdar://problem/6815988> +struct mmst_reg{ + char mmst_reg[10]; +}; + +// PR3948 +namespace PR3948 { +// PR3948 +class a { +  public: +  int b(int a()); +}; +int x(); +void y() { +  a z; z.b(x); +} +} + +namespace A { +  struct S { +    S(); +    S(int); +    void f1(); +    void f2(); +    operator int (); +    ~S(); +  }; +} + +A::S::S() {} + +void A::S::f1() {} + +struct S {}; + +A::S::S(int) {} + +void A::S::f2() {} + +A::S::operator int() { return 1; } + +A::S::~S() {} + diff --git a/clang/test/SemaCXX/conversion-delete-expr.cpp b/clang/test/SemaCXX/conversion-delete-expr.cpp new file mode 100644 index 0000000..0f298a8 --- /dev/null +++ b/clang/test/SemaCXX/conversion-delete-expr.cpp @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Test1 +struct B { +  operator char *(); // expected-note {{candidate function}} +}; + +struct D : B { +  operator int *(); // expected-note {{candidate function}} +}; + +void f (D d) +{ +   delete d; // expected-error {{ambiguous conversion of delete expression of type 'D' to a pointer}} +} + +// Test2 +struct B1 { +  operator int *(); +}; + +struct D1 : B1 { +  operator int *(); +}; + +void f1 (D1 d) +{ +   delete d; +} + +// Test3 +struct B2 { +  operator const int *();	// expected-note {{candidate function}} +}; + +struct D2 : B2 { +  operator int *();	// expected-note {{candidate function}} +}; + +void f2 (D2 d) +{ +   delete d; // expected-error {{ambiguous conversion of delete expression of type 'D2' to a pointer}} +} + +// Test4 +struct B3 { +  operator const int *();	// expected-note {{candidate function}} +}; + +struct A3 { +  operator const int *();	// expected-note {{candidate function}} +}; + +struct D3 : A3, B3 { +}; + +void f3 (D3 d) +{ +   delete d; // expected-error {{ambiguous conversion of delete expression of type 'D3' to a pointer}} +} + +// Test5 +struct X { +   operator int(); +   operator int*(); +}; + +void f4(X x) { delete x; delete x; } + +// Test6 +struct X1 { +   operator int(); +   operator int*(); +   template<typename T> operator T*() const; // converts to any pointer! +}; + +void f5(X1 x) { delete x; }  // OK. In selecting a conversion to pointer function, template convesions are skipped. + +// Test7 +struct Base { +   operator int*();	 +}; + +struct Derived : Base { +   // not the same function as Base's non-const operator int() +   operator int*() const; +}; + +void foo6(const Derived cd, Derived d) { +	// overload resolution selects Derived::operator int*() const; +	delete cd; +	delete d;	 +} + +// Test8 +struct BB { +   template<typename T> operator T*() const; +}; + +struct DD : BB { +   template<typename T> operator T*() const; // hides base conversion +   operator int *() const; +}; + +void foo7 (DD d) +{ +        // OK. In selecting a conversion to pointer function, template convesions are skipped. +	delete d; +} diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp new file mode 100644 index 0000000..a7a1782 --- /dev/null +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -0,0 +1,394 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class X {  +public: +  operator bool(); +  operator int() const; + +  bool f() { +    return operator bool(); +  } + +  float g() { +    return operator float(); // expected-error{{use of undeclared 'operator float'}} +  } +}; + +operator int(); // expected-error{{conversion function must be a non-static member function}} + +operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}} + +typedef int func_type(int); +typedef int array_type[10]; + +class Y { +public: +  void operator bool(int, ...) const; // expected-error{{conversion function cannot have a return type}} \ +  // expected-error{{conversion function cannot have any parameters}} +   +  operator float(...) const;  // expected-error{{conversion function cannot be variadic}} +   +   +  operator func_type(); // expected-error{{conversion function cannot convert to a function type}} +  operator array_type(); // expected-error{{conversion function cannot convert to an array type}} +}; + + +typedef int INT; +typedef INT* INT_PTR; + +class Z {  +  operator int(); // expected-note {{previous declaration is here}} +  operator int**(); // expected-note {{previous declaration is here}} +   +  operator INT();  // expected-error{{conversion function cannot be redeclared}} +  operator INT_PTR*(); // expected-error{{conversion function cannot be redeclared}} +}; + + +class A { }; + +class B : public A { +public: +  operator A&() const; // expected-warning{{conversion function converting 'B' to its base class 'A' will never be used}} +  operator const void() const; // expected-warning{{conversion function converting 'B' to 'const void' will never be used}} +  operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}} +}; + +// This used to crash Clang. +struct Flip; +struct Flop { +  Flop(); +  Flop(const Flip&); // expected-note{{candidate constructor}} +}; +struct Flip { +  operator Flop() const; // expected-note{{candidate function}} +}; +Flop flop = Flip(); // expected-error {{conversion from 'Flip' to 'Flop' is ambiguous}} + +// This tests that we don't add the second conversion declaration to the list of user conversions +struct C { +  operator const char *() const; +}; + +C::operator const char*() const { return 0; } + +void f(const C& c) { +  const char* v = c; +} + +// Test. Conversion in base class is visible in derived class. +class XB {  +public: +  operator int(); // expected-note {{candidate function}} +}; + +class Yb : public XB {  +public: +  operator char(); // expected-note {{candidate function}} +}; + +void f(Yb& a) { +  if (a) { } // expected-error {{conversion from 'Yb' to 'bool' is ambiguous}} +  int i = a; // OK. calls XB::operator int(); +  char ch = a;  // OK. calls Yb::operator char(); +} + +// Test conversion + copy construction. +class AutoPtrRef { }; + +class AutoPtr { +  AutoPtr(AutoPtr &); // expected-note{{declared private here}} +   +public: +  AutoPtr(); +  AutoPtr(AutoPtrRef); +   +  operator AutoPtrRef(); +}; + +AutoPtr make_auto_ptr(); + +AutoPtr test_auto_ptr(bool Cond) { +  AutoPtr p1( make_auto_ptr() ); +   +  AutoPtr p; +  if (Cond) +    return p; // expected-error{{calling a private constructor}} +   +  return AutoPtr(); +} + +struct A1 { +  A1(const char *); +  ~A1(); + +private: +  A1(const A1&); // expected-note 2 {{declared private here}} +}; + +A1 f() { +  // FIXME: redundant diagnostics! +  return "Hello"; // expected-error {{calling a private constructor}} expected-warning {{an accessible copy constructor}} +} + +namespace source_locations { +  template<typename T> +  struct sneaky_int { +    typedef int type; +  }; + +  template<typename T, typename U> +  struct A { }; + +  template<typename T> +  struct A<T, T> : A<T, int> { }; + +  struct E { +    template<typename T> +    operator A<T, typename sneaky_int<T>::type>&() const; // expected-note{{candidate function}} +  }; + +  void f() { +    A<float, float> &af = E(); // expected-error{{no viable conversion}} +    A<float, int> &af2 = E(); +    const A<float, int> &caf2 = E(); +  } + +  // Check  +  template<typename T> +  struct E2 { +    operator T +    * // expected-error{{pointer to a reference}} +    () const; +  }; + +  E2<int&> e2i; // expected-note{{in instantiation}} +} + +namespace crazy_declarators { +  struct A { +    (&operator bool())(); // expected-error {{must use a typedef to declare a conversion to 'bool (&)()'}} + +    // FIXME: This diagnostic is misleading (the correct spelling +    // would be 'operator int*'), but it's a corner case of a +    // rarely-used syntax extension. +    *operator int();  // expected-error {{must use a typedef to declare a conversion to 'int *'}} +  }; +} + +namespace smart_ptr { +  class Y {  +    class YRef { }; + +    Y(Y&); + +  public: +    Y(); +    Y(YRef); + +    operator YRef(); // expected-note{{candidate function}} +  }; + +  struct X { // expected-note{{candidate constructor (the implicit copy constructor) not}} +    explicit X(Y); +  }; + +  Y make_Y(); + +  X f() { +    X x = make_Y(); // expected-error{{no viable conversion from 'smart_ptr::Y' to 'smart_ptr::X'}} +    X x2(make_Y()); +    return X(Y()); +  } +} + +struct Any { +  Any(...); +}; + +struct Other { +  Other(const Other &);  +  Other(); +}; + +void test_any() { +  Any any = Other(); // expected-error{{cannot pass object of non-POD type 'Other' through variadic constructor; call will abort at runtime}} +} + +namespace PR7055 { +  // Make sure that we don't allow too many conversions in an +  // auto_ptr-like template. In particular, we can't create multiple +  // temporary objects when binding to a reference. +  struct auto_ptr { +    struct auto_ptr_ref { }; + +    auto_ptr(auto_ptr&); +    auto_ptr(auto_ptr_ref); +    explicit auto_ptr(int *); + +    operator auto_ptr_ref(); +  }; + +  struct X { +    X(auto_ptr); +  }; + +  X f() { +    X x(auto_ptr(new int)); +    return X(auto_ptr(new int)); +  } + +  auto_ptr foo(); + +  X e(foo()); + +  struct Y { +    Y(X); +  }; +   +  Y f2(foo()); +} + +namespace PR7934 { +  typedef unsigned char uint8; + +  struct MutablePtr { +    MutablePtr() : ptr(0) {} +    void *ptr; + +    operator void*() { return ptr; } + +  private: +    operator uint8*() { return reinterpret_cast<uint8*>(ptr); } +    operator const char*() const { return reinterpret_cast<const char*>(ptr); } +  }; + +  void fake_memcpy(const void *); + +  void use() { +    MutablePtr ptr; +    fake_memcpy(ptr); +  } +} + +namespace rdar8018274 { +  struct X { }; +  struct Y { +    operator const struct X *() const; +  }; + +  struct Z : Y { +    operator struct X * (); +  }; + +  void test() { +    Z x; +    (void) (x != __null); +  } + + +  struct Base { +    operator int(); +  }; + +  struct Derived1 : Base { }; + +  struct Derived2 : Base { }; + +  struct SuperDerived : Derived1, Derived2 {  +    using Derived1::operator int; +  }; + +  struct UeberDerived : SuperDerived { +    operator long(); +  }; + +  void test2(UeberDerived ud) { +    int i = ud; // expected-error{{ambiguous conversion from derived class 'rdar8018274::SuperDerived' to base class 'rdar8018274::Base'}} +  } + +  struct Base2 { +    operator int(); +  }; + +  struct Base3 { +    operator int(); +  }; + +  struct Derived23 : Base2, Base3 {  +    using Base2::operator int; +  }; + +  struct ExtraDerived23 : Derived23 { }; + +  void test3(ExtraDerived23 ed) { +    int i = ed; +  } +} + +namespace PR8065 { +  template <typename T> struct Iterator; +  template <typename T> struct Container; + +  template<> +  struct Iterator<int> { +    typedef Container<int> container_type; +  }; + +  template <typename T> +  struct Container { +    typedef typename Iterator<T>::container_type X; +    operator X(void) { return X(); } +  }; + +  Container<int> test; +} + +namespace PR8034 { +  struct C { +    operator int(); + +  private: +    template <typename T> operator T(); +  }; +  int x = C().operator int(); +} + +namespace PR9336 { +  template<class T> +  struct generic_list +  { +    template<class Container> +    operator Container() +    {  +      Container ar; +      T* i; +      ar[0]=*i; +      return ar; +    } +  }; + +  template<class T> +  struct array +  { +    T& operator[](int); +    const T& operator[](int)const; +  }; + +  generic_list<generic_list<int> > l; +  array<array<int> > a = l; +} + +namespace PR8800 { +  struct A; +  struct C { +    operator A&(); +  }; +  void f() { +    C c; +    A& a1(c); +    A& a2 = c; +    A& a3 = static_cast<A&>(c); +    A& a4 = (A&)c; +  } +} diff --git a/clang/test/SemaCXX/conversion.cpp b/clang/test/SemaCXX/conversion.cpp new file mode 100644 index 0000000..a64b187 --- /dev/null +++ b/clang/test/SemaCXX/conversion.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion %s 2>&1 | FileCheck %s + +#include <stddef.h> + +typedef   signed char  int8_t; +typedef   signed short int16_t; +typedef   signed int   int32_t; +typedef   signed long  int64_t; + +typedef unsigned char  uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int   uint32_t; +typedef unsigned long  uint64_t; + +// <rdar://problem/7909130> +namespace test0 { +  int32_t test1_positive(char *I, char *E) { +    return (E - I); // expected-warning {{implicit conversion loses integer precision}} +  } + +  int32_t test1_negative(char *I, char *E) { +    return static_cast<int32_t>(E - I); +  } + +  uint32_t test2_positive(uint64_t x) { +    return x; // expected-warning {{implicit conversion loses integer precision}} +  } + +  uint32_t test2_negative(uint64_t x) { +    return (uint32_t) x; +  } +} + +namespace test1 { +  uint64_t test1(int x, unsigned y) { +    return sizeof(x == y); +  } + +  uint64_t test2(int x, unsigned y) { +    return __alignof(x == y); +  } + +  void * const foo(); +  bool test2(void *p) { +    return p == foo(); +  } +} + +namespace test2 { +  struct A { +    unsigned int x : 2; +    A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} +  }; +} + +// This file tests -Wnull-conversion, a subcategory of -Wconversion +// which is on by default. + +void test3() { +  int a = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} +  int b; +  b = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} +  long l = NULL; // FIXME: this should also warn, but currently does not if sizeof(NULL)==sizeof(inttype) +  int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} +  int d; +  d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} +  bool bl = NULL; // FIXME: this should warn but we currently suppress a bunch of conversion-to-bool warnings including this one +  char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}} +  unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}} +  short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}} + +  // Use FileCheck to ensure we don't get any unnecessary macro-expansion notes  +  // (that don't appear as 'real' notes & can't be seen/tested by -verify) +  // CHECK-NOT: note: +  // CHECK: note: expanded from macro 'FNULL' +#define FNULL NULL +  int a2 = FNULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} +  // CHECK-NOT: note: +  // CHECK: note: expanded from macro 'FINIT' +#define FINIT int a3 = NULL; +  FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}} +} diff --git a/clang/test/SemaCXX/convert-to-bool.cpp b/clang/test/SemaCXX/convert-to-bool.cpp new file mode 100644 index 0000000..c9a3555 --- /dev/null +++ b/clang/test/SemaCXX/convert-to-bool.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +struct ConvToBool { +  operator bool() const; +}; + +struct ConvToInt { +  operator int(); +}; + +struct ExplicitConvToBool { +  explicit operator bool(); // expected-warning{{explicit conversion functions are a C++11 extension}} +}; + +void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) { +  if (ctb) { } +  if (cti) { } +  if (ecb) { } +  for (; ctb; ) { } +  for (; cti; ) { } +  for (; ecb; ) { } +  while (ctb) { }; +  while (cti) { } +  while (ecb) { } +  do { } while (ctb); +  do { } while (cti); +  do { } while (ecb); + +  if (!ctb) { } +  if (!cti) { } +  if (!ecb) { } + +  bool b1 = !ecb; +  if (ctb && ecb) { } +  bool b2 = ctb && ecb; +  if (ctb || ecb) { } +  bool b3 = ctb || ecb; +} + +void accepts_bool(bool) { } // expected-note{{candidate function}} + +struct ExplicitConvToRef { +  explicit operator int&(); // expected-warning{{explicit conversion functions are a C++11 extension}} +}; + +void test_explicit_bool(ExplicitConvToBool ecb) { +  bool b1(ecb); // okay +  bool b2 = ecb; // expected-error{{no viable conversion from 'ExplicitConvToBool' to 'bool'}} +  accepts_bool(ecb); // expected-error{{no matching function for call to}} +} + +void test_explicit_conv_to_ref(ExplicitConvToRef ecr) { +  int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'ExplicitConvToRef'}} +  int& i2(ecr); // okay +} + +struct A { }; +struct B { }; +struct C { +  explicit operator A&(); // expected-warning{{explicit conversion functions are a C++11 extension}} +  operator B&(); // expected-note{{candidate}} +}; + +void test_copy_init_conversions(C c) { +  A &a = c; // expected-error{{no viable conversion from 'C' to 'A'}} +  B &b = b; // okay +} + diff --git a/clang/test/SemaCXX/converting-constructor.cpp b/clang/test/SemaCXX/converting-constructor.cpp new file mode 100644 index 0000000..1688e51 --- /dev/null +++ b/clang/test/SemaCXX/converting-constructor.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +class Z { }; + +class Y {  +public: +  Y(const Z&); +}; + +class X { +public: +  X(int); +  X(const Y&); +}; + +void f(X); // expected-note{{candidate function}} + +void g(short s, Y y, Z z) { +  f(s); +  f(1.0f); +  f(y); +  f(z); // expected-error{{no matching function}} +} + + +class FromShort { +public: +  FromShort(short s); +}; + +class FromShortExplicitly { // expected-note{{candidate constructor (the implicit copy constructor)}} +public: +  explicit FromShortExplicitly(short s); +}; + +void explicit_constructor(short s) { +  FromShort fs1(s); +  FromShort fs2 = s; +  FromShortExplicitly fse1(s); +  FromShortExplicitly fse2 = s; // expected-error{{no viable conversion}} +} + +// PR5519 +struct X1 { X1(const char&); }; +void x1(X1); +void y1() { +  x1(1); +} diff --git a/clang/test/SemaCXX/copy-assignment.cpp b/clang/test/SemaCXX/copy-assignment.cpp new file mode 100644 index 0000000..798582c --- /dev/null +++ b/clang/test/SemaCXX/copy-assignment.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +struct A { +}; + +struct ConvertibleToA { +  operator A(); +}; + +struct ConvertibleToConstA { +  operator const A(); +}; + +struct B { +  B& operator=(B&);  // expected-note 4 {{candidate function}} +}; + +struct ConvertibleToB { +  operator B(); +}; + +struct ConvertibleToBref { +  operator B&(); +}; + +struct ConvertibleToConstB { +  operator const B(); +}; + +struct ConvertibleToConstBref { +  operator const B&(); +}; + +struct C { +  int operator=(int); // expected-note{{candidate function}} +  long operator=(long); // expected-note{{candidate function}} +  int operator+=(int); // expected-note{{candidate function}} +  int operator+=(long); // expected-note{{candidate function}} +}; + +struct D { +  D& operator+=(const D &); +}; + +struct ConvertibleToInt { +  operator int(); +}; + +void test() { +  A a, na; +  const A constA = A(); +  ConvertibleToA convertibleToA; +  ConvertibleToConstA convertibleToConstA; + +  B b, nb; +  const B constB = B(); +  ConvertibleToB convertibleToB; +  ConvertibleToBref convertibleToBref; +  ConvertibleToConstB convertibleToConstB; +  ConvertibleToConstBref convertibleToConstBref; + +  C c, nc; +  const C constC = C(); + +  D d, nd; +  const D constD = D(); + +  ConvertibleToInt convertibleToInt; + +  na = a; +  na = constA; +  na = convertibleToA; +  na = convertibleToConstA; +  na += a; // expected-error{{no viable overloaded '+='}} + +  nb = b; +  nb = constB;  // expected-error{{no viable overloaded '='}} +  nb = convertibleToB; // expected-error{{no viable overloaded '='}} +  nb = convertibleToBref; +  nb = convertibleToConstB; // expected-error{{no viable overloaded '='}} +  nb = convertibleToConstBref; // expected-error{{no viable overloaded '='}} + +  nc = c; +  nc = constC; +  nc = 1; +  nc = 1L; +  nc = 1.0; // expected-error{{use of overloaded operator '=' is ambiguous}} +  nc += 1; +  nc += 1L; +  nc += 1.0; // expected-error{{use of overloaded operator '+=' is ambiguous}} + +  nd = d; +  nd += d; +  nd += constD; + +  int i; +  i = convertibleToInt; +  i = a; // expected-error{{assigning to 'int' from incompatible type 'A'}} +} + +// <rdar://problem/8315440>: Don't crash +namespace test1 { +  template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} +    A(UndeclaredType n) : X(n) {} // expected-error {{unknown type name 'UndeclaredType'}} +  }; +  template<typename T> class B : public A<T>     { +    virtual void foo() {} +  }; +  extern template class A<char>; +  extern template class B<char>; +} diff --git a/clang/test/SemaCXX/copy-constructor-error.cpp b/clang/test/SemaCXX/copy-constructor-error.cpp new file mode 100644 index 0000000..64a7d58 --- /dev/null +++ b/clang/test/SemaCXX/copy-constructor-error.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +struct S { +   S (S);  // expected-error {{copy constructor must pass its first argument by reference}} +}; + +S f(); + +void g() {  +  S a( f() ); +} + +namespace PR6064 { +  struct A { +    A() { } +    inline A(A&, int); // expected-note {{was not a special member function}} +  }; + +  A::A(A&, int = 0) { } // expected-warning {{makes this constructor a copy constructor}} + +  void f() { +    A const a; +    A b(a); +  } +} diff --git a/clang/test/SemaCXX/copy-initialization.cpp b/clang/test/SemaCXX/copy-initialization.cpp new file mode 100644 index 0000000..ea2db0c --- /dev/null +++ b/clang/test/SemaCXX/copy-initialization.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +class X { +public: +  explicit X(const X&); // expected-note {{candidate constructor}} +  X(int*); // expected-note 3{{candidate constructor}} +  explicit X(float*); // expected-note {{candidate constructor}} +}; + +class Y : public X { }; + +void f(Y y, int *ip, float *fp) { +  X x1 = y; // expected-error{{no matching constructor for initialization of 'X'}} +  X x2 = 0; +  X x3 = ip; +  X x4 = fp; // expected-error{{no viable conversion}} +  X x2a(0); // expected-error{{call to constructor of 'X' is ambiguous}} +  X x3a(ip); +  X x4a(fp); +} + +struct foo { + void bar(); // expected-note{{declared here}} +}; + +// PR3600 +void test(const foo *P) { P->bar(); } // expected-error{{'bar' not viable: 'this' argument has type 'const foo', but function is not marked const}} + +namespace PR6757 { +  struct Foo { +    Foo(); +    Foo(Foo&); // expected-note{{candidate constructor not viable}} +  }; + +  struct Bar { +    operator const Foo&() const; +  }; + +  void f(Foo); + +  void g(Foo foo) { +    f(Bar()); // expected-error{{no viable constructor copying parameter of type 'const PR6757::Foo'}} +    f(foo); +  } +} + +namespace DR5 { +  // Core issue 5: if a temporary is created in copy-initialization, it is of +  // the cv-unqualified version of the destination type. +  namespace Ex1 { +    struct C { }; +    C c; +    struct A { +        A(const A&); +        A(const C&); +    }; +    const volatile A a = c; // ok +  } + +  namespace Ex2 { +    struct S { +      S(S&&); // expected-warning {{C++11}} +      S(int); +    }; +    const S a(0); +    const S b = 0; +  } +} diff --git a/clang/test/SemaCXX/crashes.cpp b/clang/test/SemaCXX/crashes.cpp new file mode 100644 index 0000000..b77248e --- /dev/null +++ b/clang/test/SemaCXX/crashes.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/8124080> +template<typename _Alloc> class allocator; +template<class _CharT> struct char_traits; +template<typename _CharT, typename _Traits = char_traits<_CharT>,             +         typename _Alloc = allocator<_CharT> > +class basic_string; +template<typename _CharT, typename _Traits, typename _Alloc> +const typename basic_string<_CharT, _Traits, _Alloc>::size_type    +basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_max_size // expected-error{{no member named '_Rep' in 'basic_string<_CharT, _Traits, _Alloc>'}} +  = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;  + +// PR7118 +template<typename T> +class Foo { +  class Bar; +  void f() { +    Bar i; +  } +}; + +// PR7625 +template<typename T> struct a : T { + struct x : T { +   int aa() { return p; } // expected-error{{use of undeclared identifier 'p'}} + }; +}; + +// rdar://8605381 +namespace rdar8605381 { +struct X {}; + +struct Y { // expected-note{{candidate}} +  Y(); +}; + +struct { +  Y obj; +} objs[] = { +  new Y // expected-error{{no viable conversion}} +}; +} + +// http://llvm.org/PR8234 +namespace PR8234 { +template<typename Signature> +class callback +{ +}; + +template<typename R , typename ARG_TYPE0> +class callback<R( ARG_TYPE0)> +{ +    public: +        callback() {} +}; + +template< typename ARG_TYPE0> +class callback<void( ARG_TYPE0)> +{ +    public: +        callback() {} +}; + +void f() +{ +    callback<void(const int&)> op; +} +} + +namespace PR9007 { +  struct bar { +    enum xxx { +      yyy = sizeof(struct foo*) +    }; +    foo *xxx(); +  }; +} + +namespace PR9026 { +  class InfallibleTArray { +  }; +  class Variant; +  class CompVariant { +    operator const InfallibleTArray&() const; +  }; +  class Variant { +    operator const CompVariant&() const; +  }; +  void     Write(const Variant& __v); +  void     Write(const InfallibleTArray& __v); +  Variant x; +  void Write2() { +    Write(x); +  } +} + +namespace PR10270 { +  template<typename T> class C; +  template<typename T> void f() { +    if (C<T> == 1) // expected-error{{expected unqualified-id}} \ +                   // expected-error{{invalid '==' at end of declaration}} +      return; +  } +} diff --git a/clang/test/SemaCXX/cstyle-cast.cpp b/clang/test/SemaCXX/cstyle-cast.cpp new file mode 100644 index 0000000..12495ec --- /dev/null +++ b/clang/test/SemaCXX/cstyle-cast.cpp @@ -0,0 +1,231 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A {}; + +// ----------- const_cast -------------- + +typedef char c; +typedef c *cp; +typedef cp *cpp; +typedef cpp *cppp; +typedef cppp &cpppr; +typedef const cppp &cpppcr; +typedef const char cc; +typedef cc *ccp; +typedef volatile ccp ccvp; +typedef ccvp *ccvpp; +typedef const volatile ccvpp ccvpcvp; +typedef ccvpcvp *ccvpcvpp; +typedef int iar[100]; +typedef iar &iarr; +typedef int (*f)(int); + +void t_cc() +{ +  ccvpcvpp var = 0; +  // Cast away deep consts and volatiles. +  char ***var2 = (cppp)(var); +  char ***const &var3 = var2; +  // Const reference to reference. +  char ***&var4 = (cpppr)(var3); +  // Drop reference. Intentionally without qualifier change. +  char *** var5 = (cppp)(var4); +  const int ar[100] = {0}; +  // Array decay. Intentionally without qualifier change. +  int *pi = (int*)(ar); +  f fp = 0; +  // Don't misidentify fn** as a function pointer. +  f *fpp = (f*)(&fp); +  int const A::* const A::*icapcap = 0; +  int A::* A::* iapap = (int A::* A::*)(icapcap); +} + +// ----------- static_cast ------------- + +struct B : public A {};             // Single public base. +struct C1 : public virtual B {};    // Single virtual base. +struct C2 : public virtual B {}; +struct D : public C1, public C2 {}; // Diamond +struct E : private A {};            // Single private base. +struct F : public C1 {};            // Single path to B with virtual. +struct G1 : public B {}; +struct G2 : public B {}; +struct H : public G1, public G2 {}; // Ambiguous path to B. + +enum Enum { En1, En2 }; +enum Onom { On1, On2 }; + +struct Co1 { operator int(); }; +struct Co2 { Co2(int); }; +struct Co3 { }; +struct Co4 { Co4(Co3); operator Co3(); }; + +// Explicit implicits +void t_529_2() +{ +  int i = 1; +  (void)(float)(i); +  double d = 1.0; +  (void)(float)(d); +  (void)(int)(d); +  (void)(char)(i); +  (void)(unsigned long)(i); +  (void)(int)(En1); +  (void)(double)(En1); +  (void)(int&)(i); +  (void)(const int&)(i); + +  int ar[1]; +  (void)(const int*)(ar); +  (void)(void (*)())(t_529_2); + +  (void)(void*)(0); +  (void)(void*)((int*)0); +  (void)(volatile const void*)((const int*)0); +  (void)(A*)((B*)0); +  (void)(A&)(*((B*)0)); +  (void)(const B*)((C1*)0); +  (void)(B&)(*((C1*)0)); +  (void)(A*)((D*)0); +  (void)(const A&)(*((D*)0)); +  (void)(int B::*)((int A::*)0); +  (void)(void (B::*)())((void (A::*)())0); +  (void)(A*)((E*)0); // C-style cast ignores access control +  (void)(void*)((const int*)0); // const_cast appended + +  (void)(int)(Co1()); +  (void)(Co2)(1); +  (void)(Co3)((Co4)(Co3())); + +  // Bad code below +  //(void)(A*)((H*)0); // {{static_cast from 'struct H *' to 'struct A *' is not allowed}} +} + +// Anything to void +void t_529_4() +{ +  (void)(1); +  (void)(t_529_4); +} + +// Static downcasts +void t_529_5_8() +{ +  (void)(B*)((A*)0); +  (void)(B&)(*((A*)0)); +  (void)(const G1*)((A*)0); +  (void)(const G1&)(*((A*)0)); +  (void)(B*)((const A*)0); // const_cast appended +  (void)(B&)(*((const A*)0)); // const_cast appended +  (void)(E*)((A*)0); // access control ignored +  (void)(E&)(*((A*)0)); // access control ignored + +  // Bad code below + +  (void)(C1*)((A*)0); // expected-error {{cannot cast 'A *' to 'C1 *' via virtual base 'B'}} +  (void)(C1&)(*((A*)0)); // expected-error {{cannot cast 'A' to 'C1 &' via virtual base 'B'}} +  (void)(D*)((A*)0); // expected-error {{cannot cast 'A *' to 'D *' via virtual base 'B'}} +  (void)(D&)(*((A*)0)); // expected-error {{cannot cast 'A' to 'D &' via virtual base 'B'}} +  (void)(H*)((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}} +  (void)(H&)(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}} + +  // TODO: Test DR427. This requires user-defined conversions, though. +} + +// Enum conversions +void t_529_7() +{ +  (void)(Enum)(1); +  (void)(Enum)(1.0); +  (void)(Onom)(En1); + +  // Bad code below + +  (void)(Enum)((int*)0); // expected-error {{C-style cast from 'int *' to 'Enum' is not allowed}} +} + +// Void pointer to object pointer +void t_529_10() +{ +  (void)(int*)((void*)0); +  (void)(const A*)((void*)0); +  (void)(int*)((const void*)0); // const_cast appended +} + +// Member pointer upcast. +void t_529_9() +{ +  (void)(int A::*)((int B::*)0); + +  // Bad code below +  (void)(int A::*)((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} +  (void)(int A::*)((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} +} + +// -------- reinterpret_cast ----------- + +enum test { testval = 1 }; +struct structure { int m; }; +typedef void (*fnptr)(); + +// Test conversion between pointer and integral types, as in p3 and p4. +void integral_conversion() +{ +  void *vp = (void*)(testval); +  long l = (long)(vp); +  (void)(float*)(l); +  fnptr fnp = (fnptr)(l); +  (void)(char)(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}} +  (void)(long)(fnp); +} + +void pointer_conversion() +{ +  int *p1 = 0; +  float *p2 = (float*)(p1); +  structure *p3 = (structure*)(p2); +  typedef int **ppint; +  ppint *deep = (ppint*)(p3); +  (void)(fnptr*)(deep); +} + +void constness() +{ +  int ***const ipppc = 0; +  int const *icp = (int const*)(ipppc); +  (void)(int*)(icp); // const_cast appended +  int const *const **icpcpp = (int const* const**)(ipppc); // const_cast appended +  int *ip = (int*)(icpcpp); +  (void)(int const*)(ip); +  (void)(int const* const* const*)(ipppc); +} + +void fnptrs() +{ +  typedef int (*fnptr2)(int); +  fnptr fp = 0; +  (void)(fnptr2)(fp); +  void *vp = (void*)(fp); +  (void)(fnptr)(vp); +} + +void refs() +{ +  long l = 0; +  char &c = (char&)(l); +  // Bad: from rvalue +  (void)(int&)(&c); // expected-error {{C-style cast from rvalue to reference type 'int &'}} +} + +void memptrs() +{ +  const int structure::*psi = 0; +  (void)(const float structure::*)(psi); +  (void)(int structure::*)(psi); // const_cast appended + +  void (structure::*psf)() = 0; +  (void)(int (structure::*)())(psf); + +  (void)(void (structure::*)())(psi); // expected-error {{C-style cast from 'const int structure::*' to 'void (structure::*)()' is not allowed}} +  (void)(int structure::*)(psf); // expected-error {{C-style cast from 'void (structure::*)()' to 'int structure::*' is not allowed}} +} diff --git a/clang/test/SemaCXX/cv-unqual-rvalues.cpp b/clang/test/SemaCXX/cv-unqual-rvalues.cpp new file mode 100644 index 0000000..ed76ced --- /dev/null +++ b/clang/test/SemaCXX/cv-unqual-rvalues.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR7463: Make sure that when we have an rvalue, it does not have +// cv-qualified non-class type. +template <typename T_> void g (T_&); // expected-note 7{{not viable}} + +template<const int X> void h() {  +  g(X); // expected-error{{no matching function for call to 'g'}} +} + +template<typename T, T X> void h2() {  +  g(X); // expected-error{{no matching function for call to 'g'}} +} + +void a(__builtin_va_list x) { +  g(__builtin_va_arg(x, const int)); // expected-error{{no matching function for call to 'g'}} +  g((const int)0); // expected-error{{no matching function for call to 'g'}} +  typedef const int cint; +  g(cint(0)); // expected-error{{no matching function for call to 'g'}} +  g(static_cast<const int>(1)); // expected-error{{no matching function for call to 'g'}} +  g(reinterpret_cast<int *const>(0)); // expected-error{{no matching function for call to 'g'}} +  h<0>();  +  h2<const int, 0>(); // expected-note{{instantiation of}} +} diff --git a/clang/test/SemaCXX/cxx-member-pointer-op.cpp b/clang/test/SemaCXX/cxx-member-pointer-op.cpp new file mode 100644 index 0000000..f43d438 --- /dev/null +++ b/clang/test/SemaCXX/cxx-member-pointer-op.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s + +struct C { +  static int (C::* a); +}; + +typedef void (C::*pmfc)(); + +void g(pmfc) { +  C *c; +  c->*pmfc(); // expected-error {{invalid use of pointer to member type after ->*}} +  C c1; +  c1.*pmfc(); // expected-error {{invalid use of pointer to member type after .*}} +  c->*(pmfc()); // expected-error {{invalid use of pointer to member type after ->*}} +  c1.*((pmfc())); // expected-error {{invalid use of pointer to member type after .*}} +} + +int a(C* x) {  +  return x->*C::a;  +} + diff --git a/clang/test/SemaCXX/cxx0x-class.cpp b/clang/test/SemaCXX/cxx0x-class.cpp new file mode 100644 index 0000000..41b0a5c --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-class.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s  + +int vs = 0; + +class C { +public: +  struct NestedC { +    NestedC(int); +  }; + +  int i = 0; +  static int si = 0; // expected-error {{non-const static data member must be initialized out of line}} +  static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}} +  static const int nci = vs; // expected-error {{in-class initializer for static data member is not a constant expression}} +  static const int vi = 0; +  static const volatile int cvi = 0; // expected-error {{static const volatile data member must be initialized out of line}} +}; + +namespace rdar8367341 { +  float foo(); // expected-note {{here}} + +  struct A { +    static const float x = 5.0f; // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} +    static const float y = foo(); // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} expected-error {{in-class initializer for static data member is not a constant expression}} +    static constexpr float x2 = 5.0f; +    static constexpr float y2 = foo(); // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr function 'foo'}} +  }; +} + + +namespace Foo { +  // Regression test -- forward declaration of Foo should not cause error about +  // nonstatic data member. +  class Foo; +  class Foo { +    int x; +    int y = x; +  }; +} diff --git a/clang/test/SemaCXX/cxx0x-compat.cpp b/clang/test/SemaCXX/cxx0x-compat.cpp new file mode 100644 index 0000000..123008a --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-compat.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -verify %s + +namespace N { +  template<typename T> void f(T) {} // expected-note 2{{here}} +  namespace M { +    template void ::N::f<int>(int); // expected-warning {{explicit instantiation of 'f' not in a namespace enclosing 'N'}} +  } +} +using namespace N; +template void f<char>(char); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}} + +template<typename T> void g(T) {} // expected-note 2{{here}} +namespace M { +  template void g<int>(int); // expected-warning {{explicit instantiation of 'g' must occur at global scope}} +  template void ::g<char>(char); // expected-warning {{explicit instantiation of 'g' must occur at global scope}} +} + +template inline void g<double>(double); // expected-warning {{explicit instantiation cannot be 'inline'}} + +void g() { +  auto int n = 0; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} +} + +int n; +struct S { +  char c; +} +s = { n }, // expected-warning {{non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list in C++11}} expected-note {{explicit cast}} +t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which cannot be narrowed to type 'char' in C++11}} expected-warning {{changes value}} expected-note {{explicit cast}} + +#define PRIuS "uS" +int printf(const char *, ...); +typedef __typeof(sizeof(int)) size_t; +void h(size_t foo, size_t bar) { +  printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a reserved user-defined literal suffix in C++11}} +} + +#define _x + 1 +char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}} diff --git a/clang/test/SemaCXX/cxx0x-constexpr-const.cpp b/clang/test/SemaCXX/cxx0x-constexpr-const.cpp new file mode 100644 index 0000000..197edeb --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-constexpr-const.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +constexpr int x = 1; +constexpr int id(int x) { return x; } + +void foo(void) { +  x = 2; // expected-error {{read-only variable is not assignable}} +  int (*idp)(int) = id; +} + diff --git a/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp new file mode 100644 index 0000000..3290595 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct non_copiable { +  non_copiable(const non_copiable&) = delete; // expected-note {{marked deleted here}} +  non_copiable& operator = (const non_copiable&) = delete; // expected-note {{explicitly deleted}} +  non_copiable() = default; +}; + +struct non_const_copy { +  non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} +  non_const_copy& operator = (non_const_copy&) & = default; // expected-note {{not viable}} +  non_const_copy& operator = (non_const_copy&) && = default; // expected-note {{not viable}} +  non_const_copy() = default; // expected-note {{not viable}} +}; + +void fn1 () { +  non_copiable nc; +  non_copiable nc2 = nc; // expected-error {{deleted constructor}} +  nc = nc; // expected-error {{deleted operator}} + +  non_const_copy ncc; +  non_const_copy ncc2 = ncc; +  ncc = ncc2; +  const non_const_copy cncc; +  non_const_copy ncc3 = cncc; // expected-error {{no matching}} +  ncc = cncc; // expected-error {{no viable overloaded}} +}; + +struct non_const_derived : non_const_copy { +  non_const_derived(const non_const_derived&) = default; // expected-error {{requires it to be non-const}} +  non_const_derived& operator =(non_const_derived&) = default; +}; + +struct bad_decls { +  bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} +  bad_decls&& operator = (bad_decls) = default; // expected-error 2{{lvalue reference}} +  bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} +  bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const', 'constexpr' or 'volatile' qualifiers}} +}; + +struct A {}; struct B {}; + +struct except_spec_a { +  virtual ~except_spec_a() throw(A); +  except_spec_a() throw(A); +}; +struct except_spec_b { +  virtual ~except_spec_b() throw(B); +  except_spec_b() throw(B); +}; + +struct except_spec_d_good : except_spec_a, except_spec_b { +  ~except_spec_d_good(); +}; +except_spec_d_good::~except_spec_d_good() = default; +// FIXME: This should error in the virtual override check. +// It doesn't because we generate the implicit specification later than +// appropriate. +struct except_spec_d_bad : except_spec_a, except_spec_b { +  ~except_spec_d_bad() = default; +}; + +// FIXME: This should error because the exceptions spec doesn't match. +struct except_spec_d_mismatch : except_spec_a, except_spec_b { +  except_spec_d_mismatch() throw(A) = default; +}; +struct except_spec_d_match : except_spec_a, except_spec_b { +  except_spec_d_match() throw(A, B) = default; +};   + +// gcc-compatibility: allow attributes on default definitions +// (but not normal definitions) +struct S { S(); }; +S::S() __attribute((pure)) = default; + diff --git a/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp new file mode 100644 index 0000000..2e4107c --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void fn() = default; // expected-error {{only special member}} +struct foo { +  void fn() = default; // expected-error {{only special member}} + +  foo() = default; +  foo(const foo&) = default; +  foo(foo&) = default; +  foo& operator = (const foo&) = default; +  foo& operator = (foo&) = default; +  ~foo() = default; +}; + +struct bar { +  bar(); +  bar(const bar&); +  bar(bar&); +  bar& operator = (const bar&); +  bar& operator = (bar&); +  ~bar(); +}; + +bar::bar() = default; +bar::bar(const bar&) = default; +bar::bar(bar&) = default; +bar& bar::operator = (const bar&) = default; +bar& bar::operator = (bar&) = default; +bar::~bar() = default; + +static_assert(__is_trivial(foo), "foo should be trivial"); + +static_assert(!__has_trivial_destructor(bar), "bar's destructor isn't trivial"); +static_assert(!__has_trivial_constructor(bar), +              "bar's default constructor isn't trivial"); +static_assert(!__has_trivial_copy(bar), "bar has no trivial copy"); +static_assert(!__has_trivial_assign(bar), "bar has no trivial assign"); + +void tester() { +  foo f, g(f); +  bar b, c(b); +  f = g; +  b = c; +} + +template<typename T> struct S : T { +  constexpr S() = default; +  constexpr S(const S&) = default; +  constexpr S(S&&) = default; +}; +struct lit { constexpr lit() {} }; +S<lit> s_lit; // ok +S<bar> s_bar; // ok diff --git a/clang/test/SemaCXX/cxx0x-delegating-ctors.cpp b/clang/test/SemaCXX/cxx0x-delegating-ctors.cpp new file mode 100644 index 0000000..2d49f0f --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-delegating-ctors.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +struct foo { +  int i; +  foo(); +  foo(int); +  foo(int, int); +  foo(bool); +  foo(char); +  foo(const float*); +  foo(const float&); +  foo(void*); +}; + +// Good +foo::foo (int i) : i(i) { +} +// Good +foo::foo () : foo(-1) { +} +// Good +foo::foo (int, int) : foo() { +} + +foo::foo (bool) : foo(true) { // expected-error{{creates a delegation cycle}} +} + +// Good +foo::foo (const float* f) : foo(*f) { // expected-note{{it delegates to}} +} + +foo::foo (const float &f) : foo(&f) { //expected-error{{creates a delegation cycle}} \ +                                      //expected-note{{which delegates to}} +} + +foo::foo (char) : i(3), foo(3) { // expected-error{{must appear alone}} +} + +// This should not cause an infinite loop +foo::foo (void*) : foo(4.0f) { +} + +struct deleted_dtor { +  ~deleted_dtor() = delete; // expected-note{{function has been explicitly marked deleted here}} +  deleted_dtor(); +  deleted_dtor(int) : deleted_dtor() // expected-error{{attempt to use a deleted function}} +  {} +}; diff --git a/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp new file mode 100644 index 0000000..0cebc10 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -0,0 +1,131 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct non_trivial { +  non_trivial(); +  non_trivial(const non_trivial&); +  non_trivial& operator = (const non_trivial&); +  ~non_trivial(); +}; + +union bad_union { +  non_trivial nt; // expected-note {{non-trivial default constructor}} +}; +bad_union u; // expected-error {{call to implicitly-deleted default constructor}} +union bad_union2 { // expected-note {{all data members are const-qualified}} +  const int i; +}; +bad_union2 u2; // expected-error {{call to implicitly-deleted default constructor}} + +struct bad_anon { +  union { +    non_trivial nt; // expected-note {{non-trivial default constructor}} +  }; +}; +bad_anon a; // expected-error {{call to implicitly-deleted default constructor}} +struct bad_anon2 { +  union { // expected-note {{all data members of an anonymous union member are const-qualified}} +    const int i; +  }; +}; +bad_anon2 a2; // expected-error {{call to implicitly-deleted default constructor}} + +// This would be great except that we implement +union good_union { +  const int i; +  float f; +}; +good_union gu; +struct good_anon { +  union { +    const int i; +    float f; +  }; +}; +good_anon ga; + +struct good : non_trivial { +  non_trivial nt; +}; +good g; + +struct bad_const { +  const good g; // expected-note {{field 'g' of const-qualified type 'const good' would not be initialized}} +}; +bad_const bc; // expected-error {{call to implicitly-deleted default constructor}} + +struct good_const { +  const non_trivial nt; +}; +good_const gc; + +struct no_default { +  no_default() = delete; // expected-note 3{{deleted here}} +}; +struct no_dtor { +  ~no_dtor() = delete; // expected-note 2{{deleted here}} +}; + +struct bad_field_default { +  no_default nd; // expected-note {{field 'nd' has a deleted default constructor}} +}; +bad_field_default bfd; // expected-error {{call to implicitly-deleted default constructor}} +struct bad_base_default : no_default { // expected-note {{base class 'no_default' has a deleted default constructor}} +}; +bad_base_default bbd; // expected-error {{call to implicitly-deleted default constructor}} + +struct bad_field_dtor { +  no_dtor nd; // expected-note {{field 'nd' has a deleted destructor}} +}; +bad_field_dtor bfx; // expected-error {{call to implicitly-deleted default constructor}} +struct bad_base_dtor : no_dtor { // expected-note {{base class 'no_dtor' has a deleted destructor}} +}; +bad_base_dtor bbx; // expected-error {{call to implicitly-deleted default constructor}} + +struct ambiguous_default { +  ambiguous_default(); +  ambiguous_default(int = 2); +}; +struct has_amb_field { +  ambiguous_default ad; // expected-note {{field 'ad' has multiple default constructors}} +}; +has_amb_field haf; // expected-error {{call to implicitly-deleted default constructor}} + +class inaccessible_default { +  inaccessible_default(); +}; +struct has_inacc_field { +  inaccessible_default id; // expected-note {{field 'id' has an inaccessible default constructor}} +}; +has_inacc_field hif; // expected-error {{call to implicitly-deleted default constructor}} + +class friend_default { +  friend struct has_friend; +  friend_default(); +}; +struct has_friend { +  friend_default fd; +}; +has_friend hf; + +struct defaulted_delete { +  no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}} +  defaulted_delete() = default; // expected-note{{implicitly deleted here}} +}; +defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}} + +struct late_delete { +  no_default nd; +  late_delete(); +}; +late_delete::late_delete() = default; // expected-error {{would delete it}} + +// See also rdar://problem/8125400. +namespace empty { +  static union {}; +  static union { union {}; }; +  static union { struct {}; }; +  static union { union { union {}; }; }; +  static union { union { struct {}; }; }; +  static union { struct { union {}; }; }; +  static union { struct { struct {}; }; }; +} diff --git a/clang/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx0x-initializer-aggregates.cpp new file mode 100644 index 0000000..801a82f --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-initializer-aggregates.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct one { char c[1]; }; +struct two { char c[2]; }; + +namespace aggregate { +  // Direct list initialization does NOT allow braces to be elided! +  struct S { +    int ar[2]; +    struct T { +      int i1; +      int i2; +    } t; +    struct U { +      int i1; +    } u[2]; +    struct V { +      int var[2]; +    } v; +  }; + +  void bracing() { +    S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error +    S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced +    S s3{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} +    S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} +    S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} +  } + +  void bracing_new() { +    new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced +    new S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} +    new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} +    new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} +  } + +  void bracing_construct() { +    (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced +    (void) S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} +    (void) S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} +    (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} +  } + +  struct String { +    String(const char*); +  }; + +  struct A { +    int m1; +    int m2; +  }; + +  void function_call() { +    void takes_A(A); +    takes_A({1, 2}); +  } + +  struct B { +    int m1; +    String m2; +  }; + +  void overloaded_call() { +    one overloaded(A); +    two overloaded(B); + +    static_assert(sizeof(overloaded({1, 2})) == sizeof(one), "bad overload"); +    static_assert(sizeof(overloaded({1, "two"})) == sizeof(two), +      "bad overload"); +    // String is not default-constructible +    static_assert(sizeof(overloaded({1})) == sizeof(one), "bad overload"); +  } + +  struct C { int a[2]; C():a({1, 2}) { } }; // expected-error {{parenthesized initialization of a member array is a GNU extension}} +} + +namespace array_explicit_conversion { +  typedef int test1[2]; +  typedef int test2[]; +  template<int x> struct A { int a[x]; }; // expected-error {{'a' declared as an array with a negative size}} +  typedef A<1> test3[]; +  typedef A<-1> test4[]; +  void f() { +    (void)test1{1}; +    (void)test2{1}; +    (void)test3{{{1}}}; +    (void)test4{{{1}}}; // expected-note {{in instantiation of template class 'array_explicit_conversion::A<-1>' requested here}} +  } +} diff --git a/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp new file mode 100644 index 0000000..09aca24 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -0,0 +1,283 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct one { char c[1]; }; +struct two { char c[2]; }; + +namespace std { +  typedef decltype(sizeof(int)) size_t; + +  // libc++'s implementation +  template <class _E> +  class initializer_list +  { +    const _E* __begin_; +    size_t    __size_; + +    initializer_list(const _E* __b, size_t __s) +      : __begin_(__b), +        __size_(__s) +    {} + +  public: +    typedef _E        value_type; +    typedef const _E& reference; +    typedef const _E& const_reference; +    typedef size_t    size_type; + +    typedef const _E* iterator; +    typedef const _E* const_iterator; + +    initializer_list() : __begin_(nullptr), __size_(0) {} + +    size_t    size()  const {return __size_;} +    const _E* begin() const {return __begin_;} +    const _E* end()   const {return __begin_ + __size_;} +  }; +} + +namespace objects { + +  struct X1 { X1(int); }; +  struct X2 { explicit X2(int); }; // expected-note {{constructor declared here}} + +  template <int N> +  struct A { +    A() { static_assert(N == 0, ""); } +    A(int, double) { static_assert(N == 1, ""); } +  }; + +  template <int N> +  struct F { +    F() { static_assert(N == 0, ""); } +    F(int, double) { static_assert(N == 1, ""); } +    F(std::initializer_list<int>) { static_assert(N == 3, ""); } +  }; + +  template <int N> +  struct D { +    D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}} +    D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}} +  }; + +  template <int N> +  struct E { +    E(int, int) { static_assert(N == 0, ""); } +    E(X1, int) { static_assert(N == 1, ""); } +  }; + +  void overload_resolution() { +    { A<0> a{}; } +    { A<0> a = {}; } +    { A<1> a{1, 1.0}; } +    { A<1> a = {1, 1.0}; } + +    { F<0> f{}; } +    { F<0> f = {}; } +    // Narrowing conversions don't affect viability. The next two choose +    // the initializer_list constructor. +    // FIXME: Emit narrowing conversion errors. +    { F<3> f{1, 1.0}; } // xpected-error {{narrowing conversion}} +    { F<3> f = {1, 1.0}; } // xpected-error {{narrowing conversion}} +    { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } +    { F<3> f = {1, 2, 3, 4, 5, 6, 7, 8}; } +    { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } +    { F<3> f{1, 2}; } + +    { D<0> d{1, 2, 3}; } +    { D<1> d{1.0, 2.0, 3.0}; } +    { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}} + +    { E<0> e{1, 2}; } +  } + +  void explicit_implicit() { +    { X1 x{0}; } +    { X1 x = {0}; } +    { X2 x{0}; } +    { X2 x = {0}; } // expected-error {{constructor is explicit}} +  } + +  struct C { +    C(); +    C(int, double); +    C(int, int); + +    int operator[](C); +  }; + +  C function_call() { +    void takes_C(C); +    takes_C({1, 1.0}); + +    C c; +    c[{1, 1.0}]; + +    return {1, 1.0}; +  } + +  void inline_init() { +    (void) C{1, 1.0}; +    (void) new C{1, 1.0}; +    (void) A<1>{1, 1.0}; +    (void) new A<1>{1, 1.0}; +  } + +  struct B { // expected-note 2 {{candidate constructor}} +    B(C, int, C); // expected-note {{candidate constructor not viable: cannot convert initializer list argument to 'objects::C'}} +  }; + +  void nested_init() { +    B b1{{1, 1.0}, 2, {3, 4}}; +    B b2{{1, 1.0, 4}, 2, {3, 4}}; // expected-error {{no matching constructor for initialization of 'objects::B'}} +  } + +  void overloaded_call() { +    one ov1(B); // expected-note {{not viable: cannot convert initializer list}} +    two ov1(C); // expected-note {{not viable: cannot convert initializer list}} + +    static_assert(sizeof(ov1({})) == sizeof(two), "bad overload"); +    static_assert(sizeof(ov1({1, 2})) == sizeof(two), "bad overload"); +    static_assert(sizeof(ov1({{1, 1.0}, 2, {3, 4}})) == sizeof(one), "bad overload"); + +    ov1({1}); // expected-error {{no matching function}} + +    one ov2(int); +    two ov2(F<3>); +    static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity +    static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable +  } + +  struct G { // expected-note 6 {{not viable}} +    // This is not an initializer-list constructor. +    template<typename ...T> +    G(std::initializer_list<int>, T ...);  // expected-note 3 {{not viable}} +  }; + +  struct H { // expected-note 6 {{not viable}} +    explicit H(int, int); // expected-note 3 {{not viable}} expected-note {{declared here}} +    H(int, void*); // expected-note 3 {{not viable}} +  }; + +  void edge_cases() { +    // invalid (the first phase only considers init-list ctors) +    // (for the second phase, no constructor is viable) +    G g1{1, 2, 3}; // expected-error {{no matching constructor}} +    (void) new G{1, 2, 3}; // expected-error {{no matching constructor}} +    (void) G{1, 2, 3} // expected-error {{no matching constructor}} + +    // valid (T deduced to <>). +    G g2({1, 2, 3}); +    (void) new G({1, 2, 3}); +    (void) G({1, 2, 3}); + +    // invalid +    H h1({1, 2}); // expected-error {{no matching constructor}} +    (void) new H({1, 2}); // expected-error {{no matching constructor}} +    // FIXME: Bad diagnostic, mentions void type instead of init list. +    (void) H({1, 2}); // expected-error {{no matching conversion}} + +    // valid (by copy constructor). +    H h2({1, nullptr}); +    (void) new H({1, nullptr}); +    (void) H({1, nullptr}); + +    // valid +    H h3{1, 2}; +    (void) new H{1, 2}; +    (void) H{1, 2}; +  } + +  struct memberinit { +    H h1{1, nullptr}; +    H h2 = {1, nullptr}; +    H h3{1, 1}; +    H h4 = {1, 1}; // expected-error {{constructor is explicit}} +  }; +} + +namespace PR12092 { + +  struct S { +    S(const char*); +  }; +  struct V { +    template<typename T> V(T, T); +    void f(std::initializer_list<S>); +    void f(const V &); +  }; + +  void g() { +    extern V s; +    s.f({"foo", "bar"}); +  } + +} + +namespace PR12117 { +  struct A { A(int); };  +  struct B { B(A); } b{{0}}; +  struct C { C(int); } c{0}; +} + +namespace PR12167 { +  template<int N> struct string {}; + +  struct X { +    X(const char v); +    template<typename T> bool operator()(T) const; +  }; + +  template<int N, class Comparator> bool g(const string<N>& s, Comparator cmp) { +    return cmp(s); +  } +  template<int N> bool f(const string<N> &s) { +    return g(s, X{'x'}); +  } + +  bool s = f(string<1>()); +} + +namespace PR12257_PR12241 { +  struct command_pair +  { +    command_pair(int, int); +  }; + +  struct command_map +  { +    command_map(std::initializer_list<command_pair>); +  }; + +  struct generator_pair +  { +    generator_pair(const command_map); +  }; + +  // 5 levels: init list, gen_pair, command_map, init list, command_pair +  const std::initializer_list<generator_pair> x = {{{{{3, 4}}}}}; + +  // 4 levels: init list, gen_pair, command_map via init list, command_pair +  const std::initializer_list<generator_pair> y = {{{{1, 2}}}}; +} + +namespace PR12120 { +  struct A { explicit A(int); A(float); }; // expected-note {{declared here}} +  A a = { 0 }; // expected-error {{constructor is explicit}} + +  struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}} +  B b = { 0 }; // expected-error {{ambiguous}} +} + +namespace PR12498 { +  class ArrayRef; // expected-note{{forward declaration}} + +  struct C { +    void foo(const ArrayRef&); // expected-note{{passing argument to parameter here}} +  }; + +  static void bar(C* c) +  { +    c->foo({ nullptr, 1 }); // expected-error{{initialization of incomplete type 'const PR12498::ArrayRef'}} +  } + +} diff --git a/clang/test/SemaCXX/cxx0x-initializer-references.cpp b/clang/test/SemaCXX/cxx0x-initializer-references.cpp new file mode 100644 index 0000000..c4e9c90 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-initializer-references.cpp @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct one { char c; }; +struct two { char c[2]; }; + +namespace reference { +  struct A { +    int i1, i2; +  }; + +  void single_init() { +    const int &cri1a = {1}; +    const int &cri1b{1}; + +    int i = 1; +    int &ri1a = {i}; +    int &ri1b{i}; + +    int &ri2 = {1}; // expected-error {{cannot bind to an initializer list temporary}} + +    A a{1, 2}; +    A &ra1a = {a}; +    A &ra1b{a}; +  } + +  void reference_to_aggregate() { +    const A &ra1{1, 2}; +    A &ra2{1, 2}; // expected-error {{cannot bind to an initializer list temporary}} + +    const int (&arrayRef)[] = {1, 2, 3}; +    static_assert(sizeof(arrayRef) == 3 * sizeof(int), "bad array size"); +  } + +  struct B { +    int i1; +  }; + +  void call() { +    void f(const int&); +    f({1}); + +    void g(int&); // expected-note {{passing argument}} +    g({1}); // expected-error {{cannot bind to an initializer list temporary}} +    int i = 0; +    g({i}); + +    void h(const B&); +    h({1}); + +    void a(B&); // expected-note {{passing argument}} +    a({1}); // expected-error {{cannot bind to an initializer list temporary}} +    B b{1}; +    a({b}); +  } + +  void overloading() { +    one f(const int&); +    two f(const B&); + +    // First is identity conversion, second is user-defined conversion. +    static_assert(sizeof(f({1})) == sizeof(one), "bad overload resolution"); + +    one g(int&); +    two g(const B&); + +    static_assert(sizeof(g({1})) == sizeof(two), "bad overload resolution"); + +    one h(const int&); +    two h(const A&); + +    static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution"); +  } + +  void edge_cases() { +    // FIXME: very poor error message +    int const &b({0}); // expected-error {{could not bind}} +  } + +} + +namespace PR12182 { +  void f(int const(&)[3]); + +  void g() { +      f({1, 2}); +  } +} + +namespace PR12660 { +  const int &i { 1 }; +  struct S { S(int); } const &s { 2 }; +} diff --git a/clang/test/SemaCXX/cxx0x-initializer-scalars.cpp b/clang/test/SemaCXX/cxx0x-initializer-scalars.cpp new file mode 100644 index 0000000..627855e --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct one { char c[1]; }; +struct two { char c[2]; }; + +namespace std { +  typedef decltype(sizeof(int)) size_t; + +  // libc++'s implementation +  template <class _E> +  class initializer_list +  { +    const _E* __begin_; +    size_t    __size_; + +    initializer_list(const _E* __b, size_t __s) +      : __begin_(__b), +        __size_(__s) +    {} + +  public: +    typedef _E        value_type; +    typedef const _E& reference; +    typedef const _E& const_reference; +    typedef size_t    size_type; + +    typedef const _E* iterator; +    typedef const _E* const_iterator; + +    initializer_list() : __begin_(nullptr), __size_(0) {} + +    size_t    size()  const {return __size_;} +    const _E* begin() const {return __begin_;} +    const _E* end()   const {return __begin_ + __size_;} +  }; +} + +namespace integral { + +  void initialization() { +    { const int a{}; static_assert(a == 0, ""); } +    { const int a = {}; static_assert(a == 0, ""); } +    { const int a{1}; static_assert(a == 1, ""); } +    { const int a = {1}; static_assert(a == 1, ""); } +    { const int a{1, 2}; } // expected-error {{excess elements}} +    { const int a = {1, 2}; } // expected-error {{excess elements}} +    // FIXME: Redundant warnings. +    { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} +    { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} +    { if (const int a{1}) static_assert(a == 1, ""); } +    { if (const int a = {1}) static_assert(a == 1, ""); } +  } + +  int direct_usage() { +    int ar[10]; +    (void) ar[{1}]; // expected-error {{array subscript is not an integer}} + +    return {1}; +  } + +  void inline_init() { +    auto v = int{1}; +    (void) new int{1}; +  } + +  struct A { +    int i; +    A() : i{1} {} +  }; + +  void function_call() { +    void takes_int(int); +    takes_int({1}); +  } + +  void overloaded_call() { +    one overloaded(int); +    two overloaded(double); + +    static_assert(sizeof(overloaded({0})) == sizeof(one), "bad overload"); +    static_assert(sizeof(overloaded({0.0})) == sizeof(two), "bad overload"); + +    void ambiguous(int, double); // expected-note {{candidate}} +    void ambiguous(double, int); // expected-note {{candidate}} +    ambiguous({0}, {0}); // expected-error {{ambiguous}} + +    void emptylist(int); +    void emptylist(int, int, int); +    emptylist({}); +    emptylist({}, {}, {}); +  } + +  void edge_cases() { +    // FIXME: very poor error message +    int a({0}); // expected-error {{cannot initialize}} +    (void) int({0}); // expected-error {{functional-style cast}} +    new int({0});  // expected-error {{cannot initialize}} +  } + +  void default_argument(int i = {}) { +  } +  struct DefaultArgument { +    void default_argument(int i = {}) { +    } +  }; +} + +namespace PR12118 { +  void test() { +    one f(std::initializer_list<int>);  +    two f(int);  + +    // to initializer_list is preferred +    static_assert(sizeof(f({0})) == sizeof(one), "bad overload"); +  } +} diff --git a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp new file mode 100644 index 0000000..7384309 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -0,0 +1,177 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// This must obviously come before the definition of std::initializer_list. +void missing_initializerlist() { +  auto l = {1, 2, 3, 4}; // expected-error {{std::initializer_list was not found}} +} + +namespace std { +  typedef decltype(sizeof(int)) size_t; + +  // libc++'s implementation +  template <class _E> +  class initializer_list +  { +    const _E* __begin_; +    size_t    __size_; + +    initializer_list(const _E* __b, size_t __s) +      : __begin_(__b), +        __size_(__s) +    {} + +  public: +    typedef _E        value_type; +    typedef const _E& reference; +    typedef const _E& const_reference; +    typedef size_t    size_type; + +    typedef const _E* iterator; +    typedef const _E* const_iterator; + +    initializer_list() : __begin_(nullptr), __size_(0) {} + +    size_t    size()  const {return __size_;} +    const _E* begin() const {return __begin_;} +    const _E* end()   const {return __begin_ + __size_;} +  }; +} + +template <typename T, typename U> +struct same_type { static const bool value = false; }; +template <typename T> +struct same_type<T, T> { static const bool value = true; }; + +struct one { char c[1]; }; +struct two { char c[2]; }; + +struct A { +  int a, b; +}; + +struct B { +  B(); +  B(int, int); +}; + +void simple_list() { +  std::initializer_list<int> il = { 1, 2, 3 }; +  std::initializer_list<double> dl = { 1.0, 2.0, 3 }; +  std::initializer_list<A> al = { {1, 2}, {2, 3}, {3, 4} }; +  std::initializer_list<B> bl = { {1, 2}, {2, 3}, {} }; +} + +void function_call() { +  void f(std::initializer_list<int>); +  f({1, 2, 3}); + +  void g(std::initializer_list<B>); +  g({ {1, 2}, {2, 3}, {} }); +} + +struct C { +  C(int); +}; + +struct D { +  D(); +  operator int(); +  operator C(); +}; + +void overloaded_call() { +    one overloaded(std::initializer_list<int>); +    two overloaded(std::initializer_list<B>); + +    static_assert(sizeof(overloaded({1, 2, 3})) == sizeof(one), "bad overload"); +    static_assert(sizeof(overloaded({ {1, 2}, {2, 3}, {} })) == sizeof(two), "bad overload"); + +    void ambiguous(std::initializer_list<A>); // expected-note {{candidate}} +    void ambiguous(std::initializer_list<B>); // expected-note {{candidate}} +    ambiguous({ {1, 2}, {2, 3}, {3, 4} }); // expected-error {{ambiguous}} + +    one ov2(std::initializer_list<int>); // expected-note {{candidate}} +    two ov2(std::initializer_list<C>); // expected-note {{candidate}} +    // Worst sequence to int is identity, whereas to C it's user-defined. +    static_assert(sizeof(ov2({1, 2, 3})) == sizeof(one), "bad overload"); +    // But here, user-defined is worst in both cases. +    ov2({1, 2, D()}); // expected-error {{ambiguous}} +} + +template <typename T> +T deduce(std::initializer_list<T>); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}} +template <typename T> +T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}} + +void argument_deduction() { +  static_assert(same_type<decltype(deduce({1, 2, 3})), int>::value, "bad deduction"); +  static_assert(same_type<decltype(deduce({1.0, 2.0, 3.0})), double>::value, "bad deduction"); + +  deduce({1, 2.0}); // expected-error {{no matching function}} + +  static_assert(same_type<decltype(deduce_ref({1, 2, 3})), int>::value, "bad deduction"); +  static_assert(same_type<decltype(deduce_ref({1.0, 2.0, 3.0})), double>::value, "bad deduction"); + +  deduce_ref({1, 2.0}); // expected-error {{no matching function}} +} + +void auto_deduction() { +  auto l = {1, 2, 3, 4}; +  static_assert(same_type<decltype(l), std::initializer_list<int>>::value, ""); +  auto bl = {1, 2.0}; // expected-error {{cannot deduce}} + +  for (int i : {1, 2, 3, 4}) {} +} + +void dangle() { +  new auto{1, 2, 3}; // expected-error {{cannot use list-initialization}} +  new std::initializer_list<int>{1, 2, 3}; // expected-warning {{at the end of the full-expression}} +} + +struct haslist1 { +  std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the end of the constructor}} +  std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end of the constructor}} +  haslist1(); +}; + +haslist1::haslist1() +: il{1, 2, 3} // expected-warning{{at the end of the constructor}} +{} + +namespace PR12119 { +  // Deduction with nested initializer lists. +  template<typename T> void f(std::initializer_list<T>); +  template<typename T> void g(std::initializer_list<std::initializer_list<T>>); + +  void foo() { +    f({0, {1}}); +    g({{0, 1}, {2, 3}}); +    std::initializer_list<int> il = {1, 2}; +    g({il, {2, 3}}); +  } +} + +namespace Decay { +  template<typename T> +  void f(std::initializer_list<T>) { +    T x = 1; // expected-error{{cannot initialize a variable of type 'const char *' with an rvalue of type 'int'}} +  } + +  void g() { +    f({"A", "BB", "CCC"}); // expected-note{{in instantiation of function template specialization 'Decay::f<const char *>' requested here}} + +    auto x = { "A", "BB", "CCC" }; +    std::initializer_list<const char *> *il = &x; + +    for( auto s : {"A", "BB", "CCC", "DDD"}) { } +  } +} + +namespace PR12436 { +  struct X { +    template<typename T> +    X(std::initializer_list<int>, T); +  }; +   +  X x({}, 17); +} diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp new file mode 100644 index 0000000..0e4add8 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct non_trivial { +  non_trivial(); +  non_trivial(const non_trivial&); +  non_trivial& operator = (const non_trivial&); +  ~non_trivial(); +}; + +union u { +  non_trivial nt; +}; +union u2 { +  non_trivial nt; +  int k; +  u2(int k) : k(k) {} +  u2() : nt() {} +}; + +union static_data_member { +  static int i; +}; +int static_data_member::i; + +union bad { +  int &i; // expected-error {{union member 'i' has reference type 'int &'}} +}; + +struct s { +  union { +    non_trivial nt; +  }; +}; + +// Don't crash on this. +struct TemplateCtor { template<typename T> TemplateCtor(T); }; +union TemplateCtorMember { TemplateCtor s; }; + +template<typename T> struct remove_ref { typedef T type; }; +template<typename T> struct remove_ref<T&> { typedef T type; }; +template<typename T> struct remove_ref<T&&> { typedef T type; }; +template<typename T> T &&forward(typename remove_ref<T>::type &&t); +template<typename T> T &&forward(typename remove_ref<T>::type &t); +template<typename T> typename remove_ref<T>::type &&move(T &&t); + +using size_t = decltype(sizeof(int)); +void *operator new(size_t, void *p) noexcept { return p; } + +namespace disabled_dtor { +  template<typename T> +  union disable_dtor { +    T val; +    template<typename...U> +    disable_dtor(U &&...u) : val(forward<U>(u)...) {} +    ~disable_dtor() {} +  }; + +  struct deleted_dtor { +    deleted_dtor(int n, char c) : n(n), c(c) {} +    int n; +    char c; +    ~deleted_dtor() = delete; +  }; + +  disable_dtor<deleted_dtor> dd(4, 'x'); +} + +namespace optional { +  template<typename T> struct optional { +    bool has; +    union { T value; }; + +    optional() : has(false) {} +    template<typename...U> +    optional(U &&...u) : has(true), value(forward<U>(u)...) {} + +    optional(const optional &o) : has(o.has) { +      if (has) new (&value) T(o.value); +    } +    optional(optional &&o) : has(o.has) { +      if (has) new (&value) T(move(o.value)); +    } + +    optional &operator=(const optional &o) { +      if (has) { +        if (o.has) +          value = o.value; +        else +          value.~T(); +      } else if (o.has) { +        new (&value) T(o.value); +      } +      has = o.has; +    } +    optional &operator=(optional &&o) { +      if (has) { +        if (o.has) +          value = move(o.value); +        else +          value.~T(); +      } else if (o.has) { +        new (&value) T(move(o.value)); +      } +      has = o.has; +    } + +    ~optional() { +      if (has) +        value.~T(); +    } + +    explicit operator bool() const { return has; } +    T &operator*() const { return value; } +  }; + +  optional<non_trivial> o1; +  optional<non_trivial> o2{non_trivial()}; +  optional<non_trivial> o3{*o2}; +  void f() { +    if (o2) +      o1 = o2; +    o2 = optional<non_trivial>(); +  } +} diff --git a/clang/test/SemaCXX/cxx0x-return-init-list.cpp b/clang/test/SemaCXX/cxx0x-return-init-list.cpp new file mode 100644 index 0000000..da83271 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-return-init-list.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test that a very basic variation of generalized initializer returns (that +// required for libstdc++ 4.5) is supported in C++98. + +int test0(int i) { +  return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}} +} + +template<typename T, typename U> +T test1(U u) { +  return { u }; // expected-warning{{generalized initializer lists are a C++11 extension}} +} + +template int test1(char); +template long test1(int); diff --git a/clang/test/SemaCXX/cxx0x-type-convert-construct.cpp b/clang/test/SemaCXX/cxx0x-type-convert-construct.cpp new file mode 100644 index 0000000..6a7fe45 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-type-convert-construct.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s  + +void f() { +  char *u8str; +  u8str = u8"a UTF-8 string"; // expected-error {{assigning to 'char *' from incompatible type 'const char [15]'}} +  char16_t *ustr; +  ustr = u"a UTF-16 string"; // expected-error {{assigning to 'char16_t *' from incompatible type 'const char16_t [16]'}} +  char32_t *Ustr; +  Ustr = U"a UTF-32 string"; // expected-error {{assigning to 'char32_t *' from incompatible type 'const char32_t [16]'}} + +  char *Rstr; +  Rstr = R"foo(a raw string)foo"; // expected-warning{{conversion from string literal to 'char *' is deprecated}} +  wchar_t *LRstr; +  LRstr = LR"foo(a wide raw string)foo"; // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}} +  char *u8Rstr; +  u8Rstr = u8R"foo(a UTF-8 raw string)foo"; // expected-error {{assigning to 'char *' from incompatible type 'const char [19]'}} +  char16_t *uRstr; +  uRstr = uR"foo(a UTF-16 raw string)foo"; // expected-error {{assigning to 'char16_t *' from incompatible type 'const char16_t [20]'}} +  char32_t *URstr; +  URstr = UR"foo(a UTF-32 raw string)foo"; // expected-error {{assigning to 'char32_t *' from incompatible type 'const char32_t [20]'}} +} diff --git a/clang/test/SemaCXX/cxx11-ast-print.cpp b/clang/test/SemaCXX/cxx11-ast-print.cpp new file mode 100644 index 0000000..afabf88 --- /dev/null +++ b/clang/test/SemaCXX/cxx11-ast-print.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++11 -ast-print %s | FileCheck %s + +// FIXME: Print the trailing-return-type properly. +// CHECK: decltype(nullptr) operator "" _foo(const char *p, decltype(sizeof(int))); +auto operator"" _foo(const char *p, decltype(sizeof(int))) -> decltype(nullptr); + +// CHECK: decltype(""_foo) operator "" _bar(unsigned long long); +decltype(""_foo) operator"" _bar(unsigned long long); + +// CHECK: decltype(42_bar) operator "" _baz(long double); +decltype(42_bar) operator"" _baz(long double); + +// CHECK: decltype(4.5_baz) operator "" _baz(char); +decltype(4.5_baz) operator"" _baz(char); + +// CHECK: const char *operator "" _quux(const char *); +const char *operator"" _quux(const char *); + +// CHECK: template <char...> const char *operator "" _fritz(); +template<char...> const char *operator"" _fritz(); + +// CHECK: const char *p1 = "bar1"_foo; +const char *p1 = "bar1"_foo; +// CHECK: const char *p2 = "bar2"_foo; +const char *p2 = R"x(bar2)x"_foo; +// CHECK: const char *p3 = u8"bar3"_foo; +const char *p3 = u8"bar3"_foo; +// CHECK: const char *p4 = 297_bar; +const char *p4 = 0x129_bar; +// CHECK: const char *p5 = 1.0E+12_baz; +const char *p5 = 1e12_baz; +// CHECK: const char *p6 = 'x'_baz; +const char *p6 = 'x'_baz; +// CHECK: const char *p7 = 123_quux; +const char *p7 = 123_quux; +// CHECK: const char *p8 = 4.9_quux; +const char *p8 = 4.9_quux; +// CHECK: const char *p9 = 0x42e3F_fritz; +const char *p9 = 0x42e3F_fritz; +// CHECK: const char *p10 = 3.300e+15_fritz; +const char *p10 = 3.300e+15_fritz; diff --git a/clang/test/SemaCXX/cxx11-user-defined-literals.cpp b/clang/test/SemaCXX/cxx11-user-defined-literals.cpp new file mode 100644 index 0000000..4bbecdb --- /dev/null +++ b/clang/test/SemaCXX/cxx11-user-defined-literals.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -fms-extensions -triple x86_64-apple-darwin9.0.0 + +using size_t = decltype(sizeof(int)); +enum class LitKind { +  Char, WideChar, Char16, Char32, +  CharStr, WideStr, Char16Str, Char32Str, +  Integer, Floating, Raw, Template +}; +constexpr LitKind operator"" _kind(char p) { return LitKind::Char; } +constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; } +constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; } +constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; } +constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; } +constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; } +constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; } +constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; } +constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; } +constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; } +constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; } +template<char ...Cs> constexpr LitKind operator"" _kind3() { return LitKind::Template; } + +static_assert('x'_kind == LitKind::Char, ""); +static_assert(L'x'_kind == LitKind::WideChar, ""); +static_assert(u'x'_kind == LitKind::Char16, ""); +static_assert(U'x'_kind == LitKind::Char32, ""); +static_assert("foo"_kind == LitKind::CharStr, ""); +static_assert(u8"foo"_kind == LitKind::CharStr, ""); +static_assert(L"foo"_kind == LitKind::WideStr, ""); +static_assert(u"foo"_kind == LitKind::Char16Str, ""); +static_assert(U"foo"_kind == LitKind::Char32Str, ""); +static_assert(194_kind == LitKind::Integer, ""); +static_assert(0377_kind == LitKind::Integer, ""); +static_assert(0x5ffc_kind == LitKind::Integer, ""); +static_assert(.5954_kind == LitKind::Floating, ""); +static_assert(1._kind == LitKind::Floating, ""); +static_assert(1.e-2_kind == LitKind::Floating, ""); +static_assert(4e6_kind == LitKind::Floating, ""); +static_assert(4e6_kind2 == LitKind::Raw, ""); +static_assert(4e6_kind3 == LitKind::Template, ""); + +constexpr const char *fractional_digits_impl(const char *p) { +  return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0; +} +constexpr const char *operator"" _fractional_digits(const char *p) { +  return fractional_digits_impl(p) ?: p; +} +constexpr bool streq(const char *p, const char *q) { +  return *p == *q && (!*p || streq(p+1, q+1)); +} + +static_assert(streq(143.97_fractional_digits, "97"), ""); +static_assert(streq(0x786_fractional_digits, "0x786"), ""); +static_assert(streq(.4_fractional_digits, "4"), ""); +static_assert(streq(4._fractional_digits, ""), ""); +static_assert(streq(1e+97_fractional_digits, "1e+97"), ""); +static_assert(streq(0377_fractional_digits, "0377"), ""); +static_assert(streq(0377.5_fractional_digits, "5"), ""); + +int operator"" _ambiguous(char); // expected-note {{candidate}} +namespace N { +  void *operator"" _ambiguous(char); // expected-note {{candidate}} +} +using namespace N; +int k = 'x'_ambiguous; // expected-error {{ambiguous}} + +int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}} +int m = 42_deleted; // expected-error {{attempt to use a deleted}} + +namespace Using { +  namespace M { +    int operator"" _using(char); +  } +  int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator "" _using'}} + +  using M::operator "" _using; +  int k2 = 'x'_using; +} + +namespace AmbiguousRawTemplate { +  int operator"" _ambig1(const char *); // expected-note {{candidate}} +  template<char...> int operator"" _ambig1(); // expected-note {{candidate}} + +  int k1 = 123_ambig1; // expected-error {{call to 'operator "" _ambig1' is ambiguous}} + +  namespace Inner { +    template<char...> int operator"" _ambig2(); // expected-note 3{{candidate}} +  } +  int operator"" _ambig2(const char *); // expected-note 3{{candidate}} +  using Inner::operator"" _ambig2; + +  int k2 = 123_ambig2; // expected-error {{call to 'operator "" _ambig2' is ambiguous}} + +  namespace N { +    using Inner::operator"" _ambig2; + +    int k3 = 123_ambig2; // ok + +    using AmbiguousRawTemplate::operator"" _ambig2; + +    int k4 = 123_ambig2; // expected-error {{ambiguous}} + +    namespace M { + +      template<char...> int operator"" _ambig2(); + +      int k5 = 123_ambig2; // ok +    } + +    int operator"" _ambig2(unsigned long long); + +    int k6 = 123_ambig2; // ok +    int k7 = 123._ambig2; // expected-error {{ambiguous}} +  } +} + +constexpr unsigned mash(unsigned a) { + return 0x93ae27b5 * ((a >> 13) | a << 19); +} +template<typename=void> constexpr unsigned hash(unsigned a) { return a; } +template<char C, char...Cs> constexpr unsigned hash(unsigned a) { + return hash<Cs...>(mash(a ^ mash(C))); +} +template<typename T, T v> struct constant { constexpr static T value = v; }; +template<char...Cs> constexpr unsigned operator"" _hash() { +  return constant<unsigned, hash<Cs...>(0)>::value; +} +static_assert(0x1234_hash == 0x103eff5e, ""); +static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, ""); + +// Functions and literal suffixes go in separate namespaces. +namespace Namespace { +  template<char...> int operator"" _x(); +  int k = _x(); // expected-error {{undeclared identifier '_x'}} + +  int _y(unsigned long long); +  int k2 = 123_y; // expected-error {{no matching literal operator for call to 'operator "" _y'}} +} diff --git a/clang/test/SemaCXX/cxx98-compat-flags.cpp b/clang/test/SemaCXX/cxx98-compat-flags.cpp new file mode 100644 index 0000000..6dc24be --- /dev/null +++ b/clang/test/SemaCXX/cxx98-compat-flags.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Wno-bind-to-temporary-copy -Wno-unnamed-type-template-args -Wno-local-type-template-args -Werror %s + +template<typename T> int TemplateFn(T) { return 0; } +void LocalTemplateArg() { +  struct S {}; +  TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}} +} +struct {} obj_of_unnamed_type; // expected-note {{here}} +int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}} + +namespace CopyCtorIssues { +  struct Private { +    Private(); +  private: +    Private(const Private&); // expected-note {{declared private here}} +  }; +  struct NoViable { +    NoViable(); +    NoViable(NoViable&); // expected-note {{not viable}} +  }; +  struct Ambiguous { +    Ambiguous(); +    Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}} +    Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}} +  }; +  struct Deleted { +    Private p; // expected-note {{copy constructor of 'Deleted' is implicitly deleted because field 'p' has an inaccessible copy constructor}} +  }; + +  const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}} +  const NoViable &b = NoViable(); // expected-warning {{copying variable of type 'CopyCtorIssues::NoViable' when binding a reference to a temporary would find no viable constructor in C++98}} +  const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}} +  const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}} +} diff --git a/clang/test/SemaCXX/cxx98-compat-pedantic.cpp b/clang/test/SemaCXX/cxx98-compat-pedantic.cpp new file mode 100644 index 0000000..00532d5 --- /dev/null +++ b/clang/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Werror %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Werror %s + +// -Wc++98-compat-pedantic warns on C++11 features which we accept without a +// warning in C++98 mode. + +#line 32767 // ok +#line 32768 // expected-warning {{#line number greater than 32767 is incompatible with C++98}} + +#define VA_MACRO(x, ...) x // expected-warning {{variadic macros are incompatible with C++98}} +VA_MACRO(,x) // expected-warning {{empty macro argument list is incompatible with C++98}} + +; // expected-warning {{extra ';' outside of a function is incompatible with C++98}} + +enum Enum { +  Enum_value, // expected-warning {{commas at the end of enumerator lists are incompatible with C++98}} +}; + +template<typename T> struct InstantiationAfterSpecialization {}; +template<> struct InstantiationAfterSpecialization<int> {}; // expected-note {{here}} +template struct InstantiationAfterSpecialization<int>; // expected-warning {{explicit instantiation of 'InstantiationAfterSpecialization<int>' that occurs after an explicit specialization is incompatible with C++98}} + +void *dlsym(); +void (*FnPtr)() = (void(*)())dlsym(); // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}} +void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}} + +struct ConvertToInt { +  operator int(); +}; +int *ArraySizeConversion = new int[ConvertToInt()]; // expected-warning {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}} + +template<typename T> class ExternTemplate {}; +extern template class ExternTemplate<int>; // expected-warning {{extern templates are incompatible with C++98}} diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp new file mode 100644 index 0000000..82a9dc8 --- /dev/null +++ b/clang/test/SemaCXX/cxx98-compat.cpp @@ -0,0 +1,305 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s + +namespace std { struct type_info; } + +template<typename ...T>  // expected-warning {{variadic templates are incompatible with C++98}} +class Variadic1 {}; + +template<template<typename> class ...T>  // expected-warning {{variadic templates are incompatible with C++98}} +class Variadic2 {}; + +template<int ...I>  // expected-warning {{variadic templates are incompatible with C++98}} +class Variadic3 {}; + +int alignas(8) with_alignas; // expected-warning {{'alignas' is incompatible with C++98}} +int with_attribute [[ ]]; // expected-warning {{attributes are incompatible with C++98}} + +void Literals() { +  (void)u8"str"; // expected-warning {{unicode literals are incompatible with C++98}} +  (void)u"str"; // expected-warning {{unicode literals are incompatible with C++98}} +  (void)U"str"; // expected-warning {{unicode literals are incompatible with C++98}} +  (void)u'x'; // expected-warning {{unicode literals are incompatible with C++98}} +  (void)U'x'; // expected-warning {{unicode literals are incompatible with C++98}} + +  (void)u8R"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} +  (void)uR"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} +  (void)UR"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} +  (void)R"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} +  (void)LR"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} +} + +template<typename T> struct S {}; +namespace TemplateParsing { +  S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}} +  S< ::S<void>> t; // expected-warning {{consecutive right angle brackets are incompatible with C++98 (use '> >')}} +} + +void Lambda() { +  []{}(); // expected-warning {{lambda expressions are incompatible with C++98}} +} + +int InitList(int i = {}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} \ +                           // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} +  (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ +                    // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} +  (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ +               // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} +  int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} +  S<int> s = {}; // ok, aggregate +  s = {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} +  return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} +} +struct DelayedDefaultArgumentParseInitList { +  void f(int i = {1}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} +  } +}; + +int operator"" _hello(const char *); // expected-warning {{literal operators are incompatible with C++98}} + +enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}} +}; + +enum class EnumScoped { // expected-warning {{scoped enumerations are incompatible with C++98}} +}; + +void Deleted() = delete; // expected-warning {{deleted function definitions are incompatible with C++98}} +struct Defaulted { +  Defaulted() = default; // expected-warning {{defaulted function definitions are incompatible with C++98}} +}; + +int &&RvalueReference = 0; // expected-warning {{rvalue references are incompatible with C++98}} +struct RefQualifier { +  void f() &; // expected-warning {{reference qualifiers on functions are incompatible with C++98}} +}; + +auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}} + +void RangeFor() { +  int xs[] = {1, 2, 3}; +  for (int &a : xs) { // expected-warning {{range-based for loop is incompatible with C++98}} +  } +} + +struct InClassInit { +  int n = 0; // expected-warning {{in-class initialization of non-static data members is incompatible with C++98}} +}; + +struct OverrideControlBase { +  virtual void f(); +  virtual void g(); +}; +struct OverrideControl final : OverrideControlBase { // expected-warning {{'final' keyword is incompatible with C++98}} +  virtual void f() override; // expected-warning {{'override' keyword is incompatible with C++98}} +  virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}} +}; + +using AliasDecl = int; // expected-warning {{alias declarations are incompatible with C++98}} +template<typename T> using AliasTemplate = T; // expected-warning {{alias declarations are incompatible with C++98}} + +inline namespace InlineNS { // expected-warning {{inline namespaces are incompatible with C++98}} +} + +auto auto_deduction = 0; // expected-warning {{'auto' type specifier is incompatible with C++98}} +int *p = new auto(0); // expected-warning {{'auto' type specifier is incompatible with C++98}} + +const int align_of = alignof(int); // expected-warning {{alignof expressions are incompatible with C++98}} +char16_t c16 = 0; // expected-warning {{'char16_t' type specifier is incompatible with C++98}} +char32_t c32 = 0; // expected-warning {{'char32_t' type specifier is incompatible with C++98}} +constexpr int const_expr = 0; // expected-warning {{'constexpr' specifier is incompatible with C++98}} +decltype(const_expr) decl_type = 0; // expected-warning {{'decltype' type specifier is incompatible with C++98}} +__decltype(const_expr) decl_type2 = 0; // ok +void no_except() noexcept; // expected-warning {{noexcept specifications are incompatible with C++98}} +bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expressions are incompatible with C++98}} +void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}} +static_assert(true, "!"); // expected-warning {{static_assert declarations are incompatible with C++98}} + +// FIXME: Reintroduce this test if support for inheriting constructors is +//        implemented. +#if 0 +struct InhCtorBase { +  InhCtorBase(int); +}; +struct InhCtorDerived : InhCtorBase { +  using InhCtorBase::InhCtorBase; // xpected-warning {{inheriting constructors are incompatible with C++98}} +}; +#endif + +struct FriendMember { +  static void MemberFn(); +  friend void FriendMember::MemberFn(); // expected-warning {{friend declaration naming a member of the declaring class is incompatible with C++98}} +}; + +struct DelegCtor { +  DelegCtor(int) : DelegCtor() {} // expected-warning {{delegating constructors are incompatible with C++98}} +  DelegCtor(); +}; + +template<int n = 0> void DefaultFuncTemplateArg(); // expected-warning {{default template arguments for a function template are incompatible with C++98}} + +template<typename T> int TemplateFn(T) { return 0; } +void LocalTemplateArg() { +  struct S {}; +  TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}} +} +struct {} obj_of_unnamed_type; // expected-note {{here}} +int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}} + +namespace RedundantParensInAddressTemplateParam { +  int n; +  template<int*p> struct S {}; +  S<(&n)> s; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}} +  S<(((&n)))> t; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}} +} + +namespace TemplateSpecOutOfScopeNs { +  template<typename T> struct S {}; // expected-note {{here}} +} +template<> struct TemplateSpecOutOfScopeNs::S<char> {}; // expected-warning {{class template specialization of 'S' outside namespace 'TemplateSpecOutOfScopeNs' is incompatible with C++98}} + +struct Typename { +  template<typename T> struct Inner {}; +}; +typename ::Typename TypenameOutsideTemplate(); // expected-warning {{use of 'typename' outside of a template is incompatible with C++98}} +Typename::template Inner<int> TemplateOutsideTemplate(); // expected-warning {{use of 'template' keyword outside of a template is incompatible with C++98}} + +struct TrivialButNonPOD { +  int f(int); +private: +  int k; +}; +void Ellipsis(int n, ...); +void TrivialButNonPODThroughEllipsis() { +  Ellipsis(1, TrivialButNonPOD()); // expected-warning {{passing object of trivial but non-POD type 'TrivialButNonPOD' through variadic function is incompatible with C++98}} +} + +struct HasExplicitConversion { +  explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}} +}; + +struct Struct {}; +enum Enum { enum_val = 0 }; +struct BadFriends { +  friend enum ::Enum; // expected-warning {{befriending enumeration type 'enum ::Enum' is incompatible with C++98}} +  friend int; // expected-warning {{non-class friend type 'int' is incompatible with C++98}} +  friend Struct; // expected-warning {{befriending 'Struct' without 'struct' keyword is incompatible with C++98}} +}; + +int n = {}; // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} + +class PrivateMember { +  struct ImPrivate {}; +}; +template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}} +  return typename T::ImPrivate(); +} +int SFINAEAccessControl(...) { return 0; } +int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember()); + +template<typename T> +struct FriendRedefinition { +  friend void Friend() {} // expected-warning {{friend function 'Friend' would be implicitly redefined in C++98}} expected-note {{previous}} +}; +FriendRedefinition<int> FriendRedef1; +FriendRedefinition<char> FriendRedef2; // expected-note {{requested here}} + +namespace CopyCtorIssues { +  struct Private { +    Private(); +  private: +    Private(const Private&); // expected-note {{declared private here}} +  }; +  struct NoViable { +    NoViable(); +    NoViable(NoViable&); // expected-note {{not viable}} +  }; +  struct Ambiguous { +    Ambiguous(); +    Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}} +    Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}} +  }; +  struct Deleted { +    Private p; // expected-note {{implicitly deleted}} +  }; + +  const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}} +  const NoViable &b = NoViable(); // expected-warning {{copying variable of type 'CopyCtorIssues::NoViable' when binding a reference to a temporary would find no viable constructor in C++98}} +  const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}} +  const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}} +} + +namespace UnionOrAnonStructMembers { +  struct NonTrivCtor { +    NonTrivCtor(); // expected-note 2{{user-declared constructor}} +  }; +  struct NonTrivCopy { +    NonTrivCopy(const NonTrivCopy&); // expected-note 2{{user-declared copy constructor}} +  }; +  struct NonTrivDtor { +    ~NonTrivDtor(); // expected-note 2{{user-declared destructor}} +  }; +  union BadUnion { +    NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial constructor is incompatible with C++98}} +    NonTrivCopy ntcp; // expected-warning {{union member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} +    NonTrivDtor ntd; // expected-warning {{union member 'ntd' with a non-trivial destructor is incompatible with C++98}} +  }; +  struct Wrap { +    struct { +      NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial constructor is incompatible with C++98}} +      NonTrivCopy ntcp; // expected-warning {{anonymous struct member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} +      NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}} +    }; +  }; +  union WithStaticDataMember { +    static constexpr double d = 0.0; // expected-warning {{static data member 'd' in union is incompatible with C++98}} expected-warning {{'constexpr' specifier is incompatible with C++98}} +    static const int n = 0; // expected-warning {{static data member 'n' in union is incompatible with C++98}} +    static int k; // expected-warning {{static data member 'k' in union is incompatible with C++98}} +  }; +} + +int EnumNNS = Enum::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}} +template<typename T> void EnumNNSFn() { +  int k = T::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}} +}; +template void EnumNNSFn<Enum>(); // expected-note {{in instantiation}} + +void JumpDiagnostics(int n) { +  goto DirectJump; // expected-warning {{goto would jump into protected scope in C++98}} +  TrivialButNonPOD tnp1; // expected-note {{jump bypasses initialization of non-POD variable}} + +DirectJump: +  void *Table[] = {&&DirectJump, &&Later}; +  goto *Table[n]; // expected-warning {{indirect goto might cross protected scopes in C++98}} + +  TrivialButNonPOD tnp2; // expected-note {{jump bypasses initialization of non-POD variable}} +Later: // expected-note {{possible target of indirect goto}} +  switch (n) { +    TrivialButNonPOD tnp3; // expected-note {{jump bypasses initialization of non-POD variable}} +  default: // expected-warning {{switch case would be in a protected scope in C++98}} +    return; +  } +} + +namespace UnevaluatedMemberAccess { +  struct S { +    int n; +    int f() { return sizeof(S::n); } // ok +  }; +  int k = sizeof(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} +  const std::type_info &ti = typeid(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} +} + +namespace LiteralUCNs { +  char c1 = '\u001e'; // expected-warning {{universal character name referring to a control character is incompatible with C++98}} +  wchar_t c2 = L'\u0041'; // expected-warning {{specifying character 'A' with a universal character name is incompatible with C++98}} +  const char *s1 = "foo\u0031"; // expected-warning {{specifying character '1' with a universal character name is incompatible with C++98}} +  const wchar_t *s2 = L"bar\u0085"; // expected-warning {{universal character name referring to a control character is incompatible with C++98}} +} + +namespace NonTypeTemplateArgs { +  template<typename T, T v> struct S {}; +  const int k = 5; // expected-note {{here}} +  static void f() {} // expected-note {{here}} +  S<const int&, k> s1; // expected-warning {{non-type template argument referring to object 'k' with internal linkage is incompatible with C++98}} +  S<void(&)(), f> s2; // expected-warning {{non-type template argument referring to function 'f' with internal linkage is incompatible with C++98}} +} diff --git a/clang/test/SemaCXX/dcl_ambig_res.cpp b/clang/test/SemaCXX/dcl_ambig_res.cpp new file mode 100644 index 0000000..fa71b11 --- /dev/null +++ b/clang/test/SemaCXX/dcl_ambig_res.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s + +// [dcl.ambig.res]p1: +struct S {  +  S(int);  +  void bar(); +};  + +int returns_an_int(); + +void foo(double a)  +{  +  S w(int(a)); // expected-warning{{disambiguated}} +  w(17); +  S x1(int()); // expected-warning{{disambiguated}} +  x1(&returns_an_int); +  S y((int)a);  +  y.bar(); +  S z = int(a); +  z.bar(); +}  + +// [dcl.ambig.res]p3: +char *p;  +void *operator new(__SIZE_TYPE__, int);  +void foo3() {  +  const int x = 63;  +  new (int(*p)) int; //new-placement expression  +  new (int(*[x])); //new type-id  +}  + +// [dcl.ambig.res]p4: +template <class T>  // expected-note{{here}} +struct S4 {  +  T *p;  +};  +S4<int()> x; //type-id  +S4<int(1)> y; // expected-error{{must be a type}} + +// [dcl.ambig.res]p5: +void foo5()  +{  +  (void)sizeof(int(1)); //expression  +  // FIXME: should we make this an error rather than a warning?  +  // (It affects SFINAE) +  (void)sizeof(int()); // expected-warning{{function type}} +} + +// [dcl.ambig.res]p6: +void foo6()  +{  +  (void)(int(1)); //expression  +  (void)(int())1; // expected-error{{to 'int ()'}} +}  + +// [dcl.ambig.res]p7: +class C7 { };  +void f7(int(C7)) { } // expected-note{{candidate}} +int g7(C7);  +void foo7() {  +  f7(1); // expected-error{{no matching function}} +  f7(g7); //OK  +}  + +void h7(int *(C7[10])) { } // expected-note{{previous}} +void h7(int *(*_fp)(C7 _parm[10])) { } // expected-error{{redefinition}} + +struct S5 { +  static bool const value = false; +}; +int foo8() { +  int v(int(S5::value)); // expected-warning{{disambiguated}} expected-error{{parameter declarator cannot be qualified}} +} + +template<typename T> +void rdar8739801( void (T::*)( void ) __attribute__((unused)) ); diff --git a/clang/test/SemaCXX/dcl_init_aggr.cpp b/clang/test/SemaCXX/dcl_init_aggr.cpp new file mode 100644 index 0000000..bd3de9e --- /dev/null +++ b/clang/test/SemaCXX/dcl_init_aggr.cpp @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +// C++ [dcl.init.aggr]p2 +struct A {  +  int x; +  struct B {  +    int i; +    int j; +  } b;  +} a1 = { 1, { 2, 3 } }; + +struct NonAggregate { +  NonAggregate(); + +  int a, b; +}; +NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{non-aggregate type 'NonAggregate' cannot be initialized with an initializer list}} + +NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'NonAggregate' with an initializer list}} + + +// C++ [dcl.init.aggr]p3 +A a_init = A();  + +// C++ [dcl.init.aggr]p4 +int x[] = { 1, 3, 5 }; +int x_sizecheck[(sizeof(x) / sizeof(int)) == 3? 1 : -1]; +int x2[] = { }; // expected-warning{{zero size arrays are an extension}} + +// C++ [dcl.init.aggr]p5 +struct StaticMemberTest { +  int i; +  static int s; +  int *j; +} smt = { 1, &smt.i }; + +// C++ [dcl.init.aggr]p6 +char cv[4] = { 'a', 's', 'd', 'f', 0 }; // expected-error{{excess elements in array initializer}} + +// C++ [dcl.init.aggr]p7 +struct TooFew { int a; char* b; int c; };  +TooFew too_few = { 1, "asdf" }; // expected-warning{{conversion from string literal to 'char *' is deprecated}} + +struct NoDefaultConstructor { // expected-note 3 {{candidate constructor (the implicit copy constructor)}} \ +                              // expected-note{{declared here}} +  NoDefaultConstructor(int); // expected-note 3 {{candidate constructor}} +}; +struct TooFewError { // expected-error{{implicit default constructor for}} +  int a; +  NoDefaultConstructor nodef; // expected-note{{member is declared here}} +}; +TooFewError too_few_okay = { 1, 1 }; +TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} + +TooFewError too_few_okay2[2] = { 1, 1 }; // expected-note{{implicit default constructor for 'TooFewError' first required here}} +TooFewError too_few_error2[2] = { 1 }; // expected-error{{no matching constructor}} + +NoDefaultConstructor too_few_error3[3] = { }; // expected-error {{no matching constructor}} + +// C++ [dcl.init.aggr]p8 +struct Empty { }; +struct EmptyTest { +  Empty s; +  int i; +} empty_test = { { }, 3 }; + +EmptyTest empty_test2 = { 3 }; // expected-error{{initializer for aggregate with no elements requires explicit braces}} + +struct NonEmpty {  +  int a; +  Empty empty; +}; +struct NonEmptyTest { +  NonEmpty a, b; +} non_empty_test = { { }, { } }; + +// C++ [dcl.init.aggr]p9 +struct HasReference { +  int i; +  int &j; // expected-note{{uninitialized reference member is here}} +}; +int global_int; +HasReference r1 = { 1, global_int }; +HasReference r2 = { 1 } ; // expected-error{{reference member of type 'int &' uninitialized}} + +// C++ [dcl.init.aggr]p10 +// Note: the behavior here is identical to C +int xs[2][2] = { 3, 1, 4, 2 }; +float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; + +// C++ [dcl.init.aggr]p11 +// Note: the behavior here is identical to C +float y2[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 } }; +float same_as_y2[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; + +// C++ [dcl.init.aggr]p12 +struct A2 {  +  int i; +  operator int *(); +};  +struct B2 { +  A2 a1, a2;  +  int *z; +};  +struct C2 { +  operator A2(); +}; +struct D2 { +  operator int(); +}; +A2 a2; +C2 c2;  +D2 d2; +B2 b2 = { 4, a2, a2 }; +B2 b2_2 = { 4, d2, 0 }; +B2 b2_3 = { c2, a2, a2 }; + +// C++ [dcl.init.aggr]p15: +union u { int a; char* b; }; // expected-note{{candidate constructor (the implicit copy constructor)}} +u u1 = { 1 };  +u u2 = u1;  +u u3 = 1; // expected-error{{no viable conversion}} +u u4 = { 0, "asdf" };  // expected-error{{excess elements in union initializer}} +u u5 = { "asdf" }; // expected-error{{cannot initialize a member subobject of type 'int' with an lvalue of type 'const char [5]'}} diff --git a/clang/test/SemaCXX/decl-expr-ambiguity.cpp b/clang/test/SemaCXX/decl-expr-ambiguity.cpp new file mode 100644 index 0000000..6f4d08c --- /dev/null +++ b/clang/test/SemaCXX/decl-expr-ambiguity.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic-errors %s + +void f() { +  int a; +  struct S { int m; }; +  typedef S *T; + +  // Expressions. +  T(a)->m = 7; +  int(a)++; // expected-error {{assignment to cast is illegal}} +  __extension__ int(a)++; // expected-error {{assignment to cast is illegal}} +  __typeof(int)(a,5)<<a; // expected-error {{excess elements in scalar initializer}} +  void(a), ++a; +  if (int(a)+1) {} +  for (int(a)+1;;) {} // expected-warning {{expression result unused}} +  a = sizeof(int()+1); +  a = sizeof(int(1)); +  typeof(int()+1) a2; // expected-error {{extension used}} +  (int(1)); // expected-warning {{expression result unused}} + +  // type-id +  (int())1; // expected-error {{C-style cast from 'int' to 'int ()' is not allowed}} + +  // Declarations. +  int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}} +  T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-note {{previous definition is here}} +  typedef T(*td)(int(p)); +  extern T(*tp)(int(p)); +  T d3(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} +  T d3v(void); +  typedef T d3t(); +  extern T f3(); +  __typeof(*T()) f4(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} +  typedef void *V; +  __typeof(*V()) f5(); +  T multi1, +    multi2(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} +  T(d)[5]; // expected-error {{redefinition of 'd'}} +  typeof(int[])(f) = { 1, 2 }; // expected-error {{extension used}} +  void(b)(int); +  int(d2) __attribute__(()); +  if (int(a)=1) {} +  int(d3(int())); +} + +struct RAII { +  RAII(); +  ~RAII(); +}; + +void func(); +namespace N { +  struct S; + +  void emptyParens() { +    RAII raii(); // expected-warning {{function declaration}} expected-note {{remove parentheses to declare a variable}} +    int a, b, c, d, e, // expected-note {{change this ',' to a ';' to call 'func'}} +    func(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}} + +    S s(); // expected-warning {{function declaration}} +  } +} + +class C { }; +void fn(int(C)) { } // void fn(int(*fp)(C c)) { } expected-note{{candidate function}} +                    // not: void fn(int C); +int g(C); + +void foo() { +  fn(1); // expected-error {{no matching function}} +  fn(g); // OK +} diff --git a/clang/test/SemaCXX/decl-init-ref.cpp b/clang/test/SemaCXX/decl-init-ref.cpp new file mode 100644 index 0000000..4c635c1 --- /dev/null +++ b/clang/test/SemaCXX/decl-init-ref.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct A {}; + +struct BASE { +  operator A(); // expected-note {{candidate function}} +}; + +struct BASE1 { + operator A();  // expected-note {{candidate function}} +}; + +class B : public BASE , public BASE1 +{ +  public: +  B(); +} b; + +extern B f(); + +const int& ri = (void)0; // expected-error {{reference to type 'const int' could not bind to an rvalue of type 'void'}} + +int main() { +        const A& rca = f(); // expected-error {{reference initialization of type 'const A &' with initializer of type 'B' is ambiguous}} +        A& ra = f(); // expected-error {{non-const lvalue reference to type 'A' cannot bind to a temporary of type 'B'}} +} + +struct PR6139 { A (&x)[1]; }; +PR6139 x = {{A()}}; // expected-error{{non-const lvalue reference to type 'A [1]' cannot bind to a temporary of type 'A'}} diff --git a/clang/test/SemaCXX/decltype-98.cpp b/clang/test/SemaCXX/decltype-98.cpp new file mode 100644 index 0000000..db52565 --- /dev/null +++ b/clang/test/SemaCXX/decltype-98.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s +extern int x; +__decltype(1) x = 3; diff --git a/clang/test/SemaCXX/decltype-crash.cpp b/clang/test/SemaCXX/decltype-crash.cpp new file mode 100644 index 0000000..002bd4c --- /dev/null +++ b/clang/test/SemaCXX/decltype-crash.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +int& a(); + +void f() { +  decltype(a()) c; // expected-warning {{'decltype' is a keyword in C++11}} expected-error {{use of undeclared identifier 'decltype'}} +} diff --git a/clang/test/SemaCXX/decltype-overloaded-functions.cpp b/clang/test/SemaCXX/decltype-overloaded-functions.cpp new file mode 100644 index 0000000..b0a43a9 --- /dev/null +++ b/clang/test/SemaCXX/decltype-overloaded-functions.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +void f(); // expected-note{{possible target for call}} +void f(int); // expected-note{{possible target for call}} +decltype(f) a;  // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{variable has incomplete type 'decltype(f())' (aka 'void')}} + +template<typename T> struct S { +  decltype(T::f) * f; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{call to non-static member function without an object argument}} +}; + +struct K {  +  void f();  // expected-note{{possible target for call}} +  void f(int); // expected-note{{possible target for call}} +}; +S<K> b; // expected-note{{in instantiation of template class 'S<K>' requested here}} diff --git a/clang/test/SemaCXX/decltype-pr4444.cpp b/clang/test/SemaCXX/decltype-pr4444.cpp new file mode 100644 index 0000000..2f95075 --- /dev/null +++ b/clang/test/SemaCXX/decltype-pr4444.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +template<typename T, T t> +struct TestStruct { +   typedef decltype(t+2) sum_type; +}; diff --git a/clang/test/SemaCXX/decltype-pr4448.cpp b/clang/test/SemaCXX/decltype-pr4448.cpp new file mode 100644 index 0000000..9d33ce7 --- /dev/null +++ b/clang/test/SemaCXX/decltype-pr4448.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +template< typename T, T t, decltype(t+2) v > +struct Convoluted {}; + +int test_array[5]; + +Convoluted< int *, test_array, nullptr > tarray; diff --git a/clang/test/SemaCXX/decltype-this.cpp b/clang/test/SemaCXX/decltype-this.cpp new file mode 100644 index 0000000..a13416f --- /dev/null +++ b/clang/test/SemaCXX/decltype-this.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template<typename T, typename U> struct is_same { +  static const bool value = false; +}; + +template<typename T> struct is_same<T, T> { +  static const bool value = true; +}; + +struct S { +  void f() { static_assert(is_same<decltype(this), S*>::value, ""); } +  void g() const { static_assert(is_same<decltype(this), const S*>::value, ""); } +  void h() volatile { static_assert(is_same<decltype(this), volatile S*>::value, ""); } +  void i() const volatile { static_assert(is_same<decltype(this), const volatile S*>::value, ""); } +}; diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp new file mode 100644 index 0000000..a1200e0 --- /dev/null +++ b/clang/test/SemaCXX/decltype.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// PR5290 +int const f0(); +void f0_test() { +  decltype(0, f0()) i = 0; +  i = 0; +} + +struct A { int a[1]; A() { } }; +typedef A const AC; +int &f1(int*); +float &f2(int const*); + +void test_f2() { +  float &fr = f2(AC().a); +} + +namespace pr10154 { +  class A{ +      A(decltype(nullptr) param); +  }; +} + +template<typename T> struct S {}; +template<typename T> auto f(T t) -> decltype(S<int>(t)) { +  using U = decltype(S<int>(t)); +  using U = S<int>; +  return S<int>(t); +} diff --git a/clang/test/SemaCXX/default-arg-special-member.cpp b/clang/test/SemaCXX/default-arg-special-member.cpp new file mode 100644 index 0000000..8402d38 --- /dev/null +++ b/clang/test/SemaCXX/default-arg-special-member.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wno-default-arg-special-member -Werror -fsyntax-only %s + +class foo { +  foo(foo&, int); // expected-note {{was not a special member function}} +  foo(int); // expected-note {{was not a special member function}} +  foo(const foo&); // expected-note {{was a copy constructor}} +}; + +foo::foo(foo&, int = 0) { } // expected-warning {{makes this constructor a copy constructor}} +foo::foo(int = 0) { } // expected-warning {{makes this constructor a default constructor}} +foo::foo(const foo& = 0) { } //expected-warning {{makes this constructor a default constructor}} diff --git a/clang/test/SemaCXX/default-argument-temporaries.cpp b/clang/test/SemaCXX/default-argument-temporaries.cpp new file mode 100644 index 0000000..3ab7bf4 --- /dev/null +++ b/clang/test/SemaCXX/default-argument-temporaries.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct B { B(void* = 0); }; + +struct A { +  A(B b = B()) { } +}; + +void f() { +  (void)B(); +  (void)A(); +} diff --git a/clang/test/SemaCXX/default-assignment-operator.cpp b/clang/test/SemaCXX/default-assignment-operator.cpp new file mode 100644 index 0000000..668c600 --- /dev/null +++ b/clang/test/SemaCXX/default-assignment-operator.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class Base { // expected-error {{cannot define the implicit default assignment operator for 'Base', because non-static reference member 'ref' can't use default assignment operator}} \ +  // expected-warning{{class 'Base' does not declare any constructor to initialize its non-modifiable members}} +  int &ref;  // expected-note {{declared here}} \ +  // expected-note{{reference member 'ref' will never be initialized}} +}; + +class X  : Base {  // // expected-error {{cannot define the implicit default assignment operator for 'X', because non-static const member 'cint' can't use default assignment operator}} \ +// expected-note{{assignment operator for 'Base' first required here}} +public:  +  X(); +  const int cint;  // expected-note {{declared here}} +};  + +struct Y  : X {  +  Y(); +  Y& operator=(const Y&); +  Y& operator=(volatile Y&); +  Y& operator=(const volatile Y&); +  Y& operator=(Y&); +};  + +class Z : Y {}; + +Z z1; +Z z2; + +// Test1 +void f(X x, const X cx) { +  x = cx; // expected-note{{assignment operator for 'X' first required here}} +  x = cx; +  z1 = z2; +} + +// Test2 +class T {}; +T t1; +T t2; + +void g() { +  t1 = t2; +} + +// Test3 +class V { +public: +  V(); +  V &operator = (V &b); +}; + +class W : V {}; +W w1, w2; + +void h() { +  w1 = w2; +} + +// Test4 + +class B1 { +public: +  B1(); +  B1 &operator = (B1 b); +}; + +class D1 : B1 {}; +D1 d1, d2; + +void i() { +  d1 = d2; +} + +// Test5 + +class E1 { // expected-error{{cannot define the implicit default assignment operator for 'E1', because non-static const member 'a' can't use default assignment operator}} + +public: +  const int a; // expected-note{{declared here}} +  E1() : a(0) {}   + +}; + +E1 e1, e2; + +void j() { +  e1 = e2; // expected-note{{assignment operator for 'E1' first required here}} +} + +namespace ProtectedCheck { +  struct X { +  protected: +    X &operator=(const X&); // expected-note{{declared protected here}} +  }; + +  struct Y : public X { }; + +  void f(Y y) { y = y; } + +  struct Z { // expected-error{{'operator=' is a protected member of 'ProtectedCheck::X'}} +    X x; +  }; + +  void f(Z z) { z = z; }  // expected-note{{implicit default copy assignment operator}} + +} + +namespace MultiplePaths { +  struct X0 {  +    X0 &operator=(const X0&); +  }; + +  struct X1 : public virtual X0 { }; + +  struct X2 : X0, X1 { }; + +  void f(X2 x2) { x2 = x2; } +} diff --git a/clang/test/SemaCXX/default-constructor-initializers.cpp b/clang/test/SemaCXX/default-constructor-initializers.cpp new file mode 100644 index 0000000..e783f49 --- /dev/null +++ b/clang/test/SemaCXX/default-constructor-initializers.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X1 { // has no implicit default constructor +   X1(int); +}; + +struct X2  : X1 {  // expected-note 2 {{'X2' declared here}} +   X2(int); +}; + +struct X3 : public X2 { // expected-error {{implicit default constructor for 'X3' must explicitly initialize the base class 'X2' which does not have a default constructor}} +}; +X3 x3; // expected-note {{first required here}} + + +struct X4 { // expected-error {{must explicitly initialize the member 'x2'}} \ +            // expected-error {{must explicitly initialize the reference member 'rx2'}} +  X2 x2; 	// expected-note {{member is declared here}} +  X2 & rx2; // expected-note {{declared here}} +}; + +X4 x4; // expected-note {{first required here}} + + +struct Y1 { // has no implicit default constructor +   Y1(int); +}; + +struct Y2  : Y1 {  +   Y2(int); +   Y2(); +}; + +struct Y3 : public Y2 { +}; +Y3 y3;  + +struct Y4 { +  Y2 y2;  +}; + +Y4 y4; + +// More tests + +struct Z1 { // expected-error {{must explicitly initialize the reference member 'z'}} \ +            // expected-error {{must explicitly initialize the const member 'c1'}} +  int& z;       // expected-note {{declared here}} +  const int c1; // expected-note {{declared here}} +  volatile int v1; +}; + +// Test default initialization which *requires* a constructor call for non-POD. +Z1 z1; // expected-note {{first required here}} + +// Ensure that value initialization doesn't use trivial implicit constructors. +namespace PR7948 { +  // Note that this is also non-POD to ensure we don't just special case PODs. +  struct S { const int x; ~S(); }; +  const S arr[2] = { { 42 } }; +} + +// This is valid +union U { +  const int i; +  float f; +}; +U u; diff --git a/clang/test/SemaCXX/default1.cpp b/clang/test/SemaCXX/default1.cpp new file mode 100644 index 0000000..ae6ef97 --- /dev/null +++ b/clang/test/SemaCXX/default1.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +void f(int i); +void f(int i = 0); // expected-note {{previous definition is here}} +void f(int i = 17); // expected-error {{redefinition of default argument}} + + +void g(int i, int j, int k = 3); +void g(int i, int j = 2, int k); +void g(int i = 1, int j, int k); + +void h(int i, int j = 2, int k = 3,  +       int l, // expected-error {{missing default argument on parameter 'l'}} +       int,   // expected-error {{missing default argument on parameter}} +       int n);// expected-error {{missing default argument on parameter 'n'}} + +struct S { } s; +void i(int = s) { } // expected-error {{no viable conversion}} \ +// expected-note{{passing argument to parameter here}} + +struct X {  +  X(int); +}; + +void j(X x = 17); + +struct Y { // expected-note 2{{candidate}} +  explicit Y(int); +}; + +void k(Y y = 17); // expected-error{{no viable conversion}} \ +// expected-note{{passing argument to parameter 'y' here}} + +void kk(Y = 17); // expected-error{{no viable conversion}} \ +// expected-note{{passing argument to parameter here}} + +int l () { +  int m(int i, int j, int k = 3); +  if (1) +  { +    int m(int i, int j = 2, int k = 4); +    m(8); +  } +  return 0; +} + +int i () { +  void j (int f = 4); +  { +    void j (int f); // expected-note{{'j' declared here}} +    j(); // expected-error{{too few arguments to function call, expected 1, have 0}} +  } +} diff --git a/clang/test/SemaCXX/default2.cpp b/clang/test/SemaCXX/default2.cpp new file mode 100644 index 0000000..1626044 --- /dev/null +++ b/clang/test/SemaCXX/default2.cpp @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f(int i, int j, int k = 3); +void f(int i, int j, int k); +void f(int i, int j = 2, int k); +void f(int i, int j, int k); +void f(int i = 1, int j, int k); +void f(int i, int j, int k); + +void i() +{ +  f(); +  f(0); +  f(0, 1); +  f(0, 1, 2); +} + + +int f1(int i,          // expected-note {{previous declaration is here}} +       int i, int j) { // expected-error {{redefinition of parameter 'i'}} +  i = 17; +  return j; +}  + +int x; +void g(int x, int y = x); // expected-error {{default argument references parameter 'x'}} + +void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}} + +class X { +  void f(X* x = this); // expected-error{{invalid use of 'this' outside of a non-static member function}} + +  void g() {  +    int f(X* x = this); // expected-error{{default argument references 'this'}} +  } +}; + +// C++ [dcl.fct.default]p6 +class C {  +  static int x; +  void f(int i = 3); // expected-note{{previous definition is here}} +  void g(int i, int j = x);  + +  void h(); +};  +void C::f(int i = 3) // expected-error{{redefinition of default argument}} +{ }  + +void C::g(int i = 88, int j) {} + +void C::h() { +  g(); // okay +} + +// C++ [dcl.fct.default]p9 +struct Y {  +  int a;  +  int mem1(int i = a); // expected-error{{invalid use of non-static data member 'a'}} +  int mem2(int i = b); // OK; use Y::b  +  int mem3(int i); +  int mem4(int i); + +  struct Nested { +    int mem5(int i = b, // OK; use Y::b +             int j = c, // OK; use Y::Nested::c +             int k = j, // expected-error{{default argument references parameter 'j'}} +             int l = a,  // expected-error{{invalid use of non-static data member 'a'}} +             Nested* self = this, // expected-error{{invalid use of 'this' outside of a non-static member function}} +             int m); // expected-error{{missing default argument on parameter 'm'}} +    static int c; +    Nested(int i = 42); +  }; + +  int mem7(Nested n = Nested()); + +  static int b;  +};  + +int Y::mem3(int i = b) { return i; } // OK; use X::b + +int Y::mem4(int i = a) // expected-error{{invalid use of non-static data member 'a'}} +{ return i; } + + +// Try to verify that default arguments interact properly with copy +// constructors. +class Z { +public: +  Z(Z&, int i = 17); // expected-note 3 {{candidate constructor}} + +  void f(Z& z) {  +    Z z2;    // expected-error{{no matching constructor for initialization}} +    Z z3(z); +  } + +  void test_Z(const Z& z) { +    Z z2(z); // expected-error{{no matching constructor for initialization of 'Z'}} +  } +}; + +void test_Z(const Z& z) { +  Z z2(z); // expected-error{{no matching constructor for initialization of 'Z'}} +} + +struct ZZ { +  static ZZ g(int = 17); + +  void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}} \ +  // expected-note{{passing argument to parameter 'z' here}} + +  ZZ(ZZ&, int = 17); // expected-note{{candidate constructor}} +}; + +// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325 +class C2 { +  static void g(int = f()); // expected-error{{use of default argument to function 'f' that is declared later in class 'C2'}} +  static int f(int = 10); // expected-note{{default argument declared here}} +}; + +// Make sure we actually parse the default argument for an inline definition +class XX { +  void A(int length = -1 ) {  }  +  void B() { A(); } +}; diff --git a/clang/test/SemaCXX/defaulted-ctor-loop.cpp b/clang/test/SemaCXX/defaulted-ctor-loop.cpp new file mode 100644 index 0000000..6416336 --- /dev/null +++ b/clang/test/SemaCXX/defaulted-ctor-loop.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// WARNING: This test may recurse infinitely if failing. + +struct foo; +struct bar { +  bar(foo&); +}; +struct foo { +  bar b; +  foo() +    : b(b) // expected-warning{{field is uninitialized}} +  {} +}; diff --git a/clang/test/SemaCXX/defaulted-private-dtor.cpp b/clang/test/SemaCXX/defaulted-private-dtor.cpp new file mode 100644 index 0000000..e6f9555 --- /dev/null +++ b/clang/test/SemaCXX/defaulted-private-dtor.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s -fcxx-exceptions + +class BadDtor { +  // A private, but nonetheless trivial, destructor. +  ~BadDtor() = default; // expected-note 9{{here}} +  friend class K; +}; +void f() { +  BadDtor *p = new BadDtor[3]; // expected-error {{private destructor}} +  delete [] p; // expected-error {{private destructor}} +  const BadDtor &dd2 = BadDtor(); // expected-error {{private destructor}} +  BadDtor dd; // expected-error {{private destructor}} +  throw dd; // expected-error {{private destructor}} +} +struct V { +  V(); +  BadDtor bd; // expected-note {{inaccessible destructor}} +}; +V v; // expected-error {{deleted function}} +struct W : BadDtor { // expected-note {{inaccessible destructor}} +  W(); +}; +W w; // expected-error {{deleted function}} +struct X : BadDtor { // expected-error {{private destructor}} +  ~X() {} +}; +struct Y { +  BadDtor dd; // expected-error {{private destructor}} +  ~Y() {} +}; +struct Z : virtual BadDtor { // expected-error {{private destructor}} +  ~Z() {} +}; +BadDtor dd; // expected-error {{private destructor}} + +class K : BadDtor { +  void f() { +    BadDtor *p = new BadDtor[3]; +    delete [] p; +    const BadDtor &dd2 = BadDtor(); +    BadDtor dd; +    throw dd; + +    { +      BadDtor x; +      goto dont_call_dtor; +    } +dont_call_dtor: +    ; +  } +  struct Z : virtual BadDtor { +    ~Z() {} +  }; +  BadDtor dd; +  ~K(); +}; diff --git a/clang/test/SemaCXX/delete.cpp b/clang/test/SemaCXX/delete.cpp new file mode 100644 index 0000000..5824fac --- /dev/null +++ b/clang/test/SemaCXX/delete.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: cp %s %t +// RUN: %clang_cc1 -fixit -x c++ %t +// RUN: %clang_cc1 -E -o - %t | FileCheck %s + +void f(int a[10][20]) { +  // CHECK: delete[] a; +  delete a; // expected-warning {{'delete' applied to a pointer-to-array type}} +} diff --git a/clang/test/SemaCXX/deleted-function.cpp b/clang/test/SemaCXX/deleted-function.cpp new file mode 100644 index 0000000..d13fd0e --- /dev/null +++ b/clang/test/SemaCXX/deleted-function.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s + +int i = delete; // expected-error {{only functions can have deleted definitions}} + +void fn() = delete; // expected-note {{candidate function has been explicitly deleted}} + +void fn2(); // expected-note {{previous declaration is here}} +void fn2() = delete; // expected-error {{deleted definition must be first declaration}} + +void fn3() = delete; // expected-note {{previous definition is here}} +void fn3() { // expected-error {{redefinition}} +} + +void ov(int) {} // expected-note {{candidate function}} +void ov(double) = delete; // expected-note {{candidate function has been explicitly deleted}} + +struct WithDel { +  WithDel() = delete; // expected-note {{function has been explicitly marked deleted here}} +  void fn() = delete; // expected-note {{function has been explicitly marked deleted here}} +  operator int() = delete; // expected-note {{function has been explicitly marked deleted here}} +  void operator +(int) = delete; + +  int i = delete; // expected-error {{only functions can have deleted definitions}} +}; + +void test() { +  fn(); // expected-error {{call to deleted function 'fn'}} +  ov(1); +  ov(1.0); // expected-error {{call to deleted function 'ov'}} + +  WithDel dd; // expected-error {{call to deleted constructor of 'WithDel'}} +  WithDel *d = 0; +  d->fn(); // expected-error {{attempt to use a deleted function}} +  int i = *d; // expected-error {{invokes a deleted function}} +} + +struct DelDtor { +  ~DelDtor() = delete; // expected-note 9{{here}} +}; +void f() { +  DelDtor *p = new DelDtor[3]; // expected-error {{attempt to use a deleted function}} +  delete [] p; // expected-error {{attempt to use a deleted function}} +  const DelDtor &dd2 = DelDtor(); // expected-error {{attempt to use a deleted function}} +  DelDtor dd; // expected-error {{attempt to use a deleted function}} +  throw dd; // expected-error {{attempt to use a deleted function}} +} +struct X : DelDtor { +  ~X() {} // expected-error {{attempt to use a deleted function}} +}; +struct Y { +  DelDtor dd; +  ~Y() {} // expected-error {{attempt to use a deleted function}} +}; +struct Z : virtual DelDtor { +  ~Z() {} // expected-error {{attempt to use a deleted function}} +}; +DelDtor dd; // expected-error {{attempt to use a deleted function}} diff --git a/clang/test/SemaCXX/deleted-operator.cpp b/clang/test/SemaCXX/deleted-operator.cpp new file mode 100644 index 0000000..0e0282a --- /dev/null +++ b/clang/test/SemaCXX/deleted-operator.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct PR10757 { +  bool operator~() = delete; // expected-note {{explicitly deleted}} +  bool operator==(const PR10757&) = delete; // expected-note {{explicitly deleted}} +  operator float(); +}; +int PR10757f() { +  PR10757 a1; +  // FIXME: We get a ridiculous number of "built-in candidate" notes here... +  if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 6 {{built-in candidate}} +  if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 81 {{built-in candidate}} +} + +struct DelOpDel { +  virtual ~DelOpDel() {} // expected-error {{deleted function}} +  void operator delete(void*) = delete; // expected-note {{deleted here}} +}; diff --git a/clang/test/SemaCXX/dependent-auto.cpp b/clang/test/SemaCXX/dependent-auto.cpp new file mode 100644 index 0000000..6d37f7a --- /dev/null +++ b/clang/test/SemaCXX/dependent-auto.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +template<typename T> +struct only { +  only(T); +  template<typename U> only(U) = delete; // expected-note {{here}} +}; + +template<typename ...T> +void f(T ...t) { +  auto x(t...); // expected-error {{is empty}} expected-error {{contains multiple expressions}} +  only<int> check = x; +} + +void g() { +  f(); // expected-note {{here}} +  f(0); +  f(0, 1); // expected-note {{here}} +} + + +template<typename T> +bool h(T t) { +  auto a = t; +  decltype(a) b; +  a = a + b; + +  auto p = new auto(t); + +  only<double*> test = p; // expected-error {{conversion function from 'char *' to 'only<double *>'}} +  return p; +} + +bool b = h('x'); // expected-note {{here}} + +// PR 9276 - Make sure we check auto types deduce the same +// in the case of a dependent initializer +namespace PR9276 { +  template<typename T> +  void f() { +    auto i = T(), j = 0; // expected-error {{deduced as 'long' in declaration of 'i' and deduced as 'int' in declaration of 'j'}} +  } + +  void g() { +    f<long>(); // expected-note {{here}} +    f<int>(); +  } +} + +namespace NoRepeatedDiagnostic { +  template<typename T> +  void f() { +    auto a = 0, b = 0.0, c = T(); // expected-error {{deduced as 'int' in declaration of 'a' and deduced as 'double' in declaration of 'b'}} +  } +  // We've already diagnosed an issue. No extra diagnostics is needed for these. +  template void f<int>(); +  template void f<double>(); +  template void f<char>(); +} diff --git a/clang/test/SemaCXX/dependent-noexcept-unevaluated.cpp b/clang/test/SemaCXX/dependent-noexcept-unevaluated.cpp new file mode 100644 index 0000000..0a3a8bb --- /dev/null +++ b/clang/test/SemaCXX/dependent-noexcept-unevaluated.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s + +template <class T> +T&& +declval() noexcept; + +template <class T> +struct some_trait +{ +    static const bool value = false; +}; + +template <class T> +void swap(T& x, T& y) noexcept(some_trait<T>::value) +{ +    T tmp(static_cast<T&&>(x)); +    x = static_cast<T&&>(y); +    y = static_cast<T&&>(tmp); +} + +template <class T, unsigned N> +struct array +{ +    T data[N]; + +    void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>()))); +}; + +struct DefaultOnly +{ +    DefaultOnly() = default; +    DefaultOnly(const DefaultOnly&) = delete; +    DefaultOnly& operator=(const DefaultOnly&) = delete; +    ~DefaultOnly() = default; +}; + +int main() +{ +    array<DefaultOnly, 1> a, b; +} diff --git a/clang/test/SemaCXX/dependent-types.cpp b/clang/test/SemaCXX/dependent-types.cpp new file mode 100644 index 0000000..13ed72f --- /dev/null +++ b/clang/test/SemaCXX/dependent-types.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify -std=c++11 %s + +template<typename T> using U = int &; + +template<typename T, int Size> void f() { +  T x1; +  T* x2; +  T& x3; // expected-error{{declaration of reference variable 'x3' requires an initializer}} +  T x4[]; // expected-error{{needs an explicit size or an initializer}} +  T x5[Size]; +  int x6[Size]; +  U<T> x7; // expected-error{{declaration of reference variable 'x7' requires an initializer}} +} diff --git a/clang/test/SemaCXX/derived-to-base-ambig.cpp b/clang/test/SemaCXX/derived-to-base-ambig.cpp new file mode 100644 index 0000000..129ec79 --- /dev/null +++ b/clang/test/SemaCXX/derived-to-base-ambig.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class A { }; +class B : public A { }; +class C : public A { }; +class D : public B, public C { }; + +void f(D* d) { +  A* a; +  a = d; // expected-error{{ambiguous conversion from derived class 'D' to base class 'A':}} expected-error{{assigning to 'A *' from incompatible type 'D *'}} +} + +class Object2 { }; +class A2 : public Object2 { }; +class B2 : public virtual A2 { }; +class C2 : virtual public A2 { }; +class D2 : public B2, public C2 { }; +class E2 : public D2, public C2, public virtual A2 { }; +class F2 : public E2, public A2 { }; + +void g(E2* e2, F2* f2) { +  Object2* o2; +  o2 = e2; +  o2 = f2; // expected-error{{ambiguous conversion from derived class 'F2' to base class 'Object2':}} expected-error{{assigning to 'Object2 *' from incompatible type 'F2 *'}} +} + +// Test that ambiguous/inaccessibility checking does not trigger too +// early, because it should not apply during overload resolution. +void overload_okay(Object2*); +void overload_okay(E2*); + +void overload_call(F2* f2) { +  overload_okay(f2); +} diff --git a/clang/test/SemaCXX/destructor.cpp b/clang/test/SemaCXX/destructor.cpp new file mode 100644 index 0000000..f3c6ab0 --- /dev/null +++ b/clang/test/SemaCXX/destructor.cpp @@ -0,0 +1,365 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +class A { +public: +  ~A(); +}; + +class B { +public: +  ~B() { } +}; + +class C { +public: +  (~C)() { } +}; + +struct D { +  static void ~D(int, ...) const { } //                          \ +    // expected-error{{static member function cannot have 'const' qualifier}} \ +    // expected-error{{destructor cannot be declared 'static'}}  \ +    // expected-error{{destructor cannot have any parameters}}   \ +    // expected-error{{destructor cannot be variadic}} \ +    // expected-error{{destructor cannot have a return type}} \ +    // expected-error{{'const' qualifier is not allowed on a destructor}} +}; + +struct D2 { +  void ~D2() { } //                          \ +  // expected-error{{destructor cannot have a return type}}   +}; + + +struct E; + +typedef E E_typedef; +struct E { +  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}} +}; + +struct F { +  (~F)(); // expected-note {{previous declaration is here}} +  ~F(); // expected-error {{destructor cannot be redeclared}} +}; + +~; // expected-error {{expected a class name after '~' to name a destructor}} +~undef(); // expected-error {{expected the class name after '~' to name a destructor}} +~operator+(int, int);  // expected-error {{expected a class name after '~' to name a destructor}} +~F(){} // expected-error {{destructor must be a non-static member function}} + +struct G { +  ~G(); +}; + +G::~G() { } + +// <rdar://problem/6841210> +struct H { +  ~H(void) { }  +}; + +struct X {}; + +struct Y { +  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}} +}; + +namespace PR6421 { +  class T; // expected-note{{forward declaration}} + +  class QGenericArgument // expected-note{{declared here}} +  { +    template<typename U> +    void foo(T t) // expected-error{{variable has incomplete type}} +    { } +     +    void disconnect() +    { +      T* t; +      bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \ +      // expected-error{{does not refer to a value}} +    } +  }; +} + +namespace PR6709 { +  template<class T> class X { T v; ~X() { ++*v; } }; +  void a(X<int> x) {} +} + +struct X0 { virtual ~X0() throw(); }; +struct X1 : public X0 { }; + +// Make sure we instantiate operator deletes when building a virtual +// destructor. +namespace test6 { +  template <class T> class A { +  public: +    void *operator new(__SIZE_TYPE__); +    void operator delete(void *p) { +      T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}} +    } + +    virtual ~A() {} +  }; + +  class B : A<int> { B(); }; // expected-note {{in instantiation of member function 'test6::A<int>::operator delete' requested here}} +  B::B() {} +} + +// Make sure classes are marked invalid when they have invalid +// members.  This avoids a crash-on-invalid. +namespace test7 { +  struct A { +    ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}} +  }; +  struct B : A {}; + +  void test() { +    B *b; +    b->~B(); +  } +} + +namespace nonvirtualdtor { +struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}} +  virtual void m(); +}; + +struct S2 { +  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}} +  virtual void m(); +}; + +struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}} +  virtual void m(); +}; + +struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}} +  virtual void m(); +}; + +struct B { +  virtual ~B(); +  virtual void m(); +}; + +struct S5 : public B { +  virtual void m(); +}; + +struct S6 { +  virtual void m(); +private: +  ~S6(); +}; + +struct S7 { +  virtual void m(); +protected: +  ~S7(); +}; + +template<class T> class TS : public B { +  virtual void m(); +}; + +TS<int> baz; + +template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}} +  virtual void m(); +}; + +TS2<int> foo; // expected-note {{instantiation}} +} + +namespace dnvd { // delete-non-virtual-dtor warning +struct NP {}; + +struct B { // expected-warning {{has virtual functions but non-virtual destructor}} +  virtual void foo(); +}; + +struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} + +struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} + +struct VB { +  virtual void foo(); +  virtual ~VB(); +}; + +struct VD: VB {}; + +struct VF final: VB {}; + +template <typename T> +class simple_ptr { +public: +  simple_ptr(T* t): _ptr(t) {} +  ~simple_ptr() { delete _ptr; } // \ +    // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \ +    // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}} +  T& operator*() const { return *_ptr; } +private: +  T* _ptr; +}; + +template <typename T> +class simple_ptr2 { +public: +  simple_ptr2(T* t): _ptr(t) {} +  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} +  T& operator*() const { return *_ptr; } +private: +  T* _ptr; +}; + +void use(B&); +void use(VB&); + +void nowarnstack() { +  B b; use(b); +  D d; use(d); +  F f; use(f); +  VB vb; use(vb); +  VD vd; use(vd); +  VF vf; use(vf); +} + +void nowarnnonpoly() { +  { +    NP* np = new NP(); +    delete np; +  } +  { +    NP* np = new NP[4]; +    delete[] np; +  } +} + +void nowarnarray() { +  { +    B* b = new B[4]; +    delete[] b; +  } +  { +    D* d = new D[4]; +    delete[] d; +  } +  { +    VB* vb = new VB[4]; +    delete[] vb; +  } +  { +    VD* vd = new VD[4]; +    delete[] vd; +  } +} + +template <typename T> +void nowarntemplate() { +  { +    T* t = new T(); +    delete t; +  } +  { +    T* t = new T[4]; +    delete[] t; +  } +} + +void nowarn0() { +  { +    F* f = new F(); +    delete f; +  } +  { +    VB* vb = new VB(); +    delete vb; +  } +  { +    VB* vb = new VD(); +    delete vb; +  } +  { +    VD* vd = new VD(); +    delete vd; +  } +  { +    VF* vf = new VF(); +    delete vf; +  } +} + +void warn0() { +  { +    B* b = new B(); +    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} +  } +  { +    B* b = new D(); +    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} +  } +  { +    D* d = new D(); +    delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}} +  } +} + +void nowarn1() { +  { +    simple_ptr<F> f(new F()); +    use(*f); +  } +  { +    simple_ptr<VB> vb(new VB()); +    use(*vb); +  } +  { +    simple_ptr<VB> vb(new VD()); +    use(*vb); +  } +  { +    simple_ptr<VD> vd(new VD()); +    use(*vd); +  } +  { +    simple_ptr<VF> vf(new VF()); +    use(*vf); +  } +} + +void warn1() { +  { +    simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}} +    use(*b); +  } +  { +    simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}} +    use(*b); +  } +  { +    simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}} +    use(*d); +  } +} +} + +namespace PR9238 { +  class B { public: ~B(); }; +  class C : virtual B { public: ~C() { } }; +} + +namespace PR7900 { +  struct A { // expected-note 2{{type 'PR7900::A' is declared here}} +  }; +  struct B : public A { +  }; +  void foo() { +    B b; +    b.~B(); +    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}} +    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}} +  } +} diff --git a/clang/test/SemaCXX/direct-initializer.cpp b/clang/test/SemaCXX/direct-initializer.cpp new file mode 100644 index 0000000..a7899c7 --- /dev/null +++ b/clang/test/SemaCXX/direct-initializer.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +int x(1); +int (x2)(1); + +void f() { +  int x(1); +  int (x2)(1); +  for (int x(1);;) {} +} + +class Y {  +public: explicit Y(float); +}; + +class X { // expected-note{{candidate constructor (the implicit copy constructor)}} +public: +  explicit X(int); // expected-note{{candidate constructor}} +  X(float, float, float); // expected-note{{candidate constructor}} +  X(float, Y); // expected-note{{candidate constructor}} +}; + +class Z { // expected-note{{candidate constructor (the implicit copy constructor)}} +public: +  Z(int); // expected-note{{candidate constructor}} +}; + +void g() { +  X x1(5); +  X x2(1.0, 3, 4.2); +  X x3(1.0, 1.0); // expected-error{{no matching constructor for initialization of 'X'}} +  Y y(1.0); +  X x4(3.14, y); + +  Z z; // expected-error{{no matching constructor for initialization of 'Z'}} +} + +struct Base { +   operator int*() const;  +}; + +struct Derived : Base { +   operator int*(); // expected-note {{candidate function}} +}; + +void foo(const Derived cd, Derived d) { +        int *pi = cd;	// expected-error {{no viable conversion from 'const Derived' to 'int *'}} +        int *ppi = d;  + +} diff --git a/clang/test/SemaCXX/discrim-union.cpp b/clang/test/SemaCXX/discrim-union.cpp new file mode 100644 index 0000000..15c9a22 --- /dev/null +++ b/clang/test/SemaCXX/discrim-union.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -std=c++11 %s -fsyntax-only -fcxx-exceptions + +template<typename T> struct remove_reference { typedef T type; }; +template<typename T> struct remove_reference<T&> { typedef T type; }; +template<typename T> struct remove_reference<T&&> { typedef T type; }; + +template<typename T> constexpr T &&forward(typename remove_reference<T>::type &t) noexcept { return static_cast<T&&>(t); } +template<typename T> constexpr T &&forward(typename remove_reference<T>::type &&t) noexcept { return static_cast<T&&>(t); } +template<typename T> constexpr typename remove_reference<T>::type &&move(T &&t) noexcept { return static_cast<typename remove_reference<T>::type&&>(t); } + +template<typename T> T declval() noexcept; + +namespace detail { +  template<unsigned N> struct select {}; // : integral_constant<unsigned, N> {}; +  template<typename T> struct type {}; + +  template<typename...T> union either_impl; + +  template<> union either_impl<> { +    void get(...); +    void destroy(...) { throw "logic_error"; } +  }; + +  template<typename T, typename...Ts> union either_impl<T, Ts...> { +  private: +    T val; +    either_impl<Ts...> rest; +    typedef either_impl<Ts...> rest_t; + +  public: +    constexpr either_impl(select<0>, T &&t) : val(move(t)) {} + +    template<unsigned N, typename U> +    constexpr either_impl(select<N>, U &&u) : rest(select<N-1>(), move(u)) {} + +    constexpr static unsigned index(type<T>) { return 0; } +    template<typename U> +    constexpr static unsigned index(type<U> t) { +      return decltype(rest)::index(t) + 1; +    } + +    void destroy(unsigned elem) { +      if (elem) +        rest.destroy(elem - 1); +      else +        val.~T(); +    } + +    constexpr const T &get(select<0>) { return val; } +    template<unsigned N> constexpr const decltype(static_cast<const rest_t&>(rest).get(select<N-1>{})) get(select<N>) { +      return rest.get(select<N-1>{}); +    } +  }; +} + +template<typename T> +struct a { +  T value; +  template<typename...U> +  constexpr a(U &&...u) : value{forward<U>(u)...} {} +}; +template<typename T> using an = a<T>; + +template<typename T, typename U> T throw_(const U &u) { throw u; } + +template<typename...T> +class either { +  unsigned elem; +  detail::either_impl<T...> impl; +  typedef decltype(impl) impl_t; + +public: +  template<typename U> +  constexpr either(a<U> &&t) : +    elem(impl_t::index(detail::type<U>())), +    impl(detail::select<impl_t::index(detail::type<U>())>(), move(t.value)) {} + +  // Destruction disabled to allow use in a constant expression. +  // FIXME: declare a destructor iff any element has a nontrivial destructor +  //~either() { impl.destroy(elem); } + +  constexpr unsigned index() noexcept { return elem; } + +  template<unsigned N> using const_get_result = +    decltype(static_cast<const impl_t&>(impl).get(detail::select<N>{})); + +  template<unsigned N> +  constexpr const_get_result<N> get() { +    // Can't just use throw here, since that makes the conditional a prvalue, +    // which means we return a reference to a temporary. +    return (elem != N ? throw_<const_get_result<N>>("bad_either_get") +                      : impl.get(detail::select<N>{})); +  } + +  template<typename U> +  constexpr const U &get() { +    return get<impl_t::index(detail::type<U>())>(); +  } +}; + +typedef either<int, char, double> icd; +constexpr icd icd1 = an<int>(4); +constexpr icd icd2 = a<char>('x'); +constexpr icd icd3 = a<double>(6.5); + +static_assert(icd1.get<int>() == 4, ""); +static_assert(icd2.get<char>() == 'x', ""); +static_assert(icd3.get<double>() == 6.5, ""); + +struct non_triv { +  constexpr non_triv() : n(5) {} +  int n; +}; +constexpr either<const icd*, non_triv> icd4 = a<const icd*>(&icd2); +constexpr either<const icd*, non_triv> icd5 = a<non_triv>(); + +static_assert(icd4.get<const icd*>()->get<char>() == 'x', ""); +static_assert(icd5.get<non_triv>().n == 5, ""); diff --git a/clang/test/SemaCXX/do-while-scope.cpp b/clang/test/SemaCXX/do-while-scope.cpp new file mode 100644 index 0000000..2602ae1 --- /dev/null +++ b/clang/test/SemaCXX/do-while-scope.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +void test() { +  int x; +  do +    int x; +  while (1); +} diff --git a/clang/test/SemaCXX/dr1301.cpp b/clang/test/SemaCXX/dr1301.cpp new file mode 100644 index 0000000..ec0db74 --- /dev/null +++ b/clang/test/SemaCXX/dr1301.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s +struct A { // expected-note 2{{candidate}} +  A(int); // expected-note {{candidate}} +  int n; +}; +int a = A().n; // expected-error {{no matching constructor}} + +struct B { +  B() = delete; // expected-note 3{{here}} +  int n; +}; +int b = B().n; // expected-error {{call to deleted}} + +struct C { +  B b; // expected-note {{deleted default constructor}} +}; +int c = C().b.n; // expected-error {{call to implicitly-deleted default}} + +struct D { +  D() = default; // expected-note {{here}} +  B b; // expected-note {{'b' has a deleted default constructor}} +}; +int d = D().b.n; // expected-error {{call to implicitly-deleted default}} + +struct E { +  E() = default; +  int n; +}; +int e = E().n; // ok + +struct F { +  F(); +  int n; +}; +int f = F().n; // ok + +union G { +  F f; // expected-note {{non-trivial default constructor}} +}; +int g = G().f.n; // expected-error {{call to implicitly-deleted default}} + +struct H { +  int n; +private: +  H(); // expected-note {{here}} +}; +int h = H().n; // expected-error {{private constructor}} + +struct I { +  H h; // expected-note {{inaccessible default constructor}} +}; +int i = I().h.n; // expected-error {{call to implicitly-deleted default}} + +struct J { +  J(); +  virtual int f(); +  int n; +}; +int j1 = J().n; // ok +int j2 = J().f(); // ok + +union K { +  J j; // expected-note 2{{non-trivial default constructor}} +  int m; +}; +int k1 = K().j.n; // expected-error {{call to implicitly-deleted default}} +int k2 = K().j.f(); // expected-error {{call to implicitly-deleted default}} diff --git a/clang/test/SemaCXX/dynamic-cast.cpp b/clang/test/SemaCXX/dynamic-cast.cpp new file mode 100644 index 0000000..b73e8c5 --- /dev/null +++ b/clang/test/SemaCXX/dynamic-cast.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A {}; +struct B : A {}; +struct C : B {}; + +struct D : private A {}; +struct E : A {}; +struct F : B, E {}; + +struct Incomplete; // expected-note 2 {{forward declaration of 'Incomplete'}} + +struct Poly +{ +  virtual void f(); +}; + +struct PolyDerived : Poly +{ +}; + +void basic_bad() +{ +  // ptr -> nonptr +  (void)dynamic_cast<A>((A*)0); // expected-error {{'A' is not a reference or pointer}} +  // nonptr -> ptr +  (void)dynamic_cast<A*>(0); // expected-error {{'int' is not a pointer}} +  // ptr -> noncls +  (void)dynamic_cast<int*>((A*)0); // expected-error {{'int' is not a class}} +  // noncls -> ptr +  (void)dynamic_cast<A*>((int*)0); // expected-error {{'int' is not a class}} +  // ref -> noncls +  (void)dynamic_cast<int&>(*((A*)0)); // expected-error {{'int' is not a class}} +  // noncls -> ref +  (void)dynamic_cast<A&>(*((int*)0)); // expected-error {{'int' is not a class}} +  // ptr -> incomplete +  (void)dynamic_cast<Incomplete*>((A*)0); // expected-error {{'Incomplete' is an incomplete type}} +  // incomplete -> ptr +  (void)dynamic_cast<A*>((Incomplete*)0); // expected-error {{'Incomplete' is an incomplete type}} +} + +void same() +{ +  (void)dynamic_cast<A*>((A*)0); +  (void)dynamic_cast<A&>(*((A*)0)); +} + +void up() +{ +  (void)dynamic_cast<A*>((B*)0); +  (void)dynamic_cast<A&>(*((B*)0)); +  (void)dynamic_cast<A*>((C*)0); +  (void)dynamic_cast<A&>(*((C*)0)); + +  // Inaccessible +  //(void)dynamic_cast<A*>((D*)0); +  //(void)dynamic_cast<A&>(*((D*)0)); + +  // Ambiguous +  (void)dynamic_cast<A*>((F*)0); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A':\n    struct F -> struct B -> struct A\n    struct F -> struct E -> struct A}} +  (void)dynamic_cast<A&>(*((F*)0)); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A':\n    struct F -> struct B -> struct A\n    struct F -> struct E -> struct A}} +} + +void poly() +{ +  (void)dynamic_cast<A*>((Poly*)0); +  (void)dynamic_cast<A&>(*((Poly*)0)); +  (void)dynamic_cast<A*>((PolyDerived*)0); +  (void)dynamic_cast<A&>(*((PolyDerived*)0)); + +  // Not polymorphic source +  (void)dynamic_cast<Poly*>((A*)0); // expected-error {{'A' is not polymorphic}} +  (void)dynamic_cast<PolyDerived&>(*((A*)0)); // expected-error {{'A' is not polymorphic}} +} diff --git a/clang/test/SemaCXX/elaborated-type-specifier.cpp b/clang/test/SemaCXX/elaborated-type-specifier.cpp new file mode 100644 index 0000000..760079f --- /dev/null +++ b/clang/test/SemaCXX/elaborated-type-specifier.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test the use of elaborated-type-specifiers to inject the names of +// structs (or classes or unions) into an outer scope as described in +// C++ [basic.scope.pdecl]p5. +typedef struct S1 { +  union { +    struct S2 *x; +    struct S3 *y; +  }; +} S1; + +bool test_elab(S1 *s1, struct S2 *s2, struct S3 *s3) { +  if (s1->x == s2) return true; +  if (s1->y == s3) return true; +  return false; +} + +namespace NS { +  class X { +  public: +    void test_elab2(struct S4 *s4); +  }; + +  void X::test_elab2(S4 *s4) { } // expected-note{{passing argument to parameter 's4' here}} +} + +void test_X_elab(NS::X x) { +  struct S4 *s4 = 0; +  x.test_elab2(s4); // expected-error{{cannot initialize a parameter of type 'NS::S4 *' with an lvalue of type 'struct S4 *'}} +} + +namespace NS { +  S4 *get_S4(); +} + +void test_S5_scope() { +  S4 *s4; // expected-error{{use of undeclared identifier 'S4'}} \ +  // expected-error{{use of undeclared identifier 's4'}} +} + +int test_funcparam_scope(struct S5 * s5) { +  struct S5 { int y; } *s5_2 = 0; +  if (s5 == s5_2) return 1; // expected-error {{comparison of distinct pointer types ('struct S5 *' and 'struct S5 *')}} +  return 0; +} + + diff --git a/clang/test/SemaCXX/empty-class-layout.cpp b/clang/test/SemaCXX/empty-class-layout.cpp new file mode 100644 index 0000000..c68f2bb --- /dev/null +++ b/clang/test/SemaCXX/empty-class-layout.cpp @@ -0,0 +1,157 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify  + +#define SA(n, p) int a##n[(p) ? 1 : -1] + +namespace Test0 { + +struct A { int a; }; +SA(0, sizeof(A) == 4); + +struct B { }; +SA(1, sizeof(B) == 1); + +struct C : A, B { }; +SA(2, sizeof(C) == 4); + +struct D { }; +struct E : D { }; +struct F : E { }; + +struct G : E, F { }; +SA(3, sizeof(G) == 2); + +struct Empty { Empty(); }; + +struct I : Empty {  +  Empty e; +}; +SA(4, sizeof(I) == 2); + +struct J : Empty {  +  Empty e[2]; +}; +SA(5, sizeof(J) == 3); + +template<int N> struct Derived : Empty, Derived<N - 1> {  +}; +template<> struct Derived<0> : Empty { }; + +struct S1 : virtual Derived<10> {  +  Empty e; +}; +SA(6, sizeof(S1) == 24); + +struct S2 : virtual Derived<10> {  +  Empty e[2]; +}; +SA(7, sizeof(S2) == 24); + +struct S3 { +  Empty e; +}; + +struct S4 : Empty, S3 {  +}; +SA(8, sizeof(S4) == 2); + +struct S5 : S3, Empty {}; +SA(9, sizeof(S5) == 2); + +struct S6 : S5 { }; +SA(10, sizeof(S6) == 2); + +struct S7 : Empty { +  void *v; +}; +SA(11, sizeof(S7) == 8); + +struct S8 : Empty, A { +}; +SA(12, sizeof(S8) == 4); + +} + +namespace Test1 { + +// Test that we don't try to place both A subobjects at offset 0. +struct A { }; +class B { virtual void f(); }; +class C : A, virtual B { }; +struct D : virtual C { }; +struct E : virtual A { }; +class F : D, E { }; + +SA(0, sizeof(F) == 24); + +} + +namespace Test2 { + +// Test that B::a isn't laid out at offset 0. +struct Empty { }; +struct A : Empty { }; +struct B : Empty { +  A a; +}; + +SA(0, sizeof(B) == 2); + +} + +namespace Test3 { + +// Test that B::a isn't laid out at offset 0. +struct Empty { }; +struct A { Empty e; }; +struct B : Empty { A a; }; +SA(0, sizeof(B) == 2); + +} + +namespace Test4 { + +// Test that C::Empty isn't laid out at offset 0. +struct Empty { }; +struct A : Empty { }; +struct B { A a; }; +struct C : B, Empty { }; +SA(0, sizeof(C) == 2); + +} + +namespace Test5 { + +// Test that B::Empty isn't laid out at offset 0. +struct Empty { }; +struct Field : virtual Empty { }; +struct A { +  Field f; +}; +struct B : A, Empty { }; +SA(0, sizeof(B) == 16); + +} + +namespace Test6 { + +// Test that B::A isn't laid out at offset 0. +struct Empty { }; +struct Field : virtual Empty { }; +struct A { +  Field f; +}; +struct B : Empty, A { }; +SA(0, sizeof(B) == 16); + +} + +namespace Test7 { +  // Make sure we reserve enough space for both bases; PR11745. +  struct Empty { }; +  struct Base1 : Empty { }; +  struct Base2 : Empty { }; +  struct Test : Base1, Base2 { +    char c; +  }; +  SA(0, sizeof(Test) == 2); +} diff --git a/clang/test/SemaCXX/enum-bitfield.cpp b/clang/test/SemaCXX/enum-bitfield.cpp new file mode 100644 index 0000000..63445ca --- /dev/null +++ b/clang/test/SemaCXX/enum-bitfield.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s + +enum E {}; + +struct Z {}; +typedef int Integer; + +struct X { +  enum E : 1; +  enum E : Z; // expected-error{{invalid underlying type}} +  enum E2 : int; +  enum E3 : Integer; +}; + +struct Y { +  enum E : int(2); +  enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}} +}; diff --git a/clang/test/SemaCXX/enum-scoped.cpp b/clang/test/SemaCXX/enum-scoped.cpp new file mode 100644 index 0000000..ebe9245 --- /dev/null +++ b/clang/test/SemaCXX/enum-scoped.cpp @@ -0,0 +1,247 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s + +enum class E1 { +  Val1 = 1L +}; + +enum struct E2 { +  Val1 = '\0' +}; + +E1 v1 = Val1; // expected-error{{undeclared identifier}} +E1 v2 = E1::Val1; + +static_assert(sizeof(E1) == sizeof(int), "bad size"); +static_assert(sizeof(E1::Val1) == sizeof(int), "bad size"); +static_assert(sizeof(E2) == sizeof(int), "bad size"); +static_assert(sizeof(E2::Val1) == sizeof(int), "bad size"); + +E1 v3 = E2::Val1; // expected-error{{cannot initialize a variable}} +int x1 = E1::Val1; // expected-error{{cannot initialize a variable}} + +enum E3 : char { +  Val2 = 1 +}; + +E3 v4 = Val2; +E1 v5 = Val2; // expected-error{{cannot initialize a variable}} + +static_assert(sizeof(E3) == 1, "bad size"); + +int x2 = Val2; + +int a1[Val2]; +int a2[E1::Val1]; // expected-error{{size of array has non-integer type}} + +int* p1 = new int[Val2]; +int* p2 = new int[E1::Val1]; // expected-error{{array size expression must have integral or unscoped enumeration type, not 'E1'}} + +enum class E4 { +  e1 = -2147483648, // ok +  e2 = 2147483647, // ok +  e3 = 2147483648 // expected-error{{enumerator value evaluates to 2147483648, which cannot be narrowed to type 'int'}} +}; + +enum class E5 { +  e1 = 2147483647, // ok +  e2 // expected-error{{2147483648 is not representable in the underlying}} +}; + +enum class E6 : bool { +    e1 = false, e2 = true, +    e3 // expected-error{{2 is not representable in the underlying}} +}; + +enum E7 : bool { +    e1 = false, e2 = true, +    e3 // expected-error{{2 is not representable in the underlying}} +}; + +template <class T> +struct X { +  enum E : T { +    e1, e2, +    e3 // expected-error{{2 is not representable in the underlying}} +  }; +}; + +X<bool> X2; // expected-note{{in instantiation of template}} + +enum Incomplete1; // expected-error{{C++ forbids forward references}} + +enum Complete1 : int; +Complete1 complete1; + +enum class Complete2; +Complete2 complete2; + +// All the redeclarations below are done twice on purpose. Tests that the type +// of the declaration isn't changed. + +enum class Redeclare2; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum Redeclare2; // expected-error{{previously declared as scoped}} +enum Redeclare2; // expected-error{{previously declared as scoped}} + +enum Redeclare3 : int; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum Redeclare3; // expected-error{{previously declared with fixed underlying type}} +enum Redeclare3; // expected-error{{previously declared with fixed underlying type}} + +enum class Redeclare5; +enum class Redeclare5 : int; // ok + +enum Redeclare6 : int; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum Redeclare6 : short; // expected-error{{redeclared with different underlying type}} +enum Redeclare6 : short; // expected-error{{redeclared with different underlying type}} + +enum class Redeclare7; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum class Redeclare7 : short; // expected-error{{redeclared with different underlying type}} +enum class Redeclare7 : short; // expected-error{{redeclared with different underlying type}} + +enum : long { +  long_enum_val = 10000 +}; + +enum : long x; // expected-error{{unnamed enumeration must be a definition}} \ +// expected-warning{{declaration does not declare anything}} + +void PR9333() { +  enum class scoped_enum { yes, no, maybe }; +  scoped_enum e = scoped_enum::yes; +  if (e == scoped_enum::no) { } +} + +// <rdar://problem/9366066> +namespace rdar9366066 { +  enum class X : unsigned { value }; + +  void f(X x) { +    x % X::value; // expected-error{{invalid operands to binary expression ('rdar9366066::X' and 'rdar9366066::X')}} +    x % 8; // expected-error{{invalid operands to binary expression ('rdar9366066::X' and 'int')}} +  } +} + +// Part 1 of PR10264 +namespace test5 { +  namespace ns { +    typedef unsigned Atype; +    enum A : Atype; +  } +  enum ns::A : ns::Atype { +    x, y, z +  }; +} + +// Part 2 of PR10264 +namespace test6 { +  enum A : unsigned; +  struct A::a; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} +  enum A::b; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} +  int A::c; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} +  void A::d(); // expected-error {{incomplete type 'test6::A' named in nested name specifier}} +  void test() { +    (void) A::e; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} +  } +} + +namespace PR11484 { +  const int val = 104; +  enum class test1 { owner_dead = val, }; +} + +namespace N2764 { +  enum class E { a, b }; +  enum E x1 = E::a; // ok +  enum class E x2 = E::a; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}} + +  enum F { a, b }; +  enum F y1 = a; // ok +  enum class F y2 = a; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}} + +  struct S { +    friend enum class E; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}} +    friend enum class F; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}} + +    friend enum G {}; // expected-error {{forward reference}} expected-error {{cannot define a type in a friend declaration}} +    friend enum class H {}; // expected-error {{cannot define a type in a friend declaration}} + +    enum A : int; +    A a; +  } s; + +  enum S::A : int {}; + +  enum class B; +} + +enum class N2764::B {}; + +namespace PR12106 { +  template<typename E> struct Enum { +    Enum() : m_e(E::Last) {} +    E m_e; +  }; + +  enum eCOLORS { Last }; +  Enum<eCOLORS> e; +} + +namespace test7 { +  enum class E { e = (struct S*)0 == (struct S*)0 }; +  S *p; +} + +namespace test8 { +  template<typename T> struct S { +    enum A : int; // expected-note {{here}} +    enum class B; // expected-note {{here}} +    enum class C : int; // expected-note {{here}} +    enum class D : int; // expected-note {{here}} +  }; +  template<typename T> enum S<T>::A { a }; // expected-error {{previously declared with fixed underlying type}} +  template<typename T> enum class S<T>::B : char { b }; // expected-error {{redeclared with different underlying}} +  template<typename T> enum S<T>::C : int { c }; // expected-error {{previously declared as scoped}} +  template<typename T> enum class S<T>::D : char { d }; // expected-error {{redeclared with different underlying}} +} + +namespace test9 { +  template<typename T> struct S { +    enum class ET : T; // expected-note 2{{here}} +    enum class Eint : int; // expected-note 2{{here}} +  }; +  template<> enum class S<int>::ET : int {}; +  template<> enum class S<char>::ET : short {}; // expected-error {{different underlying type}} +  template<> enum class S<int>::Eint : short {}; // expected-error {{different underlying type}} +  template<> enum class S<char>::Eint : int {}; + +  template<typename T> enum class S<T>::ET : int {}; // expected-error {{different underlying type 'int' (was 'short')}} +  template<typename T> enum class S<T>::Eint : T {}; // expected-error {{different underlying type 'short' (was 'int')}} + +  // The implicit instantiation of S<short> causes the implicit instantiation of +  // all declarations of member enumerations, so is ill-formed, even though we +  // never instantiate the definitions of S<short>::ET nor S<short>::Eint. +  S<short> s; // expected-note {{in instantiation of}} +} + +namespace test10 { +  template<typename T> int f() { +    enum E : int; +    enum E : T; // expected-note {{here}} +    E x; +    enum E : int { e }; // expected-error {{different underlying}} +    x = e; +    return x; +  } +  int k = f<int>(); +  int l = f<short>(); // expected-note {{here}} + +  template<typename T> int g() { +    enum class E : int; +    enum class E : T; // expected-note {{here}} +    E x; +    enum class E : int { e }; // expected-error {{different underlying}} +    x = E::e; +    return (int)x; +  } +  int m = g<int>(); +  int n = g<short>(); // expected-note {{here}} +} diff --git a/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp b/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp new file mode 100644 index 0000000..d49800c --- /dev/null +++ b/clang/test/SemaCXX/enum-unscoped-nonexistent.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +struct Base { +  static const int a = 1; +}; +template<typename T> struct S : Base { +  enum E : int; +  constexpr int f(); +  constexpr int g(); // expected-note {{declared here}} +  void h(); +}; +template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}} +template<> enum S<short>::E : int { b = 2 }; +template<> enum S<int>::E : int { a = 4 }; +template<typename T> enum S<T>::E : int { b = 8 }; + +// The unqualified-id here names a member of the non-dependent base class Base +// and not the injected enumerator name 'a' from the specialization. +template<typename T> constexpr int S<T>::f() { return a; } +static_assert(S<char>().f() == 1, ""); +static_assert(S<int>().f() == 1, ""); + +// The unqualified-id here names a member of the current instantiation, which +// bizarrely might not exist in some instantiations. +template<typename T> constexpr int S<T>::g() { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}} +static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} expected-note {{undefined}} +static_assert(S<short>().g() == 2, ""); +static_assert(S<long>().g() == 8, ""); + +// 'b' is type-dependent, so these assertions should not fire before 'h' is +// instantiated. +template<typename T> void S<T>::h() { +  char c[S<T>::b]; +  static_assert(b != 8, ""); +  static_assert(sizeof(c) != 8, ""); +} +void f() { +  S<short>().h(); // ok, b == 2 +} diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp new file mode 100644 index 0000000..370e1c3 --- /dev/null +++ b/clang/test/SemaCXX/enum.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++98 -verify -triple x86_64-apple-darwin %s +enum E { // expected-note{{previous definition is here}} +  Val1, +  Val2 +}; + +enum E; // expected-warning{{redeclaration of already-defined enum 'E' is a GNU extension}} + +int& enumerator_type(int); +float& enumerator_type(E); + +void f() { +  E e = Val1; +  float& fr = enumerator_type(Val2); +} + +// <rdar://problem/6502934> +typedef enum Foo { +  A = 0, +  B = 1 +} Foo; + +void bar() { +  Foo myvar = A; +  myvar = B; +} + +/// PR3688 +struct s1 { +  enum e1 (*bar)(void); // expected-error{{ISO C++ forbids forward references to 'enum' types}} +}; + +enum e1 { YES, NO }; + +static enum e1 badfunc(struct s1 *q) { +  return q->bar(); +} + +enum e2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} + +namespace test1 { +  template <class A, class B> struct is_same { static const int value = -1; }; +  template <class A> struct is_same<A,A> { static const int value = 1; }; + +  enum enum0 { v0 }; +  int test0[is_same<__typeof(+v0), int>::value]; + +  enum enum1 { v1 = __INT_MAX__ }; +  int test1[is_same<__typeof(+v1), int>::value]; + +  enum enum2 { v2 = __INT_MAX__ * 2U }; +  int test2[is_same<__typeof(+v2), unsigned int>::value]; + +  enum enum3 { v3 = __LONG_MAX__ }; +  int test3[is_same<__typeof(+v3), long>::value]; + +  enum enum4 { v4 = __LONG_MAX__ * 2UL }; +  int test4[is_same<__typeof(+v4), unsigned long>::value]; +} + +// PR6061 +namespace PR6061 { +  struct A { enum { id }; }; +  struct B { enum { id }; }; +   +  struct C : public A, public B +  {  +    enum { id };  +  }; +} + +namespace Conditional { +  enum a { A }; a x(const enum a x) { return 1?x:A; } +} + +namespace PR7051 { +  enum E { e0 }; +  void f() { +    E e; +    e = 1; // expected-error{{assigning to 'PR7051::E' from incompatible type 'int'}} +    e |= 1; // expected-error{{assigning to 'PR7051::E' from incompatible type 'int'}} +  } +} + +// PR7466 +enum { }; // expected-warning{{declaration does not declare anything}} +typedef enum { }; // expected-warning{{typedef requires a name}} + +// PR7921 +enum PR7921E { +    PR7921V = (PR7921E)(123) // expected-error {{expression is not an integral constant expression}} +}; + +void PR8089() { +  enum E; // expected-error{{ISO C++ forbids forward references to 'enum' types}} +  int a = (E)3; // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'E'}} +} diff --git a/clang/test/SemaCXX/exception-spec-no-exceptions.cpp b/clang/test/SemaCXX/exception-spec-no-exceptions.cpp new file mode 100644 index 0000000..2e18070 --- /dev/null +++ b/clang/test/SemaCXX/exception-spec-no-exceptions.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions -fobjc-exceptions %s + +// Note that we're specifically excluding -fcxx-exceptions in the command line above. + +// That this should work even with -fobjc-exceptions is PR9358 + +// PR7243: redeclarations +namespace test0 { +  void foo() throw(int); +  void foo() throw(); +} + +// Overrides. +namespace test1 { +  struct A { +    virtual void foo() throw(); +  }; + +  struct B : A { +    virtual void foo() throw(int); +  }; +} + +// Calls from less permissive contexts.  We don't actually do this +// check, but if we did it should also be disabled under +// -fno-exceptions. +namespace test2 { +  void foo() throw(int); +  void bar() throw() { +    foo(); +  } +} + diff --git a/clang/test/SemaCXX/exceptions.cpp b/clang/test/SemaCXX/exceptions.cpp new file mode 100644 index 0000000..486d88e --- /dev/null +++ b/clang/test/SemaCXX/exceptions.cpp @@ -0,0 +1,122 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s + +struct A; // expected-note 4 {{forward declaration of 'A'}} + +struct Abstract { virtual void f() = 0; }; // expected-note {{unimplemented pure virtual method 'f'}} + +void trys() { +  try { +  } catch(int i) { // expected-note {{previous definition}} +    int j = i; +    int i; // expected-error {{redefinition of 'i'}} +  } catch(float i) { +  } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}} +  } catch(A a) { // expected-error {{cannot catch incomplete type 'A'}} +  } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'A'}} +  } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'A'}} +  } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}} +  } catch(...) { +    int j = i; // expected-error {{use of undeclared identifier 'i'}} +  } + +  try { +  } catch(...) { // expected-error {{catch-all handler must come last}} +  } catch(int) { +  } +} + +void throws() { +  throw; +  throw 0; +  throw throw; // expected-error {{cannot throw object of incomplete type 'void'}} +  throw (A*)0; // expected-error {{cannot throw pointer to object of incomplete type 'A'}} +} + +void jumps() { +l1: +  goto l5; +  goto l4; // expected-error {{goto into protected scope}} +  goto l3; // expected-error {{goto into protected scope}} +  goto l2; // expected-error {{goto into protected scope}} +  goto l1; +  try { // expected-note 4 {{jump bypasses initialization of try block}} +  l2: +    goto l5; +    goto l4; // expected-error {{goto into protected scope}} +    goto l3; // expected-error {{goto into protected scope}} +    goto l2; +    goto l1; +  } catch(int) { // expected-note 4 {{jump bypasses initialization of catch block}} +  l3: +    goto l5; +    goto l4; // expected-error {{goto into protected scope}} +    goto l3; +    goto l2; // expected-error {{goto into protected scope}} +    goto l1; +  } catch(...) { // expected-note 4 {{jump bypasses initialization of catch block}} +  l4: +    goto l5; +    goto l4; +    goto l3; // expected-error {{goto into protected scope}} +    goto l2; // expected-error {{goto into protected scope}} +    goto l1; +  } +l5: +  goto l5; +  goto l4; // expected-error {{goto into protected scope}} +  goto l3; // expected-error {{goto into protected scope}} +  goto l2; // expected-error {{goto into protected scope}} +  goto l1; +} + +struct BadReturn { +  BadReturn() try { +  } catch(...) { +    // Try to hide +    try { +    } catch(...) { +      { +        if (0) +          return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} +      } +    } +  } +  BadReturn(int); +}; + +BadReturn::BadReturn(int) try { +} catch(...) { +  // Try to hide +  try { +  } catch(int) { +    return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} +  } catch(...) { +    { +      if (0) +        return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} +    } +  } +} + +// Cannot throw an abstract type. +class foo { +public: +  foo() {} +  void bar () { +    throw *this; // expected-error{{cannot throw an object of abstract type 'foo'}} +  } +  virtual void test () = 0; // expected-note{{unimplemented pure virtual method 'test'}} +}; + +namespace PR6831 { +  namespace NA { struct S; } +  namespace NB { struct S; } +   +  void f() { +    using namespace NA; +    using namespace NB; +    try { +    } catch (int S) {  +    } +  } +} diff --git a/clang/test/SemaCXX/explicit.cpp b/clang/test/SemaCXX/explicit.cpp new file mode 100644 index 0000000..4774637 --- /dev/null +++ b/clang/test/SemaCXX/explicit.cpp @@ -0,0 +1,175 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +namespace Constructor { +struct A { +  A(int); +}; + +struct B { +  explicit B(int); +}; + +B::B(int) { } + +struct C { +  void f(const A&); +  void f(const B&); +}; + +void f(C c) { +  c.f(10); +} +} + +namespace Conversion { +  struct A { +    operator int(); +    explicit operator bool(); +  }; + +  A::operator bool() { return false; }  + +  struct B { +    void f(int); +    void f(bool); +  }; + +  void f(A a, B b) { +    b.f(a); +  } +   +  void testExplicit() +  { +    // Taken from 12.3.2p2 +    class Y { }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \ +					          expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \ +                    expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \ +          expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} + +    struct Z { +      explicit operator Y() const; +      explicit operator int() const; +    }; +     +    Z z; +    // 13.3.1.4p1 & 8.5p16: +    Y y2 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'Conversion::Y'}} +    Y y3 = (Y)z; +    Y y4 = Y(z); +    Y y5 = static_cast<Y>(z); +    // 13.3.1.5p1 & 8.5p16: +    int i1 = (int)z; +    int i2 = int(z); +    int i3 = static_cast<int>(z); +    int i4(z); +    // 13.3.1.6p1 & 8.5.3p5: +    const Y& y6 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'const Conversion::Y'}} +    const int& y7(z); +  } +   +  void testBool() { +    struct Bool { +      operator bool(); +    }; + +    struct NotBool { +      explicit operator bool(); // expected-note {{conversion to integral type 'bool'}} +    }; +    Bool    b; +    NotBool n; + +    (void) (1 + b); +    (void) (1 + n); // expected-error {{invalid operands to binary expression ('int' and 'Conversion::NotBool')}} +     +    // 5.3.1p9: +    (void) (!b); +    (void) (!n); +     +    // 5.14p1: +    (void) (b && true); +    (void) (n && true); +     +    // 5.15p1: +    (void) (b || true); +    (void) (n || true); +     +    // 5.16p1: +    (void) (b ? 0 : 1); +    (void) (n ? 0: 1); +     +    // 5.19p5: +    // TODO: After constexpr has been implemented +     +    // 6.4p4: +    if (b) {} +    if (n) {} +     +    // 6.4.2p2: +    switch (b) {} // expected-warning {{switch condition has boolean value}} +    switch (n) {} // expected-error {{switch condition type 'Conversion::NotBool' requires explicit conversion to 'bool'}} \ +                     expected-warning {{switch condition has boolean value}} +     +    // 6.5.1: +    while (b) {} +    while (n) {} +     +    // 6.5.2p1: +    do {} while (b); +    do {} while (n); +     +    // 6.5.3: +    for (;b;) {} +    for (;n;) {} +  } +   +  void testNew() +  { +    // 5.3.4p6: +    struct Int { +      operator int(); +    }; +    struct NotInt { +      explicit operator int(); // expected-note {{conversion to integral type 'int' declared here}} +    }; +     +    Int    i; +    NotInt ni; +     +    new int[i]; +    new int[ni]; // expected-error {{array size expression of type 'Conversion::NotInt' requires explicit conversion to type 'int'}} +  } +   +  void testDelete() +  { +    // 5.3.5pp2: +    struct Ptr { +      operator int*(); +    }; +    struct NotPtr { +      explicit operator int*(); +    }; +     +    Ptr    p; +    NotPtr np; +     +    delete p; +    delete np; // expected-error {{cannot delete expression of type 'Conversion::NotPtr'}} +  } +   +  void testFunctionPointer() +  { +    // 13.3.1.1.2p2: +    using Func = void(*)(int); +     +    struct FP { +      operator Func(); +    }; +    struct NotFP { +      explicit operator Func(); +    }; +     +    FP    fp; +    NotFP nfp; +    fp(1); +    nfp(1); // expected-error {{type 'Conversion::NotFP' does not provide a call operator}} +  } +} diff --git a/clang/test/SemaCXX/expression-traits.cpp b/clang/test/SemaCXX/expression-traits.cpp new file mode 100644 index 0000000..2767d4a --- /dev/null +++ b/clang/test/SemaCXX/expression-traits.cpp @@ -0,0 +1,620 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions %s + +// +// Tests for "expression traits" intrinsics such as __is_lvalue_expr. +// +// For the time being, these tests are written against the 2003 C++ +// standard (ISO/IEC 14882:2003 -- see draft at +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2001/n1316/). +// +// C++0x has its own, more-refined, idea of lvalues and rvalues. +// If/when we need to support those, we'll need to track both +// standard documents. + +#if !__has_feature(cxx_static_assert) +# define CONCAT_(X_, Y_) CONCAT1_(X_, Y_) +# define CONCAT1_(X_, Y_) X_ ## Y_ + +// This emulation can be used multiple times on one line (and thus in +// a macro), except at class scope +# define static_assert(b_, m_) \ +  typedef int CONCAT_(sa_, __LINE__)[b_ ? 1 : -1] +#endif + +// Tests are broken down according to section of the C++03 standard +// (ISO/IEC 14882:2003(E)) + +// Assertion macros encoding the following two paragraphs +// +// basic.lval/1 Every expression is either an lvalue or an rvalue. +// +// expr.prim/5 A parenthesized expression is a primary expression whose type +// and value are identical to those of the enclosed expression. The +// presence of parentheses does not affect whether the expression is +// an lvalue. +// +// Note: these asserts cannot be made at class scope in C++03.  Put +// them in a member function instead. +#define ASSERT_LVALUE(expr)                                             \ +    static_assert(__is_lvalue_expr(expr), "should be an lvalue");       \ +    static_assert(__is_lvalue_expr((expr)),                             \ +                  "the presence of parentheses should have"             \ +                  " no effect on lvalueness (expr.prim/5)");            \ +    static_assert(!__is_rvalue_expr(expr), "should be an lvalue");      \ +    static_assert(!__is_rvalue_expr((expr)),                            \ +                  "the presence of parentheses should have"             \ +                  " no effect on lvalueness (expr.prim/5)") + +#define ASSERT_RVALUE(expr);                                            \ +    static_assert(__is_rvalue_expr(expr), "should be an rvalue");       \ +    static_assert(__is_rvalue_expr((expr)),                             \ +                  "the presence of parentheses should have"             \ +                  " no effect on lvalueness (expr.prim/5)");            \ +    static_assert(!__is_lvalue_expr(expr), "should be an rvalue");      \ +    static_assert(!__is_lvalue_expr((expr)),                            \ +                  "the presence of parentheses should have"             \ +                  " no effect on lvalueness (expr.prim/5)") + +enum Enum { Enumerator }; + +int ReturnInt(); +void ReturnVoid(); +Enum ReturnEnum(); + +void basic_lval_5() +{ +    // basic.lval/5: The result of calling a function that does not return +    // a reference is an rvalue. +    ASSERT_RVALUE(ReturnInt()); +    ASSERT_RVALUE(ReturnVoid()); +    ASSERT_RVALUE(ReturnEnum()); +} + +int& ReturnIntReference(); +extern Enum& ReturnEnumReference(); + +void basic_lval_6() +{ +    // basic.lval/6: An expression which holds a temporary object resulting +    // from a cast to a nonreference type is an rvalue (this includes +    // the explicit creation of an object using functional notation +    struct IntClass +    { +        explicit IntClass(int = 0); +        IntClass(char const*); +        operator int() const; +    }; +     +    struct ConvertibleToIntClass +    { +        operator IntClass() const; +    }; + +    ConvertibleToIntClass b; + +    // Make sure even trivial conversions are not detected as lvalues +    int intLvalue = 0; +    ASSERT_RVALUE((int)intLvalue); +    ASSERT_RVALUE((short)intLvalue); +    ASSERT_RVALUE((long)intLvalue); +     +    // Same tests with function-call notation +    ASSERT_RVALUE(int(intLvalue)); +    ASSERT_RVALUE(short(intLvalue)); +    ASSERT_RVALUE(long(intLvalue)); + +    char charLValue = 'x'; +    ASSERT_RVALUE((signed char)charLValue); +    ASSERT_RVALUE((unsigned char)charLValue); + +    ASSERT_RVALUE(static_cast<int>(IntClass())); +    IntClass intClassLValue; +    ASSERT_RVALUE(static_cast<int>(intClassLValue));  +    ASSERT_RVALUE(static_cast<IntClass>(ConvertibleToIntClass())); +    ConvertibleToIntClass convertibleToIntClassLValue; +    ASSERT_RVALUE(static_cast<IntClass>(convertibleToIntClassLValue)); +     + +    typedef signed char signed_char; +    typedef unsigned char unsigned_char; +    ASSERT_RVALUE(signed_char(charLValue)); +    ASSERT_RVALUE(unsigned_char(charLValue)); + +    ASSERT_RVALUE(int(IntClass())); +    ASSERT_RVALUE(int(intClassLValue));  +    ASSERT_RVALUE(IntClass(ConvertibleToIntClass())); +    ASSERT_RVALUE(IntClass(convertibleToIntClassLValue)); +} + +void conv_ptr_1() +{ +    // conv.ptr/1: A null pointer constant is an integral constant +    // expression (5.19) rvalue of integer type that evaluates to +    // zero. +    ASSERT_RVALUE(0); +} + +void expr_6() +{ +    // expr/6: If an expression initially has the type "reference to T" +    // (8.3.2, 8.5.3), ... the expression is an lvalue. +    int x = 0; +    int& referenceToInt = x; +    ASSERT_LVALUE(referenceToInt); +    ASSERT_LVALUE(ReturnIntReference()); +} + +void expr_prim_2() +{ +    // 5.1/2 A string literal is an lvalue; all other +    // literals are rvalues. +    ASSERT_LVALUE("foo"); +    ASSERT_RVALUE(1); +    ASSERT_RVALUE(1.2); +    ASSERT_RVALUE(10UL); +} + +void expr_prim_3() +{ +    // 5.1/3: The keyword "this" names a pointer to the object for +    // which a nonstatic member function (9.3.2) is invoked. ...The +    // expression is an rvalue. +    struct ThisTest +    { +        void f() { ASSERT_RVALUE(this); } +    }; +} + +extern int variable; +void Function(); + +struct BaseClass +{ +    virtual ~BaseClass(); +     +    int BaseNonstaticMemberFunction(); +    static int BaseStaticMemberFunction(); +    int baseDataMember; +}; + +struct Class : BaseClass +{ +    static void function(); +    static int variable; + +    template <class T> +    struct NestedClassTemplate {}; + +    template <class T> +    static int& NestedFuncTemplate() { return variable; }  // expected-note{{possible target for call}} + +    template <class T> +    int& NestedMemfunTemplate() { return variable; } + +    int operator*() const; + +    template <class T> +    int operator+(T) const; + +    int NonstaticMemberFunction(); +    static int StaticMemberFunction(); +    int dataMember; + +    int& referenceDataMember; +    static int& staticReferenceDataMember; +    static int staticNonreferenceDataMember; + +    enum Enum { Enumerator }; + +    operator long() const; +     +    Class(); +    Class(int,int); + +    void expr_prim_4() +    { +        // 5.1/4: The operator :: followed by an identifier, a +        // qualified-id, or an operator-function-id is a primary- +        // expression. ...The result is an lvalue if the entity is +        // a function or variable. +        ASSERT_LVALUE(::Function);         // identifier: function +        ASSERT_LVALUE(::variable);         // identifier: variable + +        // the only qualified-id form that can start without "::" (and thus +        // be legal after "::" ) is +        // +        // ::<sub>opt</sub> nested-name-specifier template<sub>opt</sub> unqualified-id +        ASSERT_LVALUE(::Class::function);  // qualified-id: function +        ASSERT_LVALUE(::Class::variable);  // qualified-id: variable + +        // The standard doesn't give a clear answer about whether these +        // should really be lvalues or rvalues without some surrounding +        // context that forces them to be interpreted as naming a +        // particular function template specialization (that situation +        // doesn't come up in legal pure C++ programs). This language +        // extension simply rejects them as requiring additional context +        __is_lvalue_expr(::Class::NestedFuncTemplate);    // qualified-id: template \ +        // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +         +        __is_lvalue_expr(::Class::NestedMemfunTemplate);  // qualified-id: template \ +        // expected-error{{reference to non-static member function must be called}} +         +        __is_lvalue_expr(::Class::operator+);             // operator-function-id: template \ +        // expected-error{{reference to non-static member function must be called}} + +        //ASSERT_RVALUE(::Class::operator*);         // operator-function-id: member function +    } + +    void expr_prim_7() +    { +        // expr.prim/7 An identifier is an id-expression provided it has been +        // suitably declared (clause 7). [Note: ... ] The type of the +        // expression is the type of the identifier. The result is the +        // entity denoted by the identifier. The result is an lvalue if +        // the entity is a function, variable, or data member... (cont'd) +        ASSERT_LVALUE(Function);        // identifier: function +        ASSERT_LVALUE(StaticMemberFunction);        // identifier: function +        ASSERT_LVALUE(variable);        // identifier: variable +        ASSERT_LVALUE(dataMember);      // identifier: data member +        //ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function + +        // (cont'd)...A nested-name-specifier that names a class, +        // optionally followed by the keyword template (14.2), and then +        // followed by the name of a member of either that class (9.2) or +        // one of its base classes... is a qualified-id... The result is +        // the member. The type of the result is the type of the +        // member. The result is an lvalue if the member is a static +        // member function or a data member. +        ASSERT_LVALUE(Class::dataMember); +        ASSERT_LVALUE(Class::StaticMemberFunction); +        //ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function + +        ASSERT_LVALUE(Class::baseDataMember); +        ASSERT_LVALUE(Class::BaseStaticMemberFunction); +        //ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function +    } +}; + +void expr_call_10() +{ +    // expr.call/10: A function call is an lvalue if and only if the +    // result type is a reference.  This statement is partially +    // redundant with basic.lval/5 +    basic_lval_5(); +     +    ASSERT_LVALUE(ReturnIntReference()); +    ASSERT_LVALUE(ReturnEnumReference()); +} + +namespace Namespace +{ +  int x; +  void function(); +} + +void expr_prim_8() +{ +    // expr.prim/8 A nested-name-specifier that names a namespace +    // (7.3), followed by the name of a member of that namespace (or +    // the name of a member of a namespace made visible by a +    // using-directive ) is a qualified-id; 3.4.3.2 describes name +    // lookup for namespace members that appear in qualified-ids. The +    // result is the member. The type of the result is the type of the +    // member. The result is an lvalue if the member is a function or +    // a variable. +    ASSERT_LVALUE(Namespace::x); +    ASSERT_LVALUE(Namespace::function); +} + +void expr_sub_1(int* pointer) +{ +    // expr.sub/1 A postfix expression followed by an expression in +    // square brackets is a postfix expression. One of the expressions +    // shall have the type "pointer to T" and the other shall have +    // enumeration or integral type. The result is an lvalue of type +    // "T." +    ASSERT_LVALUE(pointer[1]); +     +    // The expression E1[E2] is identical (by definition) to *((E1)+(E2)). +    ASSERT_LVALUE(*(pointer+1)); +} + +void expr_type_conv_1() +{ +    // expr.type.conv/1 A simple-type-specifier (7.1.5) followed by a +    // parenthesized expression-list constructs a value of the specified +    // type given the expression list. ... If the expression list +    // specifies more than a single value, the type shall be a class with +    // a suitably declared constructor (8.5, 12.1), and the expression +    // T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, +    // x2, ...); for some invented temporary variable t, with the result +    // being the value of t as an rvalue. +    ASSERT_RVALUE(Class(2,2)); +} + +void expr_type_conv_2() +{ +    // expr.type.conv/2 The expression T(), where T is a +    // simple-type-specifier (7.1.5.2) for a non-array complete object +    // type or the (possibly cv-qualified) void type, creates an +    // rvalue of the specified type, +    ASSERT_RVALUE(int()); +    ASSERT_RVALUE(Class()); +    ASSERT_RVALUE(void()); +} + + +void expr_ref_4() +{ +    // Applies to expressions of the form E1.E2 +     +    // If E2 is declared to have type "reference to T", then E1.E2 is +    // an lvalue;.... Otherwise, one of the following rules applies. +    ASSERT_LVALUE(Class().staticReferenceDataMember); +    ASSERT_LVALUE(Class().referenceDataMember); +     +    // - If E2 is a static data member, and the type of E2 is T, then +    // E1.E2 is an lvalue; ... +    ASSERT_LVALUE(Class().staticNonreferenceDataMember); +    ASSERT_LVALUE(Class().staticReferenceDataMember); + + +    // - If E2 is a non-static data member, ... If E1 is an lvalue, +    // then E1.E2 is an lvalue... +    Class lvalue; +    ASSERT_LVALUE(lvalue.dataMember); +    ASSERT_RVALUE(Class().dataMember); + +    // - If E1.E2 refers to a static member function, ... then E1.E2 +    // is an lvalue +    ASSERT_LVALUE(Class().StaticMemberFunction); +     +    // - Otherwise, if E1.E2 refers to a non-static member function, +    // then E1.E2 is not an lvalue. +    //ASSERT_RVALUE(Class().NonstaticMemberFunction); + +    // - If E2 is a member enumerator, and the type of E2 is T, the +    // expression E1.E2 is not an lvalue. The type of E1.E2 is T. +    ASSERT_RVALUE(Class().Enumerator); +    ASSERT_RVALUE(lvalue.Enumerator); +} + + +void expr_post_incr_1(int x) +{ +    // expr.post.incr/1 The value obtained by applying a postfix ++ is +    // the value that the operand had before applying the +    // operator... The result is an rvalue. +    ASSERT_RVALUE(x++); +} + +void expr_dynamic_cast_2() +{ +    // expr.dynamic.cast/2: If T is a pointer type, v shall be an +    // rvalue of a pointer to complete class type, and the result is +    // an rvalue of type T. +    Class instance; +    ASSERT_RVALUE(dynamic_cast<Class*>(&instance)); + +    // If T is a reference type, v shall be an +    // lvalue of a complete class type, and the result is an lvalue of +    // the type referred to by T. +    ASSERT_LVALUE(dynamic_cast<Class&>(instance)); +} + +void expr_dynamic_cast_5() +{ +    // expr.dynamic.cast/5: If T is "reference to cv1 B" and v has type +    // "cv2 D" such that B is a base class of D, the result is an +    // lvalue for the unique B sub-object of the D object referred +    // to by v. +    typedef BaseClass B; +    typedef Class D; +    D object; +    ASSERT_LVALUE(dynamic_cast<B&>(object)); +} + +// expr.dynamic.cast/8: The run-time check logically executes as follows: +// +// - If, in the most derived object pointed (referred) to by v, v +// points (refers) to a public base class subobject of a T object, and +// if only one object of type T is derived from the sub-object pointed +// (referred) to by v, the result is a pointer (an lvalue referring) +// to that T object. +// +// - Otherwise, if v points (refers) to a public base class sub-object +// of the most derived object, and the type of the most derived object +// has a base class, of type T, that is unambiguous and public, the +// result is a pointer (an lvalue referring) to the T sub-object of +// the most derived object. +// +// The mention of "lvalue" in the text above appears to be a +// defect that is being corrected by the response to UK65 (see +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2841.html). + +#if 0 +void expr_typeid_1() +{ +    // expr.typeid/1: The result of a typeid expression is an lvalue... +    ASSERT_LVALUE(typeid(1)); +} +#endif + +void expr_static_cast_1(int x) +{ +    // expr.static.cast/1: The result of the expression +    // static_cast<T>(v) is the result of converting the expression v +    // to type T. If T is a reference type, the result is an lvalue; +    // otherwise, the result is an rvalue. +    ASSERT_LVALUE(static_cast<int&>(x)); +    ASSERT_RVALUE(static_cast<int>(x)); +} + +void expr_reinterpret_cast_1() +{ +    // expr.reinterpret.cast/1: The result of the expression +    // reinterpret_cast<T>(v) is the result of converting the +    // expression v to type T. If T is a reference type, the result is +    // an lvalue; otherwise, the result is an rvalue +    ASSERT_RVALUE(reinterpret_cast<int*>(0)); +    char const v = 0; +    ASSERT_LVALUE(reinterpret_cast<char const&>(v)); +} + +void expr_unary_op_1(int* pointer, struct incomplete* pointerToIncompleteType) +{ +    // expr.unary.op/1: The unary * operator performs indirection: the +    // expression to which it is applied shall be a pointer to an +    // object type, or a pointer to a function type and the result is +    // an lvalue referring to the object or function to which the +    // expression points.   +    ASSERT_LVALUE(*pointer); +    ASSERT_LVALUE(*Function); + +    // [Note: a pointer to an incomplete type +    // (other than cv void ) can be dereferenced. ] +    ASSERT_LVALUE(*pointerToIncompleteType); +} + +void expr_pre_incr_1(int operand) +{ +    // expr.pre.incr/1: The operand of prefix ++ ... shall be a +    // modifiable lvalue.... The value is the new value of the +    // operand; it is an lvalue. +    ASSERT_LVALUE(++operand); +} + +void expr_cast_1(int x) +{ +    // expr.cast/1: The result of the expression (T) cast-expression +    // is of type T. The result is an lvalue if T is a reference type, +    // otherwise the result is an rvalue. +    ASSERT_LVALUE((void(&)())expr_cast_1); +    ASSERT_LVALUE((int&)x); +    ASSERT_RVALUE((void(*)())expr_cast_1); +    ASSERT_RVALUE((int)x); +} + +void expr_mptr_oper() +{ +    // expr.mptr.oper/6: The result of a .* expression is an lvalue +    // only if its first operand is an lvalue and its second operand +    // is a pointer to data member... (cont'd) +    typedef Class MakeRValue; +    ASSERT_RVALUE(MakeRValue().*(&Class::dataMember)); +    //ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction)); +    Class lvalue; +    ASSERT_LVALUE(lvalue.*(&Class::dataMember)); +    //ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction)); +     +    // (cont'd)...The result of an ->* expression is an lvalue only +    // if its second operand is a pointer to data member. If the +    // second operand is the null pointer to member value (4.11), the +    // behavior is undefined. +    ASSERT_LVALUE((&lvalue)->*(&Class::dataMember)); +    //ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction)); +} + +void expr_cond(bool cond) +{ +    // 5.16 Conditional operator [expr.cond] +    // +    // 2 If either the second or the third operand has type (possibly +    // cv-qualified) void, then the lvalue-to-rvalue (4.1), +    // array-to-pointer (4.2), and function-to-pointer (4.3) standard +    // conversions are performed on the second and third operands, and one +    // of the following shall hold: +    // +    // - The second or the third operand (but not both) is a +    // throw-expression (15.1); the result is of the type of the other and +    // is an rvalue. + +    Class classLvalue; +    ASSERT_RVALUE(cond ? throw 1 : (void)0); +    ASSERT_RVALUE(cond ? (void)0 : throw 1); +    ASSERT_RVALUE(cond ? throw 1 : classLvalue); +    ASSERT_RVALUE(cond ? classLvalue : throw 1); + +    // - Both the second and the third operands have type void; the result +    // is of type void and is an rvalue. [Note: this includes the case +    // where both operands are throw-expressions. ] +    ASSERT_RVALUE(cond ? (void)1 : (void)0); +    ASSERT_RVALUE(cond ? throw 1 : throw 0); +     +    // expr.cond/4: If the second and third operands are lvalues and +    // have the same type, the result is of that type and is an +    // lvalue. +    ASSERT_LVALUE(cond ? classLvalue : classLvalue); +    int intLvalue = 0; +    ASSERT_LVALUE(cond ? intLvalue : intLvalue); +     +    // expr.cond/5:Otherwise, the result is an rvalue. +    typedef Class MakeRValue; +    ASSERT_RVALUE(cond ? MakeRValue() : classLvalue); +    ASSERT_RVALUE(cond ? classLvalue : MakeRValue()); +    ASSERT_RVALUE(cond ? MakeRValue() : MakeRValue()); +    ASSERT_RVALUE(cond ? classLvalue : intLvalue); +    ASSERT_RVALUE(cond ? intLvalue : int()); +} + +void expr_ass_1(int x) +{ +    // expr.ass/1: There are several assignment operators, all of +    // which group right-to-left. All require a modifiable lvalue as +    // their left operand, and the type of an assignment expression is +    // that of its left operand. The result of the assignment +    // operation is the value stored in the left operand after the +    // assignment has taken place; the result is an lvalue. +    ASSERT_LVALUE(x = 1); +    ASSERT_LVALUE(x += 1); +    ASSERT_LVALUE(x -= 1); +    ASSERT_LVALUE(x *= 1); +    ASSERT_LVALUE(x /= 1); +    ASSERT_LVALUE(x %= 1); +    ASSERT_LVALUE(x ^= 1); +    ASSERT_LVALUE(x &= 1); +    ASSERT_LVALUE(x |= 1); +} + +void expr_comma(int x) +{ +    // expr.comma: A pair of expressions separated by a comma is +    // evaluated left-to-right and the value of the left expression is +    // discarded... result is an lvalue if its right operand is. + +    // Can't use the ASSERT_XXXX macros without adding parens around +    // the comma expression. +    static_assert(__is_lvalue_expr(x,x), "expected an lvalue"); +    static_assert(__is_rvalue_expr(x,1), "expected an rvalue"); +    static_assert(__is_lvalue_expr(1,x), "expected an lvalue"); +    static_assert(__is_rvalue_expr(1,1), "expected an rvalue"); +} + +#if 0 +template<typename T> void f(); + +// FIXME These currently fail +void expr_fun_lvalue() +{ +  ASSERT_LVALUE(&f<int>); +} + +void expr_fun_rvalue() +{ +  ASSERT_RVALUE(f<int>); +} +#endif + +template <int NonTypeNonReferenceParameter, int& NonTypeReferenceParameter> +void check_temp_param_6() +{ +    ASSERT_RVALUE(NonTypeNonReferenceParameter); +    ASSERT_LVALUE(NonTypeReferenceParameter); +} + +int AnInt = 0; + +void temp_param_6() +{ +    check_temp_param_6<3,AnInt>(); +} diff --git a/clang/test/SemaCXX/expressions.cpp b/clang/test/SemaCXX/expressions.cpp new file mode 100644 index 0000000..355833e --- /dev/null +++ b/clang/test/SemaCXX/expressions.cpp @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +void choice(int); +int choice(bool); + +void test() { +  // Result of ! must be type bool. +  int i = choice(!1); +} + +// rdar://8018252 +void f0() { +  extern void f0_1(int*); +  register int x; +  f0_1(&x); +} + +namespace test1 { +  template <class T> void bar(T &x) { T::fail(); } +  template <class T> void bar(volatile T &x) {} + +  void test_ints() { +    volatile int x; +    bar(x = 5); +    bar(x += 5); +  } + +  enum E { E_zero }; +  void test_enums() { +    volatile E x; +    bar(x = E_zero); +    bar(x += E_zero); // expected-error {{incompatible type}} +  } +} + +int test2(int x) { +  return x && 4; // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} + +  return x && sizeof(int) == 4;  // no warning, RHS is logical op. +  return x && true; +  return x && false; +  return x || true; +  return x || false; + +  return x && (unsigned)0; // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} + +  return x || (unsigned)1; // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} + +  return x || 0; // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x || 1; // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x || -1; // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x || 5; // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x && 0; // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x && 1; // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x && -1; // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x && 5; // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x || (0); // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x || (1); // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x || (-1); // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x || (5); // expected-warning {{use of logical '||' with constant operand}} \ +                   // expected-note {{use '|' for a bitwise operation}} +  return x && (0); // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x && (1); // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x && (-1); // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +  return x && (5); // expected-warning {{use of logical '&&' with constant operand}} \ +                   // expected-note {{use '&' for a bitwise operation}} \ +                   // expected-note {{remove constant to silence this warning}} +} + +template<unsigned int A, unsigned int B> struct S +{ +  enum { +    e1 = A && B, +    e2 = A && 7      // expected-warning {{use of logical '&&' with constant operand}} \ +                     // expected-note {{use '&' for a bitwise operation}} \ +                     // expected-note {{remove constant to silence this warning}} +  }; + +  int foo() { +    int x = A && B; +    int y = B && 3;  // expected-warning {{use of logical '&&' with constant operand}} \ +                     // expected-note {{use '&' for a bitwise operation}} \ +                     // expected-note {{remove constant to silence this warning}} + +    return x + y; +  } +}; + +void test3() { +  S<5, 8> s1; +  S<2, 7> s2; +  (void)s1.foo(); +  (void)s2.foo(); +} diff --git a/clang/test/SemaCXX/flexible-array-test.cpp b/clang/test/SemaCXX/flexible-array-test.cpp new file mode 100644 index 0000000..e6c3132 --- /dev/null +++ b/clang/test/SemaCXX/flexible-array-test.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +// pr7029 + +template <class Key, class T> struct QMap +{ +  void insert(const Key &, const T &); +  T v; +}; + + +template <class Key, class T> +void QMap<Key, T>::insert(const Key &, const T &avalue) +{ +  v = avalue; +} + + +struct inotify_event +{ +  int wd; +  +  // clang doesn't like '[]':  +  // cannot initialize a parameter of type 'void *' with an rvalue of type 'char (*)[]' +  char name [];	 +}; + + +void foo() +{ +    inotify_event event; +    inotify_event* ptr = &event; +    inotify_event event1 = *ptr; +    *ptr = event; +    QMap<int, inotify_event> eventForId; +    eventForId.insert(ptr->wd, *ptr); +} + +struct S { +	virtual void foo(); +}; + +struct X { +   int blah; +   S strings[];	// expected-error {{flexible array member 'strings' of non-POD element type 'S []'}} +}; + +class A { +  int s; +  char c[]; +}; + +union B { +  int s; +  char c[]; +}; + +namespace rdar9065507 { + +struct StorageBase { +  long ref_count; +  unsigned size; +  unsigned capacity; +}; + +struct Storage : StorageBase { +  int data[]; +}; + +} diff --git a/clang/test/SemaCXX/fntype-decl.cpp b/clang/test/SemaCXX/fntype-decl.cpp new file mode 100644 index 0000000..b8ae625 --- /dev/null +++ b/clang/test/SemaCXX/fntype-decl.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR2942 +typedef void fn(int); +fn f; // expected-note {{previous declaration is here}} + +int g(int x, int y); +int g(int x, int y = 2); + +typedef int g_type(int, int); +g_type g; + +int h(int x) { // expected-note {{previous definition is here}} +  return g(x); +} + +float f(int) { } // expected-error{{functions that differ only in their return type cannot be overloaded}} + +int h(int) { } // expected-error{{redefinition of 'h'}} + diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp new file mode 100644 index 0000000..8bda510 --- /dev/null +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -0,0 +1,182 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +namespace value_range_detail { +  template<typename T> +  class value_range_iter { +    T t; +  public: +    value_range_iter(const T &t) : t(t) {} +    T operator*() const { return t; } +    bool operator!=(const value_range_iter &o) const { return t != o.t; } +    value_range_iter &operator++() { ++t; return *this; } +  }; + +  template<typename T> +  struct value_range { +    value_range(const T &a, const T &b) : begin_(a), end_(b) {} +    value_range_iter<T> begin_, end_; +  }; + +  template<typename T> +  value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; } +  template<typename T> +  value_range_iter<T> end(const value_range<T> &r) { return r.end_; } + + +  struct end_t {}; + +  template<typename T> +  class value_range_step_iter { +    T it, step; +  public: +    value_range_step_iter(const T &it, const T &step) : it(it), step(step) {} +    T operator*() const { return it; } +    bool operator!=(value_range_step_iter end) const { return it != end.it; } +    value_range_step_iter &operator++() { it += step; return *this; } +  }; + +  template<typename T> +  class value_range_step { +    T it, step, end_; +  public: +    value_range_step(const T &it, const T &end, const T &step) : +      it(it), end_(end), step(step) {} +    typedef value_range_step_iter<T> iterator; +    iterator begin() const { return iterator(it, step); } +    iterator end() const { return iterator(end_, step); } +  }; +} + +template<typename T> +value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); } + +template<typename T> +value_range_detail::value_range_step<T> range(const T &a, const T &b, const T &step) { return value_range_detail::value_range_step<T>(a, b, step); } + + +namespace map_range { +  template<typename T> +  class vector { +    T storage[100]; +    decltype(sizeof(char)) size; +  public: +    vector() : size() {} +    void push_back(T t) { storage[size++] = t; } +    T *begin() { return storage; } +    T *end() { return storage + size; } +  }; + +  template<typename T> struct tuple_elem { +    T t; +    tuple_elem() {} +    tuple_elem(T t) : t(t) {} +  }; +  template<typename... A> +  struct tuple : tuple_elem<A>... { +    tuple() : tuple_elem<A>()... {} +    tuple(A... a) : tuple_elem<A>(a)... {} +    template<typename B> B &get() { return tuple_elem<B>::t; } +  }; + +  template<typename F, typename I> +  class map_iter { +    F f; +    I i; +  public: +    map_iter(F f, I i) : f(f), i(i) {} +    auto operator*() const -> decltype(f(*i)) { return f(*i); } +    bool operator!=(const map_iter &o) const { return i != o.i; } +    map_iter &operator++() { ++i; return *this; } +  }; + +  template<typename T> +  struct iter_pair { +    T begin_, end_; +    iter_pair(T begin, T end) : begin_(begin), end_(end) {} +  }; +  template<typename T> T begin(iter_pair<T> p) { return p.begin_; } +  template<typename T> T end(iter_pair<T> p) { return p.end_; } + +  template<typename...> class mem_fun_impl; +  template<typename R, typename T, typename... A> +  class mem_fun_impl<R (T::*)(A...)> { +    typedef R (T::*F)(A...); +    F f; +  public: +    mem_fun_impl(F f) : f(f) {} +    R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); } +  }; +  template<typename F> mem_fun_impl<F> mem_fun(F f) { return mem_fun_impl<F>(f); } + +  template<typename F, typename T> +  auto map(const F &f, T &t) -> iter_pair<map_iter<F, decltype(t.begin())>> { +    typedef map_iter<F, decltype(t.begin())> iter; +    return iter_pair<iter>(iter(f, t.begin()), iter(f, t.end())); +  } +} + +#define assert(b) if (!b) { return 1; } +int main() { +  int total = 0; + +  for (auto n : range(1, 5)) { +    total += n; +  } +  assert(total == 10); + +  for (auto n : range(10, 100, 10)) { +    total += n; +  } +  assert(total == 460); + +  map_range::vector<char> chars; +  chars.push_back('a'); +  chars.push_back('b'); +  chars.push_back('c'); +  for (char c : chars) { +    ++total; +  } +  assert(total == 463); + +  typedef map_range::tuple<int, double> T; +  map_range::vector<T> pairs; +  pairs.push_back(T(42, 12.9)); +  pairs.push_back(T(6, 4.2)); +  pairs.push_back(T(9, 1.1)); +  for (auto a : map(map_range::mem_fun(&T::get<int>), pairs)) { +    total += a; +  } +  assert(total == 500); +} + +// PR11793 +namespace test2 { +  class A { +    int xs[10]; // expected-note {{implicitly declared private here}} +  }; +  void test(A &a) { +    for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}} +  } +} + +namespace test3 { +  // Make sure this doesn't crash +  struct A {}; +  struct B { ~B(); operator bool(); }; +  struct C { B operator!=(const C&); C& operator++(); int operator*(); }; +  C begin(const A&); +  C end(const A&); +  template<typename T> void f() { for (auto a : A()) {} } +  void g() { f<int>(); } +} + +namespace test4 { +  void f() { +    int y; + +    // Make sure these don't crash. Better diagnostics would be nice. +    for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}} +    for (x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} +    for (y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} +  } +} diff --git a/clang/test/SemaCXX/for-range-no-std.cpp b/clang/test/SemaCXX/for-range-no-std.cpp new file mode 100644 index 0000000..fa42ca4 --- /dev/null +++ b/clang/test/SemaCXX/for-range-no-std.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions + +struct S { +  int *begin(); +  int *end(); +}; + +struct T { +}; + +struct Range {}; +int begin(Range); // expected-note {{not viable}} +int end(Range); + +namespace NS { +  struct ADL {}; +  struct iter { +    int operator*(); +    bool operator!=(iter); +    void operator++(); +  }; +  iter begin(ADL); // expected-note {{not viable}} +  iter end(ADL); + +  struct NoADL {}; +} +NS::iter begin(NS::NoADL); // expected-note {{not viable}} +NS::iter end(NS::NoADL); + +void f() { +  int a[] = {1, 2, 3}; +  for (auto b : S()) {} // ok +  for (auto b : T()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} +  for (auto b : a) {} // ok +  for (int b : NS::ADL()) {} // ok +  for (int b : NS::NoADL()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} +} + +void PR11601() { +  void (*vv[])() = {PR11601, PR11601, PR11601}; +  for (void (*i)() : vv) i(); +} diff --git a/clang/test/SemaCXX/for-range-unused.cpp b/clang/test/SemaCXX/for-range-unused.cpp new file mode 100644 index 0000000..ce6b379 --- /dev/null +++ b/clang/test/SemaCXX/for-range-unused.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wunused + +// PR9968: We used to warn that __range is unused in a dependent for-range. + +template <typename T> +  struct Vector { +    void doIt() { +      int a; // expected-warning {{unused variable 'a'}} + +      for (auto& e : elements) +        ; +    } + +    T elements[10]; +  }; + + +int main(int, char**) { +  Vector<int>    vector; +  vector.doIt(); +} diff --git a/clang/test/SemaCXX/format-strings-0x.cpp b/clang/test/SemaCXX/format-strings-0x.cpp new file mode 100644 index 0000000..e7c5904 --- /dev/null +++ b/clang/test/SemaCXX/format-strings-0x.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -std=c++11 %s + +extern "C" { +extern int scanf(const char *restrict, ...); +extern int printf(const char *restrict, ...); +} + +void f(char **sp, float *fp) { +  scanf("%as", sp); // expected-warning{{format specifies type 'float *' but the argument has type 'char **'}} + +  printf("%a", 1.0); +  scanf("%afoobar", fp); +  printf(nullptr); +  printf(*sp); // expected-warning {{not a string literal}} +} diff --git a/clang/test/SemaCXX/format-strings.cpp b/clang/test/SemaCXX/format-strings.cpp new file mode 100644 index 0000000..6b0df29 --- /dev/null +++ b/clang/test/SemaCXX/format-strings.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s + +#include <stdarg.h> + +extern "C" { +extern int scanf(const char *restrict, ...); +extern int printf(const char *restrict, ...); +extern int vprintf(const char *restrict, va_list); +} + +void f(char **sp, float *fp) { +  scanf("%as", sp); // expected-warning{{'a' length modifier is not supported by ISO C}} + +  // TODO: Warn that the 'a' conversion specifier is a C++11 feature. +  printf("%a", 1.0); +  scanf("%afoobar", fp); +} + +void g() { +  printf("%ls", "foo"); // expected-warning{{format specifies type 'wchar_t *' but the argument has type 'const char *'}} +} + +// Test that we properly handle format_idx on C++ members. +class Foo { +public: +  const char *gettext(const char *fmt) __attribute__((format_arg(2))); + +  int scanf(const char *, ...) __attribute__((format(scanf, 2, 3))); +  int printf(const char *, ...) __attribute__((format(printf, 2, 3))); +  int printf2(const char *, ...); + +  static const char *gettext_static(const char *fmt) __attribute__((format_arg(1))); +  static int printf_static(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +}; + +void h(int *i) { +  Foo foo; +  foo.scanf("%d"); // expected-warning{{more '%' conversions than data arguments}} +  foo.printf("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} +  Foo::printf_static("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} + +  printf(foo.gettext("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} +  printf(Foo::gettext_static("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} +} + +// Test handling __null for format string literal checking. +extern "C" { +  int test_null_format(const char *format, ...) __attribute__((__format__ (__printf__, 1, 2))); +} + +void rdar8269537(const char *f) +{ +  test_null_format(false); // expected-warning {{null from a constant boolean}} +  test_null_format(0); // no-warning +  test_null_format(__null); // no-warning +  test_null_format(f); // expected-warning {{not a string literal}} +} + +int Foo::printf(const char *fmt, ...) { +  va_list ap; +  va_start(ap,fmt); +  const char * const format = fmt; +  vprintf(format, ap); // no-warning + +  const char *format2 = fmt; +  vprintf(format2, ap); // expected-warning{{format string is not a string literal}} + +  return 0; +} + +int Foo::printf2(const char *fmt, ...) { +  va_list ap; +  va_start(ap,fmt); +  vprintf(fmt, ap); // expected-warning{{format string is not a string literal}} + +  return 0; +} diff --git a/clang/test/SemaCXX/friend-class-nodecl.cpp b/clang/test/SemaCXX/friend-class-nodecl.cpp new file mode 100644 index 0000000..41e2da6 --- /dev/null +++ b/clang/test/SemaCXX/friend-class-nodecl.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -ast-print %s -o %t +// RUN: not grep '^ *class B' %t + +// Tests that the tag decls in friend declarations aren't added to the +// declaring class's decl chain. + +class A { +  friend class B; +}; + diff --git a/clang/test/SemaCXX/friend-out-of-line.cpp b/clang/test/SemaCXX/friend-out-of-line.cpp new file mode 100644 index 0000000..56b2daa --- /dev/null +++ b/clang/test/SemaCXX/friend-out-of-line.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/10204947> +namespace N { +  class X; +}; + +class N::X { +  template<typename T> friend const T& f(const X&); +  friend const int& g(const X&); +  friend class Y; +}; diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp new file mode 100644 index 0000000..c5b11eb --- /dev/null +++ b/clang/test/SemaCXX/friend.cpp @@ -0,0 +1,140 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +friend class A; // expected-error {{'friend' used outside of class}} +void f() { friend class A; } // expected-error {{'friend' used outside of class}} +class C { friend class A; }; +class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}} + +// PR5760 +namespace test0 { +  namespace ns { +    void f(int); +  } + +  struct A { +    friend void ns::f(int a); +  }; +} + +// Test derived from LLVM's Registry.h +namespace test1 { +  template <class T> struct Outer { +    void foo(T); +    struct Inner { +      friend void Outer::foo(T); +    }; +  }; + +  void test() { +    (void) Outer<int>::Inner(); +  } +} + +// PR5476 +namespace test2 { +  namespace foo { +    void Func(int x); +  } + +  class Bar { +    friend void ::test2::foo::Func(int x); +  }; +} + +// PR5134 +namespace test3 { +  class Foo { +    friend const int getInt(int inInt = 0); + +  }; +} + +namespace test4 { +  class T4A { +    friend class T4B; +   +  public: +    T4A(class T4B *); + +  protected: +    T4B *mB;          // error here +  }; +  +  class T4B {}; +} + +namespace rdar8529993 { +struct A { ~A(); }; + +struct B : A +{ +  template<int> friend A::~A(); // expected-error {{destructor cannot be declared as a template}} +}; +} + +// PR7915 +namespace test5 { +  struct A; +  struct A1 { friend void A(); }; + +  struct B { friend void B(); }; +} + +// PR8479 +namespace test6_1 { +  class A { +   public: +   private: +    friend class vectorA; +    A() {} +  }; +  class vectorA { +   public: +    vectorA(int i, const A& t = A()) {} +  }; +  void f() { +    vectorA v(1); +  } +} +namespace test6_2 { +  template<class T> +  class vector { +   public: +    vector(int i, const T& t = T()) {} +  }; +  class A { +   public: +   private: +    friend class vector<A>; +    A() {} +  }; +  void f() { +    vector<A> v(1); +  } +} +namespace test6_3 { +  template<class T> +  class vector { +   public: +    vector(int i) {} +    void f(const T& t = T()) {} +  }; +  class A { +   public: +   private: +    friend void vector<A>::f(const A&); +    A() {} +  }; +  void f() { +    vector<A> v(1); +    v.f(); +  } +} + +namespace test7 { +  extern "C" { +    class X { +      friend int f() { return 42; } +    }; +  } +} diff --git a/clang/test/SemaCXX/function-extern-c.cpp b/clang/test/SemaCXX/function-extern-c.cpp new file mode 100644 index 0000000..f20cd38 --- /dev/null +++ b/clang/test/SemaCXX/function-extern-c.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -Wreturn-type -fsyntax-only -std=c++11 -verify %s + +class A { +public: +  A(const A&); +}; + +struct S { +  int i; +  double d; + +  virtual void B() {} +}; + +union U { +  struct { +    int i; +    virtual void B() {} // Can only do this in C++11 +  } t; +}; + +struct S2 { +  int i; +  double d; +}; + +extern "C" U f3( void ); // expected-warning {{'f3' has C-linkage specified, but returns user-defined type 'U' which is incompatible with C}} +extern "C" S f0(void); // expected-warning {{'f0' has C-linkage specified, but returns user-defined type 'S' which is incompatible with C}} +extern "C" A f4( void ); // expected-warning {{'f4' has C-linkage specified, but returns user-defined type 'A' which is incompatible with C}} + +// These should all be fine +extern "C" S2 f5( void ); +extern "C" void f2( A x ); +extern "C" void f6( S s ); +extern "C" void f7( U u ); +extern "C" double f8(void); +extern "C" long long f11( void ); +extern "C" A *f10( void ); diff --git a/clang/test/SemaCXX/function-overload-typo-crash.cpp b/clang/test/SemaCXX/function-overload-typo-crash.cpp new file mode 100644 index 0000000..8c5cec8 --- /dev/null +++ b/clang/test/SemaCXX/function-overload-typo-crash.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR10283 +void min(); //expected-note {{'min' declared here}} +void min(int); + +template <typename T> void max(T); //expected-note {{'max' declared here}} + +void f() { +  fin(); //expected-error {{use of undeclared identifier 'fin'; did you mean 'min'}} +  fax(0); //expected-error {{use of undeclared identifier 'fax'; did you mean 'max'}} +} + +template <typename T> void somefunc(T*, T*); //expected-note {{'somefunc' declared here}} +template <typename T> void somefunc(const T[]); //expected-note {{'somefunc' declared here}} +template <typename T1, typename T2> void somefunc(T1*, T2*); //expected-note {{'somefunc' declared here}} +template <typename T1, typename T2> void somefunc(T1*, const T2[]); //expected-note 2 {{'somefunc' declared here}} + +void c() { +  int *i = 0, *j = 0; +  const int x[] = {1, 2, 3}; +  long *l = 0; +  somefun(i, j); //expected-error {{use of undeclared identifier 'somefun'; did you mean 'somefunc'?}} +  somefun(x); //expected-error {{use of undeclared identifier 'somefun'; did you mean 'somefunc'?}} +  somefun(i, l); //expected-error {{use of undeclared identifier 'somefun'; did you mean 'somefunc'?}} +  somefun(l, x); //expected-error {{use of undeclared identifier 'somefun'; did you mean 'somefunc'?}} +  somefun(i, x); //expected-error {{use of undeclared identifier 'somefun'; did you mean 'somefunc'?}} +} diff --git a/clang/test/SemaCXX/function-overloaded-redecl.cpp b/clang/test/SemaCXX/function-overloaded-redecl.cpp new file mode 100644 index 0000000..0077881 --- /dev/null +++ b/clang/test/SemaCXX/function-overloaded-redecl.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +typedef const int cInt; + +void f (int);  +void f (const int);  // redecl + +void f (int) {  }    // expected-note {{previous definition is here}} +void f (cInt) { }    // expected-error {{redefinition of 'f'}} + diff --git a/clang/test/SemaCXX/function-redecl.cpp b/clang/test/SemaCXX/function-redecl.cpp new file mode 100644 index 0000000..0eb109d --- /dev/null +++ b/clang/test/SemaCXX/function-redecl.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +int foo(int); + +namespace N { +  void f1() { +    void foo(int); // okay +  } + +  // FIXME: we shouldn't even need this declaration to detect errors +  // below. +  void foo(int); // expected-note{{previous declaration is here}} + +  void f2() { +    int foo(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} + +    { +      int foo; +      { +        // FIXME: should diagnose this because it's incompatible with +        // N::foo. However, name lookup isn't properly "skipping" the +        // "int foo" above. +        float foo(int);  +      } +    } +  } +} + +class A { + void typocorrection(); // expected-note {{'typocorrection' declared here}} +}; + +void A::Notypocorrection() { // expected-error {{out-of-line definition of 'Notypocorrection' does not match any declaration in 'A'; did you mean 'typocorrection'}} +} + + +namespace test0 { +  void dummy() { +    void Bar(); // expected-note {{'Bar' declared here}} +    class A { +      friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean 'Bar'}} +    }; +  } +} + + +class B { + void typocorrection(const int); // expected-note {{'typocorrection' declared here}} + void typocorrection(double); +}; + +void B::Notypocorrection(int) { // expected-error {{out-of-line definition of 'Notypocorrection' does not match any declaration in 'B'; did you mean 'typocorrection'}} +} + +struct X { int f(); }; +struct Y : public X {}; +int Y::f() { return 3; } // expected-error {{out-of-line definition of 'f' does not match any declaration in 'Y'}} + +namespace test1 { +struct Foo { +  class Inner { }; +}; +} + +class Bar { +  void f(test1::Foo::Inner foo) const; // expected-note {{member declaration does not match because it is const qualified}} +}; + +using test1::Foo; + +void Bar::f(Foo::Inner foo) { // expected-error {{out-of-line definition of 'f' does not match any declaration in 'Bar'}} +  (void)foo; +} + +class Crash { + public: +  void GetCart(int count) const; +}; +// This out-of-line definition was fine... +void Crash::cart(int count) const {} // expected-error {{out-of-line definition of 'cart' does not match any declaration in 'Crash'}} \ +                                     // expected-note {{'cart' declared here}} \ +                                     // expected-note {{previous definition is here}} +// ...while this one crashed clang +void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'; did you mean 'cart'?}} \ +                                      // expected-error {{redefinition of 'cart'}} + +class TestConst { + public: +  int getit() const; // expected-note {{member declaration does not match because it is const qualified}} +  void setit(int); // expected-note {{member declaration does not match because it is not const qualified}} +}; + +int TestConst::getit() { // expected-error {{out-of-line definition of 'getit' does not match any declaration in 'TestConst'}} +  return 1; +} + +void TestConst::setit(int) const { // expected-error {{out-of-line definition of 'setit' does not match any declaration in 'TestConst'}} +} + +struct J { int typo() const; }; +int J::typo_() { return 3; } // expected-error {{out-of-line definition of 'typo_' does not match any declaration in 'J'}} diff --git a/clang/test/SemaCXX/function-type-qual.cpp b/clang/test/SemaCXX/function-type-qual.cpp new file mode 100644 index 0000000..73613ae --- /dev/null +++ b/clang/test/SemaCXX/function-type-qual.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() const; // expected-error {{non-member function cannot have 'const' qualifier}} +void (*pf)() const; // expected-error {{pointer to function type cannot have 'const' qualifier}} +extern void (&rf)() const; // expected-error {{reference to function type cannot have 'const' qualifier}} + +typedef void cfn() const; +cfn f2; // expected-error {{non-member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}} + +class C { +  void f() const; +  cfn f2; +  static void f3() const; // expected-error {{static member function cannot have 'const' qualifier}} +  static cfn f4; // expected-error {{static member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}} + +  void m1() { +    x = 0; +  } + +  void m2() const { +    x = 0; // expected-error {{read-only variable is not assignable}} +  } + +  int x; +}; + +void (C::*mpf)() const; +cfn C::*mpg; diff --git a/clang/test/SemaCXX/functional-cast.cpp b/clang/test/SemaCXX/functional-cast.cpp new file mode 100644 index 0000000..61e4da3 --- /dev/null +++ b/clang/test/SemaCXX/functional-cast.cpp @@ -0,0 +1,320 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// ------------ not interpreted as C-style cast ------------ + +struct SimpleValueInit { +  int i; +}; + +struct InitViaConstructor { +  InitViaConstructor(int i = 7); +}; + +struct NoValueInit { // expected-note 2 {{candidate constructor (the implicit copy constructor)}}  +  NoValueInit(int i, int j); // expected-note 2 {{candidate constructor}} +}; + +void test_cxx_functional_value_init() { +  (void)SimpleValueInit(); +  (void)InitViaConstructor(); +  (void)NoValueInit(); // expected-error{{no matching constructor for initialization}} +} + +void test_cxx_function_cast_multi() {  +  (void)NoValueInit(0, 0); +  (void)NoValueInit(0, 0, 0); // expected-error{{no matching constructor for initialization}} +  (void)int(1, 2); // expected-error{{excess elements in scalar initializer}} +} + + +// ------------------ everything else -------------------- + +struct A {}; + +// ----------- const_cast -------------- + +typedef char c; +typedef c *cp; +typedef cp *cpp; +typedef cpp *cppp; +typedef cppp &cpppr; +typedef const cppp &cpppcr; +typedef const char cc; +typedef cc *ccp; +typedef volatile ccp ccvp; +typedef ccvp *ccvpp; +typedef const volatile ccvpp ccvpcvp; +typedef ccvpcvp *ccvpcvpp; +typedef int iar[100]; +typedef iar &iarr; +typedef int (*f)(int); + +void t_cc() +{ +  ccvpcvpp var = 0; +  // Cast away deep consts and volatiles. +  char ***var2 = cppp(var); +  char ***const &var3 = var2; +  // Const reference to reference. +  char ***&var4 = cpppr(var3); +  // Drop reference. Intentionally without qualifier change. +  char *** var5 = cppp(var4); +  const int ar[100] = {0}; +  // Array decay. Intentionally without qualifier change. +  typedef int *intp; +  int *pi = intp(ar); +  f fp = 0; +  // Don't misidentify fn** as a function pointer. +  typedef f *fp_t; +  f *fpp = fp_t(&fp); +  int const A::* const A::*icapcap = 0; +  typedef int A::* A::*iapap_t; +  iapap_t iapap = iapap_t(icapcap); +} + +// ----------- static_cast ------------- + +struct B : public A {};             // Single public base. +struct C1 : public virtual B {};    // Single virtual base. +struct C2 : public virtual B {}; +struct D : public C1, public C2 {}; // Diamond +struct E : private A {};            // Single private base. +struct F : public C1 {};            // Single path to B with virtual. +struct G1 : public B {}; +struct G2 : public B {}; +struct H : public G1, public G2 {}; // Ambiguous path to B. + +enum Enum { En1, En2 }; +enum Onom { On1, On2 }; + +struct Co1 { operator int(); }; +struct Co2 { Co2(int); }; +struct Co3 { }; +struct Co4 { Co4(Co3); operator Co3(); }; + +// Explicit implicits +void t_529_2() +{ +  int i = 1; +  (void)float(i); +  double d = 1.0; +  (void)float(d); +  (void)int(d); +  (void)char(i); +  typedef unsigned long ulong; +  (void)ulong(i); +  (void)int(En1); +  (void)double(En1); +  typedef int &intr; +  (void)intr(i); +  typedef const int &cintr; +  (void)cintr(i); + +  int ar[1]; +  typedef const int *cintp; +  (void)cintp(ar); +  typedef void (*pfvv)(); +  (void)pfvv(t_529_2); + +  typedef void *voidp; +  (void)voidp(0); +  (void)voidp((int*)0); +  typedef volatile const void *vcvoidp; +  (void)vcvoidp((const int*)0); +  typedef A *Ap; +  (void)Ap((B*)0); +  typedef A &Ar; +  (void)Ar(*((B*)0)); +  typedef const B *cBp; +  (void)cBp((C1*)0); +  typedef B &Br; +  (void)Br(*((C1*)0)); +  (void)Ap((D*)0); +  typedef const A &cAr; +  (void)cAr(*((D*)0)); +  typedef int B::*Bmp; +  (void)Bmp((int A::*)0); +  typedef void (B::*Bmfp)(); +  (void)Bmfp((void (A::*)())0); +  (void)Ap((E*)0); // functional-style cast ignores access control +  (void)voidp((const int*)0); // const_cast appended + +  (void)int(Co1()); +  (void)Co2(1); +  (void)Co3((Co4)(Co3())); + +  // Bad code below +  //(void)(A*)((H*)0); // {{static_cast from 'struct H *' to 'struct A *' is not allowed}} +} + +// Anything to void +void t_529_4() +{ +  void(1); +  (void(t_529_4)); +} + +// Static downcasts +void t_529_5_8() +{ +  typedef B *Bp; +  (void)Bp((A*)0); +  typedef B &Br; +  (void)Br(*((A*)0)); +  typedef const G1 *cG1p; +  (void)cG1p((A*)0); +  typedef const G1 &cG1r; +  (void)cG1r(*((A*)0)); +  (void)Bp((const A*)0); // const_cast appended +  (void)Br(*((const A*)0)); // const_cast appended +  typedef E *Ep; +  (void)Ep((A*)0); // access control ignored +  typedef E &Er; +  (void)Er(*((A*)0)); // access control ignored + +  // Bad code below + +  typedef C1 *C1p; +  (void)C1p((A*)0); // expected-error {{cannot cast 'A *' to 'C1p' (aka 'C1 *') via virtual base 'B'}} +  typedef C1 &C1r; +  (void)C1r(*((A*)0)); // expected-error {{cannot cast 'A' to 'C1r' (aka 'C1 &') via virtual base 'B'}} +  typedef D *Dp; +  (void)Dp((A*)0); // expected-error {{cannot cast 'A *' to 'Dp' (aka 'D *') via virtual base 'B'}} +  typedef D &Dr; +  (void)Dr(*((A*)0)); // expected-error {{cannot cast 'A' to 'Dr' (aka 'D &') via virtual base 'B'}} +  typedef H *Hp; +  (void)Hp((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}} +  typedef H &Hr; +  (void)Hr(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}} + +  // TODO: Test DR427. This requires user-defined conversions, though. +} + +// Enum conversions +void t_529_7() +{ +  (void)Enum(1); +  (void)Enum(1.0); +  (void)Onom(En1); + +  // Bad code below + +  (void)Enum((int*)0); // expected-error {{functional-style cast from 'int *' to 'Enum' is not allowed}} +} + +// Void pointer to object pointer +void t_529_10() +{ +  typedef int *intp; +  (void)intp((void*)0); +  typedef const A *cAp; +  (void)cAp((void*)0); +  (void)intp((const void*)0); // const_cast appended +} + +// Member pointer upcast. +void t_529_9() +{ +  typedef int A::*Amp; +  (void)Amp((int B::*)0); + +  // Bad code below +  (void)Amp((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} +  (void)Amp((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} +} + +// -------- reinterpret_cast ----------- + +enum test { testval = 1 }; +struct structure { int m; }; +typedef void (*fnptr)(); + +// Test conversion between pointer and integral types, as in p3 and p4. +void integral_conversion() +{ +  typedef void *voidp; +  void *vp = voidp(testval); +  long l = long(vp); +  typedef float *floatp; +  (void)floatp(l); +  fnptr fnp = fnptr(l); +  (void)char(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}} +  (void)long(fnp); +} + +void pointer_conversion() +{ +  int *p1 = 0; +  typedef float *floatp; +  float *p2 = floatp(p1); +  typedef structure *structurep; +  structure *p3 = structurep(p2); +  typedef int **ppint; +  typedef ppint *pppint; +  ppint *deep = pppint(p3); +  typedef fnptr fnptrp; +  (void)fnptrp(deep); +} + +void constness() +{ +  int ***const ipppc = 0; +  typedef int const *icp_t; +  int const *icp = icp_t(ipppc); +  typedef int *intp; +  (void)intp(icp); // const_cast appended +  typedef int const *const ** intcpcpp; +  intcpcpp icpcpp = intcpcpp(ipppc); // const_cast appended +  int *ip = intp(icpcpp); +  (void)icp_t(ip); +  typedef int const *const *const *intcpcpcp; +  (void)intcpcpcp(ipppc); +} + +void fnptrs() +{ +  typedef int (*fnptr2)(int); +  fnptr fp = 0; +  (void)fnptr2(fp); +  typedef void *voidp; +  void *vp = voidp(fp); +  (void)fnptr(vp); +} + +void refs() +{ +  long l = 0; +  typedef char &charr; +  char &c = charr(l); +  // Bad: from rvalue +  typedef int &intr; +  (void)intr(&c); // expected-error {{functional-style cast from rvalue to reference type 'intr' (aka 'int &')}} +} + +void memptrs() +{ +  const int structure::*psi = 0; +  typedef const float structure::*structurecfmp; +  (void)structurecfmp(psi); +  typedef int structure::*structureimp; +  (void)structureimp(psi); // const_cast appended + +  void (structure::*psf)() = 0; +  typedef int (structure::*structureimfp)(); +  (void)structureimfp(psf); + +  typedef void (structure::*structurevmfp)(); +  (void)structurevmfp(psi); // expected-error {{functional-style cast from 'const int structure::*' to 'structurevmfp' (aka 'void (structure::*)()') is not allowed}} +  (void)structureimp(psf); // expected-error {{functional-style cast from 'void (structure::*)()' to 'structureimp' (aka 'int structure::*') is not allowed}} +} + +// ---------------- misc ------------------ + +void crash_on_invalid_1() +{ +  typedef itn Typo; // expected-error {{unknown type name 'itn'}} +  (void)Typo(1); // used to crash + +  typedef int &int_ref; +  (void)int_ref(); // expected-error {{reference to type 'int' requires an initializer}} +} diff --git a/clang/test/SemaCXX/generic-selection.cpp b/clang/test/SemaCXX/generic-selection.cpp new file mode 100644 index 0000000..c0a5d89 --- /dev/null +++ b/clang/test/SemaCXX/generic-selection.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template <typename T, typename U = void*> +struct A { +  enum { +    id = _Generic(T(), // expected-error {{controlling expression type 'char' not compatible with any generic association type}} +        int: 1, // expected-note {{compatible type 'int' specified here}} +        float: 2, +        U: 3) // expected-error {{type 'int' in generic association compatible with previously specified type 'int'}} +  }; +}; + +static_assert(A<int>::id == 1, "fail"); +static_assert(A<float>::id == 2, "fail"); +static_assert(A<double, double>::id == 3, "fail"); + +A<char> a1; // expected-note {{in instantiation of template class 'A<char, void *>' requested here}} +A<short, int> a2; // expected-note {{in instantiation of template class 'A<short, int>' requested here}} + +template <typename T, typename U> +struct B { +  enum { +    id = _Generic(T(), +        int: 1, // expected-note {{compatible type 'int' specified here}} +        int: 2, // expected-error {{type 'int' in generic association compatible with previously specified type 'int'}} +        U: 3) +  }; +}; + +template <unsigned Arg, unsigned... Args> struct Or { +  enum { result = Arg | Or<Args...>::result }; +}; + +template <unsigned Arg> struct Or<Arg> { +  enum { result = Arg }; +}; + +template <class... Args> struct TypeMask { +  enum { +   result = Or<_Generic(Args(), int: 1, long: 2, short: 4, float: 8)...>::result +  }; +}; + +static_assert(TypeMask<int, long, short>::result == 7, "fail"); +static_assert(TypeMask<float, short>::result == 12, "fail"); +static_assert(TypeMask<int, float, float>::result == 9, "fail"); diff --git a/clang/test/SemaCXX/gnu-case-ranges.cpp b/clang/test/SemaCXX/gnu-case-ranges.cpp new file mode 100644 index 0000000..b082e3a --- /dev/null +++ b/clang/test/SemaCXX/gnu-case-ranges.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -verify -Wno-covered-switch-default %s + +enum E { +    one, +    two, +    three, +    four +}; + + +int test(enum E e)  +{ +    switch (e)  +    { +        case one: +            return 7; +        case two ... two + 1: +            return 42; +        case four: +            return 25; +        default: +            return 0; +    } +} diff --git a/clang/test/SemaCXX/goto.cpp b/clang/test/SemaCXX/goto.cpp new file mode 100644 index 0000000..24bcb7c --- /dev/null +++ b/clang/test/SemaCXX/goto.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wall -fblocks %s + +// PR9463 +double *end; +void f(bool b1, bool b2) { +  { +    do { +      int end = 0; +      if (b2) { +        do { +          goto end; +        } while (b2); +      } +      end = 1; +    } while (b1); +  } + + end: +  return; +} + +namespace N { +  float* end; +  void f(bool b1, bool b2) { +    { +      do { +        int end = 0; +        if (b2) { +          do { +            goto end; +          } while (b2); +        } +        end = 1; +      } while (b1); +    } + +  end: +    return; +  } +} + +void g() { +  end = 1; // expected-error{{assigning to 'double *' from incompatible type 'int'}} +} + +void h(int end) { +  { +    goto end; // expected-error{{use of undeclared label 'end'}} +  } +} + +void h2(int end) { +  { +    __label__ end; +    goto end; + +  end: +    ::end = 0; +  } + end: // expected-warning{{unused label 'end'}} +  end = 1; +} + +class X { +public: +  X(); +}; + +void rdar9135994() +{ +X:   +    goto X; +} + +namespace PR9495 { +  struct NonPOD { NonPOD(); ~NonPOD(); };   +   +  void f(bool b) { +    NonPOD np; +    if (b) { +      goto undeclared; // expected-error{{use of undeclared label 'undeclared'}} +    } +  } + +  void g() { +    (void)^(bool b){ +      NonPOD np; +      if (b) { +        goto undeclared; // expected-error{{use of undeclared label 'undeclared'}} +      } +    }; +  } +} + +extern "C" { +  void exit(int); +} + +void f() { +  { +    goto exit; +  } + exit: +  return; +} + +namespace PR10620 { +  struct S { +    ~S() {} +  }; +  void g(const S& s) { +    goto done; // expected-error {{goto into protected scope}} +    const S s2(s); // expected-note {{jump bypasses variable initialization}} +  done: +    ; +  } +} + +namespace test12 { +  struct A { A(); A(const A&); ~A(); }; +  void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: wierd location +    goto lbl; // expected-error {{goto into protected scope}} +    (void) ^{ (void) a; }; +  lbl: +    return; +  } +} diff --git a/clang/test/SemaCXX/goto2.cpp b/clang/test/SemaCXX/goto2.cpp new file mode 100644 index 0000000..01ea031 --- /dev/null +++ b/clang/test/SemaCXX/goto2.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +//PR9463 +int subfun(const char *text) { +  const char *tmp = text; +  return 0; +} + +void fun(const char* text) { +  int count = 0; +  bool check = true; + +  if (check) +    { +      const char *end = text; + +      if (check) +        { +          do +            { +              if (check) +                { +                  count = subfun(end); +                  goto end; +                } + +              check = !check; +            } +          while (check); +        } +      // also works, after commenting following line of source code +      int e = subfun(end); +    } + end: +  if (check) +    ++count; +} + +const char *text = "some text"; + +int main() { +	const char *ptr = text; + +	fun(ptr); + +	return 0; +} diff --git a/clang/test/SemaCXX/i-c-e-cxx.cpp b/clang/test/SemaCXX/i-c-e-cxx.cpp new file mode 100644 index 0000000..5631577 --- /dev/null +++ b/clang/test/SemaCXX/i-c-e-cxx.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s + +// C++-specific tests for integral constant expressions. + +const int c = 10; +int ar[c]; + +struct X0 { +  static const int value = static_cast<int>(4.0); +}; + +void f() { +  if (const int value = 17) { +    int array[value]; +  } +} + +int a() { +  const int t=t; // expected-note {{declared here}} +  switch(1) { // expected-warning {{no case matching constant switch condition '1'}} +    case t:; // expected-error {{not an integral constant expression}} expected-note {{initializer of 't' is not a constant expression}} +  } +} + +// PR6206:  out-of-line definitions are legit +namespace pr6206 { +  class Foo { +  public: +    static const int kBar; +  }; + +  const int Foo::kBar = 20; +   +  char Test() { +    char str[Foo::kBar]; +    str[0] = '0'; +    return str[0]; +  } +} + +// PR6373:  default arguments don't count. +void pr6373(const unsigned x = 0) { +  unsigned max = 80 / x; +} + + +// rdar://9204520 +namespace rdar9204520 { +   +struct A { +  static const int B = int(0.75 * 1000 * 1000); // expected-warning {{not a constant expression; folding it to a constant is a GNU extension}} +}; + +int foo() { return A::B; } +} + +// PR11040 +const int x = 10; +int* y = reinterpret_cast<const char&>(x); // expected-error {{cannot initialize}} + +// This isn't an integral constant expression, but make sure it folds anyway. +struct PR8836 { char _; long long a; }; // expected-warning {{long long}} +int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + +const int nonconst = 1.0; // expected-note {{declared here}} +int arr[nonconst]; // expected-warning {{folded to constant array as an extension}} expected-note {{initializer of 'nonconst' is not a constant expression}} +const int castfloat = static_cast<int>(1.0); +int arr2[castfloat]; // ok diff --git a/clang/test/SemaCXX/illegal-member-initialization.cpp b/clang/test/SemaCXX/illegal-member-initialization.cpp new file mode 100644 index 0000000..87069ef --- /dev/null +++ b/clang/test/SemaCXX/illegal-member-initialization.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +struct A { +   A() : value(), cvalue() { } // expected-error {{reference to type 'int' requires an initializer}} +   int &value; +   const int cvalue; +}; + +struct B { +}; + +struct X { +   X() { }      // expected-error {{constructor for 'X' must explicitly initialize the reference member 'value'}} \ +                // expected-error {{constructor for 'X' must explicitly initialize the const member 'cvalue'}} \ +                // expected-error {{constructor for 'X' must explicitly initialize the reference member 'b'}} \ +                // expected-error {{constructor for 'X' must explicitly initialize the const member 'cb'}} +   int &value; // expected-note{{declared here}} +   const int cvalue; // expected-note{{declared here}} +   B& b; // expected-note{{declared here}} +   const B cb; // expected-note{{declared here}} +}; + + +// PR5924 +struct bar {}; +bar xxx(); + +struct foo { +  foo_t a;  // expected-error {{unknown type name 'foo_t'}} +  foo() : a(xxx()) {}  // no error here. +}; diff --git a/clang/test/SemaCXX/implicit-exception-spec.cpp b/clang/test/SemaCXX/implicit-exception-spec.cpp new file mode 100644 index 0000000..25316f8 --- /dev/null +++ b/clang/test/SemaCXX/implicit-exception-spec.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s + +template<bool b> struct ExceptionIf { static int f(); }; +template<> struct ExceptionIf<false> { typedef int f; }; + +// The exception specification of a defaulted default constructor depends on +// the contents of in-class member initializers. However, the in-class member +// initializers can depend on the exception specification of the constructor, +// since the class is considered complete within them. We reject any such cases. +namespace InClassInitializers { +  // Noexcept::Noexcept() is implicitly declared as noexcept(false), because it +  // directly invokes ThrowSomething(). However... +  // +  // If noexcept(Noexcept()) is false, then Noexcept() is a constant expression, +  // so noexcept(Noexcept()) is true. But if noexcept(Noexcept()) is true, then +  // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept()) +  // is false. +  bool ThrowSomething() noexcept(false); +  struct ConstExpr { +    bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{exception specification is not available until end of class definition}} +  }; +  // We can use it now. +  bool w = noexcept(ConstExpr()); + +  // Much more obviously broken: we can't parse the initializer without already +  // knowing whether it produces a noexcept expression. +  struct TemplateArg { +    int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{exception specification is not available until end of class definition}} +  }; +  bool x = noexcept(TemplateArg()); + +  // And within a nested class. +  struct Nested { +    struct Inner { +      int n = ExceptionIf<noexcept(Nested())>::f(); // expected-error {{exception specification is not available until end of class definition}} +    } inner; +  }; +  bool y = noexcept(Nested()); +  bool z = noexcept(Nested::Inner()); +} + +namespace ExceptionSpecification { +  // A type is permitted to be used in a dynamic exception specification when it +  // is still being defined, but isn't complete within such an exception +  // specification. +  struct Nested { // expected-note {{not complete}} +    struct T { +      T() noexcept(!noexcept(Nested())); // expected-error{{incomplete type}} +    } t; +  }; +} + +namespace DefaultArgument { +  struct Default { +    struct T { +      T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to implicitly-deleted default constructor}} +    } t; // expected-note {{has no default constructor}} +  }; +} + +namespace ImplicitDtorExceptionSpec { +  struct A { +    virtual ~A(); + +    struct Inner { +      ~Inner() throw(); +    }; +    Inner inner; +  }; + +  struct B { +    virtual ~B() {} // expected-note {{here}} +  }; + +  struct C : B { +    virtual ~C() {} +    A a; +  }; + +  struct D : B { +    ~D(); // expected-error {{more lax than base}} +    struct E { +      ~E(); +      struct F { +        ~F() throw(A); +      } f; +    } e; +  }; +} diff --git a/clang/test/SemaCXX/implicit-int.cpp b/clang/test/SemaCXX/implicit-int.cpp new file mode 100644 index 0000000..9711adf --- /dev/null +++ b/clang/test/SemaCXX/implicit-int.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +x; // expected-error{{C++ requires a type specifier for all declarations}} + +f(int y) { return y; } // expected-error{{C++ requires a type specifier for all declarations}} diff --git a/clang/test/SemaCXX/implicit-member-functions.cpp b/clang/test/SemaCXX/implicit-member-functions.cpp new file mode 100644 index 0000000..8451739 --- /dev/null +++ b/clang/test/SemaCXX/implicit-member-functions.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { }; +A::A() { } // expected-error {{definition of implicitly declared default constructor}} + +struct B { }; +B::B(const B&) { } // expected-error {{definition of implicitly declared copy constructor}} + +struct C { }; +C& C::operator=(const C&) { return *this; } // expected-error {{definition of implicitly declared copy assignment operator}} + +struct D { }; +D::~D() { } // expected-error {{definition of implicitly declared destructor}} + +// Make sure that the special member functions are introduced for +// name-lookup purposes and overload with user-declared +// constructors and assignment operators. +namespace PR6570 { +  class A { }; + +  class B { +  public: +    B() {} + +    B(const A& a) { +      operator = (CONST); +      operator = (a); +    } + +    B& operator = (const A& a) { +      return *this; +    } + +    void f(const A &a) { +      B b(a); +    }; + +    static const B CONST; +  }; + +} + +namespace PR7594 { +  // If the lazy declaration of special member functions is triggered +  // in an out-of-line initializer, make sure the functions aren't in +  // the initializer scope. This used to crash Clang: +  struct C { +    C(); +    static C *c; +  }; +  C *C::c = new C(); +} diff --git a/clang/test/SemaCXX/implicit-virtual-member-functions.cpp b/clang/test/SemaCXX/implicit-virtual-member-functions.cpp new file mode 100644 index 0000000..f6082e5 --- /dev/null +++ b/clang/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { +  virtual ~A(); +}; + +struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} +  virtual void f(); + +  void operator delete (void *, int); // expected-note {{'operator delete' declared here}} +}; + +void B::f() { // expected-note {{implicit default destructor for 'B' first required here}} +} + +struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} +  C(); +  void operator delete(void *, int); // expected-note {{'operator delete' declared here}} +}; + +C::C() { }  // expected-note {{implicit default destructor for 'C' first required here}} + +struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} +  void operator delete(void *, int); // expected-note {{'operator delete' declared here}} +};  + +void f() { +  new D; // expected-note {{implicit default destructor for 'D' first required here}} +} + diff --git a/clang/test/SemaCXX/incomplete-call.cpp b/clang/test/SemaCXX/incomplete-call.cpp new file mode 100644 index 0000000..69eb03a --- /dev/null +++ b/clang/test/SemaCXX/incomplete-call.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A; // expected-note 14 {{forward declaration of 'A'}} + +A f(); // expected-note {{'f' declared here}} + +struct B { +  A f(); // expected-note {{'f' declared here}} +  A operator()(); // expected-note 2 {{'operator()' declared here}} +  operator A(); // expected-note {{'operator A' declared here}} +  A operator!(); // expected-note 2 {{'operator!' declared here}} +  A operator++(int); // expected-note {{'operator++' declared here}} +  A operator[](int); // expected-note {{'operator[]' declared here}} +  A operator+(int); // expected-note {{'operator+' declared here}} +  A operator->(); // expected-note {{'operator->' declared here}} +}; + +void g() { +  f(); // expected-error {{calling 'f' with incomplete return type 'A'}} + +  typedef A (*Func)(); +  Func fp; +  fp(); // expected-error {{calling function with incomplete return type 'A'}} +  ((Func)0)();  // expected-error {{calling function with incomplete return type 'A'}}   +   +  B b; +  b.f(); // expected-error {{calling 'f' with incomplete return type 'A'}} +   +  b.operator()(); // expected-error {{calling 'operator()' with incomplete return type 'A'}} +  b.operator A(); // expected-error {{calling 'operator A' with incomplete return type 'A'}} +  b.operator!(); // expected-error {{calling 'operator!' with incomplete return type 'A'}} +   +  !b; // expected-error {{calling 'operator!' with incomplete return type 'A'}} +  b(); // expected-error {{calling 'operator()' with incomplete return type 'A'}} +  b++; // expected-error {{calling 'operator++' with incomplete return type 'A'}} +  b[0]; // expected-error {{calling 'operator[]' with incomplete return type 'A'}} +  b + 1; // expected-error {{calling 'operator+' with incomplete return type 'A'}} +  b->f(); // expected-error {{calling 'operator->' with incomplete return type 'A'}} +   +  A (B::*mfp)() = 0; +  (b.*mfp)(); // expected-error {{calling function with incomplete return type 'A'}} +   +} + + +struct C; // expected-note{{forward declaration}} + +void test_incomplete_object_call(C& c) { +  c(); // expected-error{{incomplete type in call to object of type}} +} diff --git a/clang/test/SemaCXX/increment-decrement.cpp b/clang/test/SemaCXX/increment-decrement.cpp new file mode 100644 index 0000000..11b7d1e --- /dev/null +++ b/clang/test/SemaCXX/increment-decrement.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +volatile int i; + +const int &inc = i++; +const int &dec = i--; + +const int &incfail = ++i; // expected-error {{drops qualifiers}} +const int &decfail = --i; // expected-error {{drops qualifiers}} + +// PR7794 +void f0(int e) { +  ++(int&)e; +} diff --git a/clang/test/SemaCXX/indirect-goto.cpp b/clang/test/SemaCXX/indirect-goto.cpp new file mode 100644 index 0000000..5b3fac4 --- /dev/null +++ b/clang/test/SemaCXX/indirect-goto.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test1 { +  // Make sure this doesn't crash. +  struct A { ~A(); }; +  void a() { goto *(A(), &&L); L: return; } +} diff --git a/clang/test/SemaCXX/inherit.cpp b/clang/test/SemaCXX/inherit.cpp new file mode 100644 index 0000000..a926c81 --- /dev/null +++ b/clang/test/SemaCXX/inherit.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class A { }; + +class B1 : A { }; + +class B2 : virtual A { }; + +class B3 : virtual virtual A { }; // expected-error{{duplicate 'virtual' in base specifier}} + +class C : public B1, private B2 { }; + + +class D;                // expected-note {{forward declaration of 'D'}} + +class E : public D { }; // expected-error{{base class has incomplete type}} + +typedef int I; + +class F : public I { }; // expected-error{{base specifier must name a class}} + +union U1 : public A { }; // expected-error{{unions cannot have base classes}} + +union U2 {}; + +class G : public U2 { }; // expected-error{{unions cannot be base classes}} + +typedef G G_copy; +typedef G G_copy_2; +typedef G_copy G_copy_3; + +class H : G_copy, A, G_copy_2, // expected-error{{base class 'G_copy' (aka 'G') specified more than once as a direct base class}} +          public G_copy_3 { }; // expected-error{{base class 'G_copy' (aka 'G') specified more than once as a direct base class}} diff --git a/clang/test/SemaCXX/init-priority-attr.cpp b/clang/test/SemaCXX/init-priority-attr.cpp new file mode 100644 index 0000000..6facebf --- /dev/null +++ b/clang/test/SemaCXX/init-priority-attr.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class Two { +private: +    int i, j, k; +public: +    static int count; +    Two( int ii, int jj ) { i = ii; j = jj; k = count++; }; +    Two( void )           { i =  0; j =  0; k = count++; }; +    int eye( void ) { return i; }; +    int jay( void ) { return j; }; +    int kay( void ) { return k; }; +}; + +extern Two foo; +extern Two goo; +extern Two coo[]; +extern Two koo[]; + +Two foo __attribute__((init_priority(101))) ( 5, 6 ); + +Two goo __attribute__((init_priority(2,3))) ( 5, 6 ); // expected-error {{attribute takes one argument}} + +Two coo[2]  __attribute__((init_priority(3)));	// expected-error {{init_priority attribute requires integer constant between 101 and 65535 inclusive}} + +Two koo[4]  __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires integer constant}} + + +Two func()  __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} + +int i  __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} + +int main() { +	Two foo __attribute__((init_priority(1001)));	// expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} +} + diff --git a/clang/test/SemaCXX/inline.cpp b/clang/test/SemaCXX/inline.cpp new file mode 100644 index 0000000..e569300 --- /dev/null +++ b/clang/test/SemaCXX/inline.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Check that we don't allow illegal uses of inline +// (checking C++-only constructs here) +struct c {inline int a;}; // expected-error{{'inline' can only appear on functions}} diff --git a/clang/test/SemaCXX/instantiate-blocks.cpp b/clang/test/SemaCXX/instantiate-blocks.cpp new file mode 100644 index 0000000..bb0f8d8 --- /dev/null +++ b/clang/test/SemaCXX/instantiate-blocks.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fblocks -fsyntax-only -verify %s +// rdar: // 6182276 + +template <typename T, typename T1> void foo(T t, T1 r) +{ +    T block_arg; +    __block T1 byref_block_arg; + +    T1 (^block)(T)  =  ^ T1 (T arg) {  +         byref_block_arg = arg; +         block_arg = arg; 	// expected-error {{variable is not assignable (missing __block type specifier)}} +         return block_arg+arg; }; +} + +// rdar://10466373 +template <typename T, typename T1> void noret(T t, T1 r) +{ +    (void) ^{ +    if (1) +      return t; +    else if (2) +      return r;  // expected-error {{return type 'double' must match previous return type 'float' when block literal has unspecified explicit return type}} +  }; +} + +int main(void) +{ +    foo(100, 'a');	// expected-note {{in instantiation of function template specialization 'foo<int, char>' requested here}} + +   noret((float)0.0, double(0.0)); // expected-note {{in instantiation of function template specialization 'noret<float, double>' requested here}} +} + diff --git a/clang/test/SemaCXX/invalid-instantiated-field-decl.cpp b/clang/test/SemaCXX/invalid-instantiated-field-decl.cpp new file mode 100644 index 0000000..8b26489 --- /dev/null +++ b/clang/test/SemaCXX/invalid-instantiated-field-decl.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <typename T> +class SmallVectorImpl  { +public: +  explicit SmallVectorImpl(unsigned N) { +  } + +  ~SmallVectorImpl() { } + +}; + +template <typename T, unsigned N> +class SmallVector : public SmallVectorImpl<T> { +  typedef typename SmallVectorImpl<T>::U U; // expected-error {{no type named 'U' in 'SmallVectorImpl<CallSite>'}} +  enum { + +    MinUs = (static_cast<unsigned int>(sizeof(T))*N +	// expected-error {{invalid application of 'sizeof' to an incomplete type 'CallSite'}} +             static_cast<unsigned int>(sizeof(U)) - 1) / +            static_cast<unsigned int>(sizeof(U)), +    NumInlineEltsElts = MinUs  +  }; +  U InlineElts[NumInlineEltsElts]; +public: +  SmallVector() : SmallVectorImpl<T>(NumInlineEltsElts) { +  } + +}; + +class CallSite;	// expected-note {{forward declaration of 'CallSite'}} +class InlineFunctionInfo { +public: +  explicit InlineFunctionInfo() {} +  SmallVector<CallSite, 2> DevirtualizedCalls;	// expected-note {{in instantiation of template class 'SmallVector<CallSite, 2>' requested}} +}; diff --git a/clang/test/SemaCXX/invalid-member-expr.cpp b/clang/test/SemaCXX/invalid-member-expr.cpp new file mode 100644 index 0000000..287d9af --- /dev/null +++ b/clang/test/SemaCXX/invalid-member-expr.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X {}; + +void test() { +  X x; + +  x.int; // expected-error{{expected unqualified-id}} +  x.~int(); // expected-error{{expected a class name}} +  x.operator; // expected-error{{expected a type}} +  x.operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}} +} + +void test2() { +  X *x; + +  x->int; // expected-error{{expected unqualified-id}} +  x->~int(); // expected-error{{expected a class name}} +  x->operator; // expected-error{{expected a type}} +  x->operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}} +} + +// PR6327 +namespace test3 { +  template <class A, class B> struct pair {}; + +  void test0() { +    pair<int, int> z = minmax({}); // expected-error {{expected expression}} +  } + +  struct string { +    class iterator {}; +  }; + +  void test1() { +    string s; +    string::iterator i = s.foo(); // expected-error {{no member named 'foo'}} +  } +} diff --git a/clang/test/SemaCXX/invalid-template-specifier.cpp b/clang/test/SemaCXX/invalid-template-specifier.cpp new file mode 100644 index 0000000..bcd6da7 --- /dev/null +++ b/clang/test/SemaCXX/invalid-template-specifier.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only +// PR4809 +// This test is primarily checking that this doesn't crash, not the particular +// diagnostics. + +const template basic_istream<char>; // expected-error {{expected unqualified-id}} + +namespace S {} +template <class X> class Y { +  void x() { S::template y<char>(1); } // expected-error {{does not refer to a template}} \ +                                       // expected-error {{unqualified-id}} +}; diff --git a/clang/test/SemaCXX/issue547.cpp b/clang/test/SemaCXX/issue547.cpp new file mode 100644 index 0000000..ab03a15 --- /dev/null +++ b/clang/test/SemaCXX/issue547.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> +struct classify_function { +  static const unsigned value = 0; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args...)> { +  static const unsigned value = 1; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args...) const> { +  static const unsigned value = 2; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args...) volatile> { +  static const unsigned value = 3; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args...) const volatile> { +  static const unsigned value = 4; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args......)> { +  static const unsigned value = 5; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args......) const> { +  static const unsigned value = 6; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args......) volatile> { +  static const unsigned value = 7; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args......) const volatile> { +  static const unsigned value = 8; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args......) &&> { +  static const unsigned value = 9; +}; + +template<typename R, typename ...Args> +struct classify_function<R(Args......) const &> { +  static const unsigned value = 10; +}; + +typedef void f0(int) const; +typedef void f1(int, float...) const volatile; +typedef void f2(int, double, ...) &&; +typedef void f3(int, double, ...) const &; + +int check0[classify_function<f0>::value == 2? 1 : -1]; +int check1[classify_function<f1>::value == 8? 1 : -1]; +int check2[classify_function<f2>::value == 9? 1 : -1]; +int check3[classify_function<f3>::value == 10? 1 : -1]; diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp new file mode 100644 index 0000000..e91dee9 --- /dev/null +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s + +namespace std { class type_info; }; + +namespace ExplicitCapture { +  class C { +    int Member; + +    static void Overload(int); +    void Overload(); +    virtual C& Overload(float); + +    void ImplicitThisCapture() { +      [](){(void)Member;}; // expected-error {{'this' cannot be implicitly captured in this context}} +      [&](){(void)Member;}; + +      [this](){(void)Member;}; +      [this]{[this]{};}; +      []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}} +      []{Overload(3);};  +      []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}}  +      []{(void)typeid(Overload());}; +      []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}}  +    } +  }; + +  void f() { +    [this] () {}; // expected-error {{'this' cannot be captured in this context}}  +  } +} + +namespace ReturnDeduction { +  void test() { +    [](){ return 1; };  +    [](){ return 1; };  +    [](){ return ({return 1; 1;}); };  +    [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} \ +    // expected-warning{{omitted result type}} +    []()->int{ return 'c'; return 1; };  +    [](){ return 'c'; return 1; };  // expected-error {{must match previous return type}} +    []() { return; return (void)0; };  +    [](){ return 1; return 1; }; // expected-warning{{omitted result type}} +  } +} + +namespace ImplicitCapture { +  void test() { +    int a = 0; // expected-note 5 {{declared}} +    []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}}   +    [&]() { return a; };  +    [=]() { return a; };  +    [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}}  +    [=]() { return [&]() { return a; }; }; +    []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}  +    []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}  +    []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}}  +    [=]() { return [&a] { return a; }; }; //  + +    const int b = 2; +    []() { return b; };  + +    union { // expected-note {{declared}} +      int c; +      float d; +    }; +    d = 3; +    [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}}  + +    __block int e; // expected-note 3 {{declared}} +    [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}}  +    [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}}  + +    int f[10]; // expected-note {{declared}} +    [&]() { return f[2]; };   +    (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \ +    // expected-note{{lambda expression begins here}} + +    struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}} +    G g; +    [=]() { const G* gg = &g; return gg->a; }; // expected-warning{{omitted result type}} +    [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}}  \ +    // expected-warning{{omitted result type}} +    (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}}  \ +    // expected-warning{{omitted result type}} + +    const int h = a; // expected-note {{declared}} +    []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}  + +    // The exemption for variables which can appear in constant expressions +    // applies only to objects (and not to references). +    // FIXME: This might be a bug in the standard. +    static int i; +    constexpr int &ref_i = i; // expected-note {{declared}} +    [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} +  } +} + +namespace PR12031 { +  struct X { +    template<typename T> +    X(const T&); +    ~X(); +  }; + +  void f(int i, X x); +  void g() { +    const int v = 10; +    f(v, [](){}); +  } +} + +namespace NullPtr { +  int &f(int *p); +  char &f(...); +  void g() { +    int n = 0; +    [=] { +      char &k = f(n); // not a null pointer constant +    } (); + +    const int m = 0; +    [=] { +      int &k = f(m); // a null pointer constant +    } (); + +    [=] () -> bool { +      int &k = f(m); // a null pointer constant +      return &m == 0; +    } (); + +    [m] { +      int &k = f(m); // a null pointer constant +    } (); +  } +} + +void PR12248() +{ +  unsigned int result = 0; +  auto l = [&]() { ++result; }; +} + +namespace ModifyingCapture { +  void test() { +    int n = 0; +    [=] { +      n = 1; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} +    }; +  } +} diff --git a/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp b/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp new file mode 100644 index 0000000..3ac2336 --- /dev/null +++ b/clang/test/SemaCXX/libstdcxx_is_pod_hack.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +// This is a test for an egregious hack in Clang that works around +// issues with GCC's evolution. libstdc++ 4.2.x uses __is_pod as an +// identifier (to declare a struct template like the one below), while +// GCC 4.3 and newer make __is_pod a keyword. Clang treats __is_pod as +// a keyword *unless* it is introduced following the struct keyword. + +template<typename T> +struct __is_pod { +}; + +__is_pod<int> ipi; + +// Ditto for __is_same. +template<typename T> +struct __is_same { +}; + +__is_same<int> isi; + +// Another, similar egregious hack for __is_signed, which is a type +// trait in Embarcadero's compiler but is used as an identifier in +// libstdc++. +struct test_is_signed { +  static const bool __is_signed = true; +}; + +bool check_signed = test_is_signed::__is_signed; + +#if __has_feature(is_pod) +#  error __is_pod won't work now anyway +#endif diff --git a/clang/test/SemaCXX/libstdcxx_map_base_hack.cpp b/clang/test/SemaCXX/libstdcxx_map_base_hack.cpp new file mode 100644 index 0000000..a556281 --- /dev/null +++ b/clang/test/SemaCXX/libstdcxx_map_base_hack.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +// libstdc++ 4.2.x contains a bug where a friend struct template +// declaration for std::tr1::__detail::_Map base has different +// template arguments than the real declaration. Clang has an +// egregious hack to work around this problem, since we can't modify +// all of the world's libstdc++'s. + +namespace std { namespace tr1 { namespace __detail { +  template<typename _Key, typename _Value, typename _Ex, bool __unique, +	   typename _Hashtable> +    struct _Map_base { }; + +} } }  + +namespace std { namespace tr1 { +  template<typename T> +  struct X1 { +    template<typename _Key2, typename _Pair, typename _Hashtable> +    friend struct __detail::_Map_base; +  }; + +} } + +std::tr1::X1<int> x1i; diff --git a/clang/test/SemaCXX/linkage-spec.cpp b/clang/test/SemaCXX/linkage-spec.cpp new file mode 100644 index 0000000..cb7e32c --- /dev/null +++ b/clang/test/SemaCXX/linkage-spec.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +extern "C" { +  extern "C" void f(int); +} + +extern "C++" { +  extern "C++" int& g(int); +  float& g(); +} +double& g(double); + +void test(int x, double d) { +  f(x); +  float &f1 = g(); +  int& i1 = g(x); +  double& d1 = g(d); +} + +extern "C" int foo; +extern "C" int foo; + +extern "C" const int bar; +extern "C" int const bar; + +// <rdar://problem/6895431> +extern "C" struct bar d; +extern struct bar e; + +extern "C++" { +  namespace N0 { +    struct X0 { +      int foo(int x) { return x; } +    }; +  } +} + +// PR5430 +namespace pr5430 { +  extern "C" void func(void); +} +using namespace pr5430; +extern "C" void pr5430::func(void) { } + +// PR5404 +int f2(char *) +{ +        return 0; +} + +extern "C" +{ +    int f2(int) +    { +        return f2((char *)0); +    } +} + +// PR6991 +extern "C" typedef int (*PutcFunc_t)(int); + + +// PR7859 +extern "C" void pr7859_a(int) {} // expected-note {{previous definition}} +extern "C" void pr7859_a(int) {} // expected-error {{redefinition}} + +extern "C" void pr7859_b() {} // expected-note {{previous definition}} +extern "C" void pr7859_b(int) {} // expected-error {{conflicting}} + +extern "C" void pr7859_c(short) {} // expected-note {{previous definition}} +extern "C" void pr7859_c(int) {} // expected-error {{conflicting}} + +// <rdar://problem/8318976> +extern "C" { +  struct s0 { +  private: +    s0(); +    s0(const s0 &); +  }; +} + +//PR7754 +extern "C++" template <class T> int pr7754(T param); + +namespace N { +  int value; +} + +extern "C++" using N::value; + +// PR7076 +extern "C" const char *Version_string = "2.9"; + +namespace PR9162 { +  extern "C" { +    typedef struct _ArtsSink ArtsSink; +    struct _ArtsSink { +      int sink; +    }; +  } +  int arts_sink_get_type() +  { +    return sizeof(ArtsSink); +  } +} diff --git a/clang/test/SemaCXX/linkage.cpp b/clang/test/SemaCXX/linkage.cpp new file mode 100644 index 0000000..6b73d59 --- /dev/null +++ b/clang/test/SemaCXX/linkage.cpp @@ -0,0 +1,96 @@ +// This is an IR generation test because the calculation of visibility +// during IR gen will cause linkage to be implicitly recomputed and +// compared against the earlier cached value.  If we had a way of +// testing linkage directly in Sema, that would be better. + +// RUN: %clang_cc1 -Werror -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s + +// PR8926 +namespace test0 { +  typedef struct { +    void *foo() { return 0; } +  } A; + +  // CHECK: define linkonce_odr i8* @_ZN5test01A3fooEv( + +  void test(A *a) { +    a->foo(); +  } +} + +namespace test1 { +  typedef struct { +    template <unsigned n> void *foo() { return 0; } + +    void foo() { +      foo<0>(); +    } +  } A; + +  // CHECK: define linkonce_odr void @_ZN5test11A3fooEv( +  // another at the end + +  void test(A *a) { +    a->foo(); +  } +} + +namespace test2 { +  typedef struct { +    template <unsigned n> struct B { +      void *foo() { return 0; } +    }; + +    void foo(B<0> *b) { +      b->foo(); +    } +  } A; + +  // CHECK: define linkonce_odr void @_ZN5test21A3fooEPNS0_1BILj0EEE( + +  void test(A *a) { +    a->foo(0); +  } +} + +namespace test3 { +  namespace { struct A {}; } + +  // CHECK: define internal void @_ZN5test34testENS_12_GLOBAL__N_11AE( +  void test(A a) {} +  void force() { test(A()); } + +  // CHECK: define void @test3( +  extern "C" void test3(A a) {} +} + +namespace { +  // CHECK: define void @test4( +  extern "C" void test4(void) {} +} + +// PR9316: Ensure that even non-namespace-scope function declarations in +// a C declaration context respect that over the anonymous namespace. +extern "C" { +  namespace { +    struct X { +      int f() { +        extern int g(); +        extern int a; + +        // Test both for mangling in the code generation and warnings from use +        // of internal, undefined names via -Werror. +        // CHECK: call i32 @g( +        // CHECK: load i32* @a, +        return g() + a; +      } +    }; +  } +  // Force the above function to be emitted by codegen. +  int test(X& x) { +    return x.f(); +  } +} + +// CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv( +// CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv( diff --git a/clang/test/SemaCXX/literal-operators.cpp b/clang/test/SemaCXX/literal-operators.cpp new file mode 100644 index 0000000..7f68cd3 --- /dev/null +++ b/clang/test/SemaCXX/literal-operators.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +#include <stddef.h> + +struct tag { +  void operator "" _tag_bad (const char *); // expected-error {{literal operator 'operator "" _tag_bad' must be in a namespace or global scope}} +  friend void operator "" _tag_good (const char *); +}; + +namespace ns { void operator "" _ns_good (const char *); } + +// Check extern "C++" declarations +extern "C++" void operator "" _extern_good (const char *); +extern "C++" { void operator "" _extern_good (const char *); } + +void fn () { void operator "" _fn_good (const char *); } + +// One-param declarations (const char * was already checked) +void operator "" _good (char); +void operator "" _good (wchar_t); +void operator "" _good (char16_t); +void operator "" _good (char32_t); +void operator "" _good (unsigned long long); +void operator "" _good (long double); + +// Two-param declarations +void operator "" _good (const char *, size_t); +void operator "" _good (const wchar_t *, size_t); +void operator "" _good (const char16_t *, size_t); +void operator "" _good (const char32_t *, size_t); + +// Check typedef and array equivalences +void operator "" _good (const char[]); +typedef const char c; +void operator "" _good (c*); + +// Check extra cv-qualifiers +void operator "" _cv_good (volatile const char *, const size_t); // expected-error {{parameter declaration for literal operator 'operator "" _cv_good' is not valid}} + +// Template declaration +template <char...> void operator "" _good (); + +// FIXME: Test some invalid decls that might crop up. diff --git a/clang/test/SemaCXX/literal-type.cpp b/clang/test/SemaCXX/literal-type.cpp new file mode 100644 index 0000000..14a4094 --- /dev/null +++ b/clang/test/SemaCXX/literal-type.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +static_assert(__is_literal(int), "fail"); +static_assert(__is_literal_type(int), "fail"); // alternate spelling for GCC +static_assert(__is_literal(void*), "fail"); +enum E { E1 }; +static_assert(__is_literal(E), "fail"); +static_assert(__is_literal(decltype(E1)), "fail"); +typedef int IAR[10]; +static_assert(__is_literal(IAR), "fail"); +typedef int Vector __attribute__((vector_size(16))); +typedef int VectorExt __attribute__((ext_vector_type(4))); +static_assert(__is_literal(Vector), "fail"); +static_assert(__is_literal(VectorExt), "fail"); + +// C++0x [basic.types]p10: +//   A type is a literal type if it is: +//    [...] +//    -- a class type that has all of the following properties: +//        -- it has a trivial destructor +//        -- every constructor call and full-expression in the +//           brace-or-equal-initializers for non-static data members (if an) is +//           a constant expression, +//        -- it is an aggregate type or has at least one constexpr constructor +//           or constructor template that is not a copy or move constructor, and +//           [DR1452 adds class types with trivial default constructors to +//            this list] +//        -- it has all non-static data members and base classes of literal +//           types +struct Empty {}; +struct LiteralType { +  int x; +  E e; +  IAR arr; +  Empty empty; +  int method(); +}; +struct HasDtor { ~HasDtor(); }; + +class NonAggregate { int x; }; +struct NonLiteral { NonLiteral(); }; +struct HasNonLiteralBase : NonLiteral {}; +struct HasNonLiteralMember { HasDtor x; }; + +static_assert(__is_literal(Empty), "fail"); +static_assert(__is_literal(LiteralType), "fail"); +static_assert(__is_literal(NonAggregate), "fail"); +static_assert(!__is_literal(NonLiteral), "fail"); +static_assert(!__is_literal(HasDtor), "fail"); +static_assert(!__is_literal(HasNonLiteralBase), "fail"); +static_assert(!__is_literal(HasNonLiteralMember), "fail"); + +// DR1361 removes the brace-or-equal-initializer bullet so that we can allow: +extern int f(); // expected-note {{here}} +struct HasNonConstExprMemInit { +  int x = f(); // expected-note {{non-constexpr function}} +  constexpr HasNonConstExprMemInit() {} // expected-error {{never produces a constant expression}} +  constexpr HasNonConstExprMemInit(int y) : x(y) {} // ok +}; +static_assert(__is_literal(HasNonConstExprMemInit), "fail"); + +class HasConstExprCtor { +  int x; +public: +  constexpr HasConstExprCtor(int x) : x(x) {} +}; +template <typename T> class HasConstExprCtorTemplate { +  T x; +public: +  template <typename U> constexpr HasConstExprCtorTemplate(U y) : x(y) {} +}; +template <typename T> class HasConstExprCtorT { +  constexpr HasConstExprCtorT(T) {} +}; +static_assert(__is_literal(HasConstExprCtor), "fail"); +static_assert(__is_literal(HasConstExprCtorTemplate<int>), "fail"); +static_assert(__is_literal(HasConstExprCtorT<NonLiteral>), "fail"); diff --git a/clang/test/SemaCXX/local-classes.cpp b/clang/test/SemaCXX/local-classes.cpp new file mode 100644 index 0000000..500b219 --- /dev/null +++ b/clang/test/SemaCXX/local-classes.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR6382 { +  int foo() +  { +    goto error; +    { +      struct BitPacker { +        BitPacker() {} +      }; +      BitPacker packer; +    } + +  error: +    return -1; +  } +} + +namespace PR6383 { +  void test (bool gross) +  { +    struct compare_and_set +    { +      void operator() (const bool inner, const bool gross = false) +      { +        // the code +      } +    } compare_and_set2; + +    compare_and_set2 (false, gross); +  } +} + +namespace Templates { +  template<int Value> +  void f() { +    struct Inner { +      static int getValue() { return Value; } +    }; +  } +} diff --git a/clang/test/SemaCXX/lookup-member.cpp b/clang/test/SemaCXX/lookup-member.cpp new file mode 100644 index 0000000..c75b185 --- /dev/null +++ b/clang/test/SemaCXX/lookup-member.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { +  class String; +}; + +using A::String; +class String; + +// rdar://8603569 +union value { +char *String; +}; diff --git a/clang/test/SemaCXX/member-class-11.cpp b/clang/test/SemaCXX/member-class-11.cpp new file mode 100644 index 0000000..c230c53 --- /dev/null +++ b/clang/test/SemaCXX/member-class-11.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct rdar9677163 { +  struct Y { ~Y(); }; +  struct Z { ~Z(); }; +  Y::~Y() { } // expected-error{{non-friend class member '~Y' cannot have a qualified name}} +  ~Z(); // expected-error{{expected the class name after '~' to name the enclosing class}} +}; diff --git a/clang/test/SemaCXX/member-expr-anonymous-union.cpp b/clang/test/SemaCXX/member-expr-anonymous-union.cpp new file mode 100644 index 0000000..6e35eb2 --- /dev/null +++ b/clang/test/SemaCXX/member-expr-anonymous-union.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +// PR5543 + +struct A { int x; union { int* y; float* z; }; }; struct B : A {int a;}; +int* a(B* x) { return x->y; } + +struct x { union { int y; }; }; x y; template <int X> int f() { return X+y.y; } +int g() { return f<2>(); } + diff --git a/clang/test/SemaCXX/member-expr-static.cpp b/clang/test/SemaCXX/member-expr-static.cpp new file mode 100644 index 0000000..7ed60f7 --- /dev/null +++ b/clang/test/SemaCXX/member-expr-static.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +typedef void (*thread_continue_t)(); + +extern "C" { +  extern void kernel_thread_start(thread_continue_t continuation); +  extern void pure_c(void); +} + +class _IOConfigThread { +public: +  static void main( void ); +}; + + +void foo( void ) { +  kernel_thread_start(&_IOConfigThread::main); +  kernel_thread_start((thread_continue_t)&_IOConfigThread::main); +  kernel_thread_start(&pure_c); +} diff --git a/clang/test/SemaCXX/member-expr.cpp b/clang/test/SemaCXX/member-expr.cpp new file mode 100644 index 0000000..dbddd1c --- /dev/null +++ b/clang/test/SemaCXX/member-expr.cpp @@ -0,0 +1,159 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X{ +public: +  enum E {Enumerator}; // expected-note 2{{declared here}} +  int f(); +  static int mem; +  static float g(); +}; + +void test(X* xp, X x) { +  int i1 = x.f(); +  int i2 = xp->f(); +  x.E; // expected-error{{cannot refer to type member 'E' in 'X' with '.'}} +  xp->E; // expected-error{{cannot refer to type member 'E' in 'X' with '->'}} +  int i3 = x.Enumerator; +  int i4 = xp->Enumerator; +  x.mem = 1; +  xp->mem = 2; +  float f1 = x.g(); +  float f2 = xp->g(); +} + +struct A { + int f0; +}; +struct B { + A *f0(); +}; +int f0(B *b) { +  return b->f0->f0; // expected-error{{did you mean to call it with no arguments}} +} + +int i; + +namespace C { +  int i; +} + +void test2(X *xp) { +  xp->::i = 7; // expected-error{{qualified member access refers to a member in the global namespace}} +  xp->C::i = 7; // expected-error{{qualified member access refers to a member in namespace 'C'}} +} + + +namespace test3 { +  struct NamespaceDecl; + +  struct NamedDecl { +    void *getIdentifier() const; +  }; + +  struct NamespaceDecl : NamedDecl { +    bool isAnonymousNamespace() const { +      return !getIdentifier(); +    } +  }; +} + +namespace test4 { +  class X { +  protected: +    template<typename T> void f(T); +  }; + +  class Y : public X { +  public: +    using X::f; +  }; + +  void test_f(Y y) { +    y.f(17); +  } +} + +namespace test5 { +  struct A { +    template <class T> void foo(); +  }; + +  void test0(int x) { +    x.A::foo<int>(); // expected-error {{'int' is not a structure or union}} +  } + +  void test1(A *x) { +    x.A::foo<int>(); // expected-error {{'test5::A *' is a pointer}} +  } + +  void test2(A &x) { +    x->A::foo<int>(); // expected-error {{'test5::A' is not a pointer}} +  } +} + +namespace PR7508 { +  struct A { +    struct CleanupScope {}; +    void PopCleanupBlock(); // expected-note{{'PopCleanupBlock' declared here}} +  }; + +  void foo(A &a) { +    a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'; did you mean 'PopCleanupBlock'?}} +  } +} + +namespace rdar8231724 { +  namespace N { +    template<typename T> struct X1; +    int i; +  } + +  struct X { }; +  struct Y : X { }; + +  void f(Y *y) { +    y->N::X1<int>; // expected-error{{'rdar8231724::N::X1' is not a member of class 'rdar8231724::Y'}} +  } +} + +namespace PR9025 { +  struct S { int x; }; +  S fun(); // expected-note{{possible target for call}} +  int fun(int i); // expected-note{{possible target for call}} +  int g() { +    return fun.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} +  } + +  S fun2(); // expected-note{{possible target for call}} +  S fun2(int i); // expected-note{{possible target for call}} +  int g2() { +    return fun2.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} +  } + +  S fun3(int i=0); // expected-note{{possible target for call}} +  int fun3(int i, int j); // expected-note{{possible target for call}} +  int g3() { +    return fun3.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} +  } + +  template <typename T> S fun4(); // expected-note{{possible target for call}} +  int g4() { +    return fun4.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +  } + +  S fun5(int i); // expected-note{{possible target for call}} +  S fun5(float f); // expected-note{{possible target for call}} +  int g5() { +    return fun5.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +  } +} + +namespace FuncInMemberExpr { +  struct Vec { int size(); }; +  Vec fun1(); +  int test1() { return fun1.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} +  Vec *fun2(); +  int test2() { return fun2->size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} +  Vec fun3(int x = 0); +  int test3() { return fun3.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} +} diff --git a/clang/test/SemaCXX/member-init.cpp b/clang/test/SemaCXX/member-init.cpp new file mode 100644 index 0000000..c93c85b --- /dev/null +++ b/clang/test/SemaCXX/member-init.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s + +struct Bitfield { +  int n : 3 = 7; // expected-error {{bitfield member cannot have an in-class initializer}} +}; + +int a; +class NoWarning { +  int &n = a; +public: +  int &GetN() { return n; } +}; + +bool b(); +int k; +struct Recurse { +  int &n = b() ? Recurse().n : k; // ok +}; + +struct UnknownBound { +  int as[] = { 1, 2, 3 }; // expected-error {{array bound cannot be deduced from an in-class initializer}} +  int bs[4] = { 4, 5, 6, 7 }; +  int cs[] = { 8, 9, 10 }; // expected-error {{array bound cannot be deduced from an in-class initializer}} +}; + +template<int n> struct T { static const int B; }; +template<> struct T<2> { template<int C, int D> using B = int; }; +const int C = 0, D = 0; +struct S { +  int as[] = { decltype(x)::B<C, D>(0) }; // expected-error {{array bound cannot be deduced from an in-class initializer}} +  T<sizeof(as) / sizeof(int)> x; // expected-error {{requires a type specifier}} +  // test that we handle invalid array bound deductions without crashing when the declarator name is itself invalid +  operator int[](){}; // expected-error {{'operator int' cannot be the name of a variable or data member}} \ +                      // expected-error {{array bound cannot be deduced from an in-class initializer}} +}; + +struct ThrowCtor { ThrowCtor(int) noexcept(false); }; +struct NoThrowCtor { NoThrowCtor(int) noexcept(true); }; + +struct Throw { ThrowCtor tc = 42; }; +struct NoThrow { NoThrowCtor tc = 42; }; + +static_assert(!noexcept(Throw()), "incorrect exception specification"); +static_assert(noexcept(NoThrow()), "incorrect exception specification"); + +struct CheckExcSpec { +  CheckExcSpec() noexcept(true) = default; +  int n = 0; +}; +struct CheckExcSpecFail { +  CheckExcSpecFail() noexcept(true) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} +  ThrowCtor tc = 123; +}; + +struct TypedefInit { +  typedef int A = 0; // expected-error {{illegal initializer}} +}; + +// PR10578 / <rdar://problem/9877267> +namespace PR10578 { +  template<typename T> +  struct X {  +    X() { +      T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} +    } +  }; + +  struct Y : X<int> { +    Y(); +  }; + +  Y::Y() try { // expected-note{{in instantiation of member function 'PR10578::X<int>::X' requested here}} +  } catch(...) { +  } +} diff --git a/clang/test/SemaCXX/member-location.cpp b/clang/test/SemaCXX/member-location.cpp new file mode 100644 index 0000000..6f7e1f5 --- /dev/null +++ b/clang/test/SemaCXX/member-location.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR4103: Make sure we have a location for the error +class A {  +  float a(int *); // expected-note{{passing argument to parameter here}} +  int b();  +}; +int A::b() { return a(a((int*)0)); } // expected-error {{cannot initialize a parameter of type 'int *' with an rvalue of type 'float'}} + diff --git a/clang/test/SemaCXX/member-name-lookup.cpp b/clang/test/SemaCXX/member-name-lookup.cpp new file mode 100644 index 0000000..0149169 --- /dev/null +++ b/clang/test/SemaCXX/member-name-lookup.cpp @@ -0,0 +1,158 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A {  +  int a;  // expected-note 4{{member found by ambiguous name lookup}} +  static int b; +  static int c; // expected-note 2{{member found by ambiguous name lookup}} + +  enum E { enumerator }; + +  typedef int type; + +  static void f(int); +  void f(float); // expected-note 2{{member found by ambiguous name lookup}} + +  static void static_f(int); +  static void static_f(double); +}; + +struct B : A { +  int d; // expected-note 2{{member found by ambiguous name lookup}} + +  enum E2 { enumerator2 }; + +  enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct C : A { +  int c; // expected-note 2{{member found by ambiguous name lookup}} +  int d; // expected-note 2{{member found by ambiguous name lookup}} + +  enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct D : B, C { +  void test_lookup(); +}; + +void test_lookup(D d) { +  d.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} +  (void)d.b; // okay +  d.c; // expected-error{{member 'c' found in multiple base classes of different types}} +  d.d; // expected-error{{member 'd' found in multiple base classes of different types}} +  d.f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'A':}} +  d.static_f(0); // okay + +  D::E e = D::enumerator; // okay +  D::type t = 0; // okay + +  D::E2 e2 = D::enumerator2; // okay + +  D::E3 e3; // expected-error{{multiple base classes}} +} + +void D::test_lookup() { +  a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} +  (void)b; // okay +  c; // expected-error{{member 'c' found in multiple base classes of different types}} +  d; // expected-error{{member 'd' found in multiple base classes of different types}} +  f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'A':}} +  static_f(0); // okay + +  E e = enumerator; // okay +  type t = 0; // okay + +  E2 e2 = enumerator2; // okay + +  E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} +} + +struct B2 : virtual A { +  int d; // expected-note 2{{member found by ambiguous name lookup}} + +  enum E2 { enumerator2 }; + +  enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}} +}; + +struct C2 : virtual A { +  int c; +  int d; // expected-note 2{{member found by ambiguous name lookup}} + +  enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct D2 : B2, C2 {  +  void test_virtual_lookup(); +}; + +struct F : A { }; +struct G : F, D2 {  +  void test_virtual_lookup(); +}; + +void test_virtual_lookup(D2 d2, G g) { +  (void)d2.a; +  (void)d2.b; +  (void)d2.c; // okay +  d2.d; // expected-error{{member 'd' found in multiple base classes of different types}} +  d2.f(0); // okay +  d2.static_f(0); // okay + +  D2::E e = D2::enumerator; // okay +  D2::type t = 0; // okay + +  D2::E2 e2 = D2::enumerator2; // okay + +  D2::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} + +  g.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} +  g.static_f(0); // okay +} + +void D2::test_virtual_lookup() { +  (void)a; +  (void)b; +  (void)c; // okay +  d; // expected-error{{member 'd' found in multiple base classes of different types}} +  f(0); // okay +  static_f(0); // okay + +  E e = enumerator; // okay +  type t = 0; // okay + +  E2 e2 = enumerator2; // okay + +  E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} +} + +void G::test_virtual_lookup() { +  a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'A':}} +  static_f(0); // okay +} + + +struct HasMemberType1 { +  struct type { }; // expected-note{{member found by ambiguous name lookup}} +}; + +struct HasMemberType2 { +  struct type { }; // expected-note{{member found by ambiguous name lookup}} +}; + +struct HasAnotherMemberType : HasMemberType1, HasMemberType2 {  +  struct type { }; +}; + +struct UsesAmbigMemberType : HasMemberType1, HasMemberType2 { +  type t; // expected-error{{member 'type' found in multiple base classes of different types}} +}; + +struct X0 { +  struct Inner { +    static const int m; +  }; +   +  static const int n = 17; +}; + +const int X0::Inner::m = n; diff --git a/clang/test/SemaCXX/member-operator-expr.cpp b/clang/test/SemaCXX/member-operator-expr.cpp new file mode 100644 index 0000000..ae5f8bb --- /dev/null +++ b/clang/test/SemaCXX/member-operator-expr.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X { +public: +  int operator++(); +  operator int(); +}; + +void test() { +  X x; +  int i; + +  i = x.operator++(); +  i = x.operator int(); +  x.operator--(); // expected-error{{no member named 'operator--'}} +  x.operator float(); // expected-error{{no member named 'operator float'}} +  x.operator; // expected-error{{expected a type}} +} + +void test2() { +  X *x; +  int i; + +  i = x->operator++(); +  i = x->operator int(); +  x->operator--(); // expected-error{{no member named 'operator--'}} +  x->operator float(); // expected-error{{no member named 'operator float'}} +  x->operator; // expected-error{{expected a type}} +} diff --git a/clang/test/SemaCXX/member-pointer-ms.cpp b/clang/test/SemaCXX/member-pointer-ms.cpp new file mode 100644 index 0000000..3b2d0fc --- /dev/null +++ b/clang/test/SemaCXX/member-pointer-ms.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -cxx-abi microsoft -fsyntax-only -verify %s + +// Test that we reject pointers to members of incomplete classes (for now) +struct A; //expected-note{{forward declaration of 'A'}} +int A::*pai1; //expected-error{{incomplete type 'A'}} + +// Test that we don't allow reinterpret_casts from pointers of one size to +// pointers of a different size. +struct A {}; +struct B {}; +struct C: A, B {}; + +void (A::*paf)(); +void (C::*pcf)() = reinterpret_cast<void (C::*)()>(paf); //expected-error{{cannot reinterpret_cast from member pointer type}} diff --git a/clang/test/SemaCXX/member-pointer-size.cpp b/clang/test/SemaCXX/member-pointer-size.cpp new file mode 100644 index 0000000..3aa1eaf --- /dev/null +++ b/clang/test/SemaCXX/member-pointer-size.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify +// RUN: %clang_cc1 -triple i686-unknown-unknown %s -fsyntax-only -verify +#include <stddef.h> + +struct A; + +void f() { +  int A::*dataMember; +   +  int (A::*memberFunction)(); +   +  typedef int assert1[sizeof(dataMember) == sizeof(ptrdiff_t) ? 1 : -1]; +  typedef int assert2[sizeof(memberFunction) == sizeof(ptrdiff_t) * 2 ? 1 : -1]; +} + diff --git a/clang/test/SemaCXX/member-pointer.cpp b/clang/test/SemaCXX/member-pointer.cpp new file mode 100644 index 0000000..4e8b4a8 --- /dev/null +++ b/clang/test/SemaCXX/member-pointer.cpp @@ -0,0 +1,314 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A {}; +enum B { Dummy }; +namespace C {} +struct D : A {}; +struct E : A {}; +struct F : D, E {}; +struct G : virtual D {}; + +int A::*pdi1; +int (::A::*pdi2); +int (A::*pfi)(int); + +int B::*pbi; // expected-error {{expected a class or namespace}} +int C::*pci; // expected-error {{'pci' does not point into a class}} +void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}} +int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}} + +void f() { +  // This requires tentative parsing. +  int (A::*pf)(int, int); + +  // Implicit conversion to bool. +  bool b = pdi1; +  b = pfi; + +  // Conversion from null pointer constant. +  pf = 0; +  pf = __null; + +  // Conversion to member of derived. +  int D::*pdid = pdi1; +  pdid = pdi2; + +  // Fail conversion due to ambiguity and virtuality. +  int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'A' to pointer to member of derived class 'F':}} +  int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'A' to pointer to member of class 'G' via virtual base 'D' is not allowed}} + +  // Conversion to member of base. +  pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}} +   +  // Comparisons +  int (A::*pf2)(int, int); +  int (D::*pf3)(int, int) = 0; +  bool b1 = (pf == pf2); (void)b1; +  bool b2 = (pf != pf2); (void)b2; +  bool b3 = (pf == pf3); (void)b3; +  bool b4 = (pf != 0); (void)b4; +} + +struct TheBase +{ +  void d(); +}; + +struct HasMembers : TheBase +{ +  int i; +  void f(); + +  void g(); +  void g(int); +  static void g(double); +}; + +namespace Fake +{ +  int i; +  void f(); +} + +void g() { +  HasMembers hm; + +  int HasMembers::*pmi = &HasMembers::i; +  int *pni = &Fake::i; +  int *pmii = &hm.i; + +  void (HasMembers::*pmf)() = &HasMembers::f; +  void (*pnf)() = &Fake::f; +  &hm.f; // expected-error {{cannot create a non-constant pointer to member function}} + +  void (HasMembers::*pmgv)() = &HasMembers::g; +  void (HasMembers::*pmgi)(int) = &HasMembers::g; +  void (*pmgd)(double) = &HasMembers::g; + +  void (HasMembers::*pmd)() = &HasMembers::d; +} + +struct Incomplete; + +void h() { +  HasMembers hm, *phm = &hm; + +  int HasMembers::*pi = &HasMembers::i; +  hm.*pi = 0; +  int i = phm->*pi; +  (void)&(hm.*pi); +  (void)&(phm->*pi); +  (void)&((&hm)->*pi);  + +  void (HasMembers::*pf)() = &HasMembers::f; +  (hm.*pf)(); +  (phm->*pf)(); + +  (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'HasMembers'}} +  (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'HasMembers *'}} +  (void)(i.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'int'}} +  int *ptr; +  (void)(ptr->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'int *'}} + +  int A::*pai = 0; +  D d, *pd = &d; +  (void)(d.*pai); +  (void)(pd->*pai); +  F f, *ptrf = &f; +  (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'F'}} +  (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'F *'}} + +  (void)(hm.*i); // expected-error {{pointer-to-member}} +  (void)(phm->*i); // expected-error {{pointer-to-member}} + +  // Okay +  Incomplete *inc; +  int Incomplete::*pii = 0; +  (void)(inc->*pii); +} + +struct OverloadsPtrMem +{ +  int operator ->*(const char *); +}; + +void i() { +  OverloadsPtrMem m; +  int foo = m->*"Awesome!"; +} + +namespace pr5985 { +  struct c { +    void h(); +    void f() { +      void (c::*p)(); +      p = &h; // expected-error {{must explicitly qualify}} +      p = &this->h; // expected-error {{cannot create a non-constant pointer to member function}} +      p = &(*this).h; // expected-error {{cannot create a non-constant pointer to member function}} +    } +  }; +} + +namespace pr6783 { +  struct Base {}; +  struct X; // expected-note {{forward declaration}} + +  int test1(int Base::* p2m, X* object) +  { +    return object->*p2m; // expected-error {{left hand operand to ->*}} +  } +} + +namespace PR7176 { +  namespace base +  { +    struct Process +    { }; +    struct Continuous : Process +    { +      bool cond(); +    }; +  } + +  typedef bool( base::Process::*Condition )(); + +  void m() +  { (void)(Condition) &base::Continuous::cond; } +} + +namespace rdar8358512 { +  // We can't call this with an overload set because we're not allowed +  // to look into overload sets unless the parameter has some kind of +  // function type. +  template <class F> void bind(F f); // expected-note 12 {{candidate template ignored}} +  template <class F, class T> void bindmem(F (T::*f)()); // expected-note 4 {{candidate template ignored}} +  template <class F> void bindfn(F (*f)()); // expected-note 4 {{candidate template ignored}} + +  struct A { +    void nonstat(); +    void nonstat(int); + +    void mixed(); +    static void mixed(int); + +    static void stat(); +    static void stat(int); +     +    template <typename T> struct Test0 { +      void test() { +        bind(&nonstat); // expected-error {{no matching function for call}} +        bind(&A::nonstat); // expected-error {{no matching function for call}} + +        bind(&mixed); // expected-error {{no matching function for call}} +        bind(&A::mixed); // expected-error {{no matching function for call}} + +        bind(&stat); // expected-error {{no matching function for call}} +        bind(&A::stat); // expected-error {{no matching function for call}} +      } +    }; + +    template <typename T> struct Test1 { +      void test() { +        bindmem(&nonstat); // expected-error {{no matching function for call}} +        bindmem(&A::nonstat); + +        bindmem(&mixed); // expected-error {{no matching function for call}} +        bindmem(&A::mixed); + +        bindmem(&stat); // expected-error {{no matching function for call}} +        bindmem(&A::stat); // expected-error {{no matching function for call}} +      } +    }; + +    template <typename T> struct Test2 { +      void test() { +        bindfn(&nonstat); // expected-error {{no matching function for call}} +        bindfn(&A::nonstat); // expected-error {{no matching function for call}} + +        bindfn(&mixed); // expected-error {{no matching function for call}} +        bindfn(&A::mixed); // expected-error {{no matching function for call}} + +        bindfn(&stat); +        bindfn(&A::stat); +      } +    }; +  }; + +  template <class T> class B { +    void nonstat(); +    void nonstat(int); + +    void mixed(); +    static void mixed(int); + +    static void stat(); +    static void stat(int); + +    // None of these can be diagnosed yet, because the arguments are +    // still dependent. +    void test0a() { +      bind(&nonstat); +      bind(&B::nonstat); + +      bind(&mixed); +      bind(&B::mixed); + +      bind(&stat); +      bind(&B::stat); +    } + +    void test0b() { +      bind(&nonstat); // expected-error {{no matching function for call}} +      bind(&B::nonstat); // expected-error {{no matching function for call}} + +      bind(&mixed); // expected-error {{no matching function for call}} +      bind(&B::mixed); // expected-error {{no matching function for call}} + +      bind(&stat); // expected-error {{no matching function for call}} +      bind(&B::stat); // expected-error {{no matching function for call}} +    } +  }; + +  template void B<int>::test0b(); // expected-note {{in instantiation}} +} + +namespace PR9973 { +  template<class R, class T> struct dm +  { +    typedef R T::*F; +    F f_; +    template<class U> int & call(U u) +    { return u->*f_; } // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} + +    template<class U> int operator()(U u) +    { call(u); } // expected-note{{in instantiation of}} +  }; + +  template<class R, class T>  +  dm<R, T> mem_fn(R T::*) ; + +  struct test +  { int nullary_v(); }; + +  void f() +  { +    test* t; +    mem_fn(&test::nullary_v)(t); // expected-note{{in instantiation of}} +  } +} + +namespace test8 { +  struct A { int foo; }; +  int test1() { +    // Verify that we perform (and check) an lvalue conversion on the operands here. +    return (*((A**) 0)) // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}} +             ->**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}} +  } + +  int test2() { +    // Verify that we perform (and check) an lvalue conversion on the operands here. +    // TODO: the .* should itself warn about being a dereference of null. +    return (*((A*) 0)) +             .**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}} +  } +} diff --git a/clang/test/SemaCXX/member-pointers-2.cpp b/clang/test/SemaCXX/member-pointers-2.cpp new file mode 100644 index 0000000..6c39282 --- /dev/null +++ b/clang/test/SemaCXX/member-pointers-2.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -emit-llvm-only %s + +// Tests that Sema properly creates member-access expressions for +// these instead of bare FieldDecls. + +struct Foo { +  int myvalue; + +  // We have to override these to get something with an lvalue result. +  int &operator++(int); +  int &operator--(int); +}; + +struct Test0 { +  Foo memfoo; +  int memint; +  int memarr[10]; +  Test0 *memptr; +  struct MemClass { int a; } memstruct; +  int &memfun(); +   +  void test() { +    int *p; +    p = &Test0::memfoo++; +    p = &Test0::memfoo--; +    p = &Test0::memarr[1]; +    p = &Test0::memptr->memint; +    p = &Test0::memstruct.a; +    p = &Test0::memfun(); +  } +}; + +void test0() { +  Test0 mytest; +  mytest.test(); +} + +namespace rdar9065289 { +  typedef void (*FuncPtr)(); +  struct X0 { }; + +  struct X1 +  { +    X0* x0; +    FuncPtr X0::*fptr; +  }; + +  void f(X1 p) { +    (p.x0->*(p.fptr))(); +  } +} diff --git a/clang/test/SemaCXX/microsoft-cxx0x.cpp b/clang/test/SemaCXX/microsoft-cxx0x.cpp new file mode 100644 index 0000000..3b9bbef --- /dev/null +++ b/clang/test/SemaCXX/microsoft-cxx0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++11-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11 + + +struct A { +     unsigned int a; +}; +int b = 3; +A var = {  b }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} diff --git a/clang/test/SemaCXX/missing-header.cpp b/clang/test/SemaCXX/missing-header.cpp new file mode 100644 index 0000000..5b3915b --- /dev/null +++ b/clang/test/SemaCXX/missing-header.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#include "not exist" // expected-error{{'not exist' file not found}} + +class AnalysisDeclContext {}; +static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { +  if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {} +  bool NoReturnEdge = false; +} diff --git a/clang/test/SemaCXX/missing-members.cpp b/clang/test/SemaCXX/missing-members.cpp new file mode 100644 index 0000000..529ba10 --- /dev/null +++ b/clang/test/SemaCXX/missing-members.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace A { +  namespace B { +    class C { }; +    struct S { }; +    union U { }; +  } +} + +void f() { +  A::B::i; // expected-error {{no member named 'i' in namespace 'A::B'}} +  A::B::C::i; // expected-error {{no member named 'i' in 'A::B::C'}} +  ::i; // expected-error {{no member named 'i' in the global namespace}} +} + +namespace B { +  class B { }; +} + +void g() { +  A::B::D::E; // expected-error {{no member named 'D' in namespace 'A::B'}} +  B::B::C::D; // expected-error {{no member named 'C' in 'B::B'}} +  ::C::D; // expected-error {{no member named 'C' in the global namespace}} +} + +int A::B::i = 10; // expected-error {{no member named 'i' in namespace 'A::B'}} +int A::B::C::i = 10; // expected-error {{no member named 'i' in 'A::B::C'}} +int A::B::S::i = 10; // expected-error {{no member named 'i' in 'A::B::S'}} +int A::B::U::i = 10; // expected-error {{no member named 'i' in 'A::B::U'}} + +using A::B::D; // expected-error {{no member named 'D' in namespace 'A::B'}} + +struct S : A::B::C {  +  using A::B::C::f; // expected-error {{no member named 'f' in 'A::B::C'}} +   +}; diff --git a/clang/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/clang/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp new file mode 100644 index 0000000..83f8395 --- /dev/null +++ b/clang/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s + +namespace fizbin { class Foobar {}; } // expected-note 2 {{'fizbin::Foobar' declared here}} \ +                                      // expected-note {{'Foobar' declared here}} +Foobar *my_bar  // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} +    = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} +fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{no type named 'FooBar' in namespace 'fizbin'; did you mean 'Foobar'?}} + +namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}} +int Double(int x) { return x + x; } +void empty() { +  Double(toFoobar()); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}} +} + +namespace fizbin { +  namespace baztool { bool toFoobar() { return true; } } // expected-note{{'fizbin::baztool' declared here}} +  namespace nested { bool moreFoobar() { return true; } } // expected-note{{'fizbin::nested::moreFoobar' declared here}} +  namespace nested { bool lessFoobar() { return true; } } // expected-note{{'fizbin::nested' declared here}} \ +                                                          // expected-note{{'fizbin::nested::lessFoobar' declared here}} +  class dummy { // expected-note 2 {{'fizbin::dummy' declared here}} +   public: +    static bool moreFoobar() { return false; } // expected-note{{'moreFoobar' declared here}} +  }; +} +void Check() { // expected-note{{'Check' declared here}} +  if (toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}} +  if (noFoobar()) Double(7); // expected-error{{use of undeclared identifier 'noFoobar'; did you mean 'barstool::toFoobar'?}} +  if (moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'moreFoobar'; did you mean 'fizbin::nested::moreFoobar'}} +  if (lessFoobar()) Double(7); // expected-error{{use of undeclared identifier 'lessFoobar'; did you mean 'fizbin::nested::lessFoobar'?}} +  if (baztool::toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'baztool'; did you mean 'fizbin::baztool'?}} +  if (nested::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'nested'; did you mean 'fizbin::nested'?}} +  if (dummy::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} +  if (dummy::mreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} \ +                                     // expected-error{{no member named 'mreFoobar' in 'fizbin::dummy'; did you mean 'moreFoobar'?}} +  if (moFoobin()) Double(7); // expected-error{{use of undeclared identifier 'moFoobin'}} +} + +void Alt() { +  Cleck(); // expected-error{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}} +} + +namespace N { +  namespace inner { +    class myvector { /* ... */ }; // expected-note{{'inner::myvector' declared here}} +  } + +  void f() { +    myvector v; // expected-error{{unknown type name 'myvector'; did you mean 'inner::myvector'?}} +  } +} + +namespace realstd { +  inline namespace __1 { +    class mylinkedlist { /* ... */ }; // expected-note 2 {{'realstd::mylinkedlist' declared here}} +  } + +  class linkedlist { /* ... */ }; +} + +void f() { +  mylinkedlist v; // expected-error{{unknown type name 'mylinkedlist'; did you mean 'realstd::mylinkedlist'?}} +  nylinkedlist w; // expected-error{{unknown type name 'nylinkedlist'; did you mean 'realstd::mylinkedlist'?}} +} + +// Test case from http://llvm.org/bugs/show_bug.cgi?id=10318 +namespace llvm { + template <typename T> class GraphWriter {}; // expected-note 3{{declared here}} +} + +struct S {}; +void bar() { + GraphWriter<S> x; //expected-error{{no template named 'GraphWriter'; did you mean 'llvm::GraphWriter'?}} + (void)new llvm::GraphWriter; // expected-error {{use of class template llvm::GraphWriter requires template arguments}} + (void)new llvm::Graphwriter<S>; // expected-error {{no template named 'Graphwriter' in namespace 'llvm'; did you mean 'GraphWriter'?}} +} + +// If namespace prefixes and character edits have the same weight, correcting +// "fimish" to "N::famish" would have the same edit distance as correcting +// "fimish" to "Finish". The result would be no correction being suggested +// unless one of the corrections is given precedence (e.g. by filtering out +// suggestions with added namespace qualifiers). +namespace N { void famish(int); } +void Finish(int); // expected-note {{'Finish' declared here}} +void Start() { +  fimish(7); // expected-error {{use of undeclared identifier 'fimish'; did you mean 'Finish'?}} +} + +// But just eliminating the corrections containing added namespace qualifiers +// won't work if both of the tied corrections have namespace qualifiers added. +namespace N { +void someCheck(int); // expected-note {{'N::someCheck' declared here}} +namespace O { void somechock(int); } +} +void confusing() { +  somechick(7); // expected-error {{use of undeclared identifier 'somechick'; did you mean 'N::someCheck'?}} +} + + +class Message {}; +namespace extra { +  namespace util { +    namespace MessageUtils { +      bool Equivalent(const Message&, const Message&); // expected-note {{'extra::util::MessageUtils::Equivalent' declared here}} \ +                                                       // expected-note {{'::extra::util::MessageUtils::Equivalent' declared here}} +    } +  } +} +namespace util { namespace MessageUtils {} } +bool nstest () { +  Message a, b; +  return util::MessageUtils::Equivalent(a, b); // expected-error {{no member named 'Equivalent' in namespace 'util::MessageUtils'; did you mean 'extra::util::MessageUtils::Equivalent'?}} +} + +namespace util { +  namespace extra { +    bool nstest () { +      Message a, b; +      return MessageUtils::Equivalent(a, b); // expected-error {{no member named 'Equivalent' in namespace 'util::MessageUtils'; did you mean '::extra::util::MessageUtils::Equivalent'?}} +    } +  } +} diff --git a/clang/test/SemaCXX/ms-exception-spec.cpp b/clang/test/SemaCXX/ms-exception-spec.cpp new file mode 100644 index 0000000..bda56f5 --- /dev/null +++ b/clang/test/SemaCXX/ms-exception-spec.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions + +void f() throw(...) { } diff --git a/clang/test/SemaCXX/namespace-alias.cpp b/clang/test/SemaCXX/namespace-alias.cpp new file mode 100644 index 0000000..e18b58b --- /dev/null +++ b/clang/test/SemaCXX/namespace-alias.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { struct X { }; }; + +namespace A = N; + +int B; // expected-note {{previous definition is here}} +namespace B = N; // expected-error {{redefinition of 'B' as different kind of symbol}} + +namespace C { } // expected-note {{previous definition is here}} +namespace C = N; // expected-error {{redefinition of 'C'}} + +int i; +namespace D = +i; // expected-error {{expected namespace name}} + +namespace E1 = N:: +Foo; // expected-error {{expected namespace name}} +namespace E2 = N:: +X; // expected-error {{expected namespace name}} + +namespace F { +  namespace A { namespace B { } } // expected-note {{candidate found by name lookup is 'F::A::B'}} +  namespace B { } // expected-note {{candidate found by name lookup is 'F::B'}} +  using namespace A; +  namespace D = B; // expected-error {{reference to 'B' is ambiguous}} +} + +namespace G {  +  namespace B = N; +} + +namespace H { +  namespace A1 { } +  namespace A2 { } + +  // These all point to A1. +  namespace B = A1; // expected-note {{previous definition is here}} +  namespace B = A1; +  namespace C = B; +  namespace B = C; + +  namespace B = A2; // expected-error {{redefinition of 'B' as different kind of symbol}} +} + +namespace I {  +  namespace A1 { int i; } +   +  namespace A2 = A1; +} + +int f() { +  return I::A2::i; +} + +namespace J { +  namespace A {  +    namespace B { void func (); } +  } + +  namespace C = A; + +  using namespace C::B; + +  void g() { +    func(); +  } +} + +namespace K { +  namespace KA { void func(); } + +  void f() { +    namespace KB = KA; +    KB::func(); +  } + +  template <class T> void g() { +    namespace KC = KA; +    KC::func(); +  } +  template void g<int>(); +  template void g<long>(); + +  void h() { +    KB::func(); // expected-error {{undeclared identifier 'KB'}} +    KC::func(); // expected-error {{undeclared identifier 'KC'}} +  } +} + +namespace { +  class C1; +} +namespace { +  class C1; +} +C1 *pc1 = 0; + +namespace N { +  namespace { +    class C2; +  } +} +namespace N { +  namespace { +    class C2; +  } +} +N::C2 *pc2 = 0; + +// PR6341 +namespace A = N; +namespace N { } +namespace A = N; + +A::X nx; + +namespace PR7014 { +  namespace X +  { +    namespace Y {} +  } + +  using namespace X; + +  namespace Y = X::Y; +} diff --git a/clang/test/SemaCXX/namespace.cpp b/clang/test/SemaCXX/namespace.cpp new file mode 100644 index 0000000..d47b707 --- /dev/null +++ b/clang/test/SemaCXX/namespace.cpp @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +namespace A { // expected-note 2 {{previous definition is here}} +  int A; +  void f() { A = 0; } +} + +void f() { A = 0; } // expected-error {{unexpected namespace name 'A': expected expression}} +int A; // expected-error {{redefinition of 'A' as different kind of symbol}} +class A; // expected-error {{redefinition of 'A' as different kind of symbol}} + +class B {}; // expected-note {{previous definition is here}} \ +            // expected-note{{candidate function (the implicit copy assignment operator)}} + +void C(); // expected-note {{previous definition is here}} +namespace C {} // expected-error {{redefinition of 'C' as different kind of symbol}} + +namespace D { +  class D {}; +} + +namespace S1 { +  int x; + +  namespace S2 { + +    namespace S3 { +      B x; +    } +  } +} + +namespace S1 { +  void f() { +    x = 0; +  } + +  namespace S2 { +     +    namespace S3 { +      void f() { +        x = 0; // expected-error {{no viable overloaded '='}} +      } +    } + +    int y; +  } +} + +namespace S1 { +  namespace S2 { +    namespace S3 { +      void f3() { +        y = 0; +      } +    } +  } +} + +namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}} + + +namespace foo { +  enum x { +    Y +  }; +} + +static foo::x  test1;  // ok + +static foo::X  test2;  // typo: expected-error {{no type named 'X' in}} + +namespace PR6620 { +  namespace numeric { +    namespace op { +      struct greater {}; +    } +    namespace { +      extern op::greater const greater; +    } +  } + +  namespace numeric { +    namespace { +      op::greater const greater = op::greater(); +    } + +    template<typename T, typename U> +    int f(T& l, U& r) +    { numeric::greater(l, r); } + +  } +} diff --git a/clang/test/SemaCXX/neon-vector-types.cpp b/clang/test/SemaCXX/neon-vector-types.cpp new file mode 100644 index 0000000..aa82b11 --- /dev/null +++ b/clang/test/SemaCXX/neon-vector-types.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://9208404 + +typedef int MP4Err; +typedef float Float32; +typedef float float32_t; +typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t; +typedef float vFloat __attribute__((__vector_size__(16))); +typedef vFloat VFLOAT; +typedef unsigned long UInt32; + +extern int bar (float32x4_t const *p); + +int foo (const Float32 *realBufPtr) { +  float32x4_t const *vRealPtr = (VFLOAT *)&realBufPtr[0]; +  return bar(vRealPtr); +} + +MP4Err autoCorrelation2nd_Neon(Float32 *alphar, Float32 *alphai, +			    const Float32 *realBufPtr, +			    const Float32 *imagBufPtr, +			    const UInt32 len) +{ +  float32x4_t const *vRealPtr = (VFLOAT *)&realBufPtr[0]; +  return 0; +} + diff --git a/clang/test/SemaCXX/nested-name-spec-locations.cpp b/clang/test/SemaCXX/nested-name-spec-locations.cpp new file mode 100644 index 0000000..048d4ba --- /dev/null +++ b/clang/test/SemaCXX/nested-name-spec-locations.cpp @@ -0,0 +1,162 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Note: the formatting in this test case is intentionally funny, with +// nested-name-specifiers stretched out vertically so that we can +// match up diagnostics per-line and still verify that we're getting +// good source-location information. + +namespace outer { +  namespace inner { +    template<typename T> +    struct X0 { +    }; +  } +} + +template<typename T> +struct add_reference { +  typedef T& type; +}; + +namespace outer_alias = outer; + +template<typename T> +struct UnresolvedUsingValueDeclTester { +  using outer::inner::X0< +          typename add_reference<T>::type  +    * // expected-error{{declared as a pointer to a reference of type}} +        >::value; +}; + +UnresolvedUsingValueDeclTester<int> UnresolvedUsingValueDeclCheck; // expected-note{{in instantiation of template class}} + +template<typename T> +struct UnresolvedUsingTypenameDeclTester { +  using outer::inner::X0< +          typename add_reference<T>::type  +    * // expected-error{{declared as a pointer to a reference of type}} +        >::value; +}; + +UnresolvedUsingTypenameDeclTester<int> UnresolvedUsingTypenameDeclCheck; // expected-note{{in instantiation of template class}} + + +template<typename T, typename U> +struct PseudoDestructorExprTester { +  void f(T *t) { +    t->T::template Inner<typename add_reference<U>::type  +      * // expected-error{{as a pointer to a reference of type}} +      >::Blarg::~Blarg(); +  } +}; + +struct HasInnerTemplate { +  template<typename T> +  struct Inner; + +  typedef HasInnerTemplate T; +}; + +void PseudoDestructorExprCheck( +                    PseudoDestructorExprTester<HasInnerTemplate, float> tester) { +  tester.f(0); // expected-note{{in instantiation of member function}} +} + +template<typename T> +struct DependentScopedDeclRefExpr { +  void f() { +    outer_alias::inner::X0<typename add_reference<T>::type  +      * // expected-error{{as a pointer to a reference of type}} +      >::value = 17; +  } +}; + +void DependentScopedDeclRefExprCheck(DependentScopedDeclRefExpr<int> t) { +  t.f(); // expected-note{{in instantiation of member function}} +} + + +template<typename T> +struct TypenameTypeTester { +  typedef typename outer::inner::X0< +          typename add_reference<T>::type  +    * // expected-error{{declared as a pointer to a reference of type}} +        >::type type; +}; + +TypenameTypeTester<int> TypenameTypeCheck; // expected-note{{in instantiation of template class}} + +template<typename T, typename U> +struct DependentTemplateSpecializationTypeTester { +  typedef typename T::template apply<typename add_reference<U>::type  +                                     * // expected-error{{declared as a pointer to a reference of type}} +                                     >::type type; +}; + +struct HasApply { +  template<typename T> +  struct apply { +    typedef T type; +  }; +}; + +DependentTemplateSpecializationTypeTester<HasApply, int> DTSTCheck; // expected-note{{in instantiation of template class}} + +template<typename T, typename U> +struct DependentTemplateSpecializationTypeTester2 { +  typedef typename T::template apply<typename add_reference<U>::type  +                                     * // expected-error{{declared as a pointer to a reference of type}} +                                     > type; +}; + +DependentTemplateSpecializationTypeTester2<HasApply, int> DTSTCheck2; // expected-note{{in instantiation of template class}} + +template<typename T, typename U> +struct DependentTemplateSpecializationTypeTester3 : +  T::template apply<typename add_reference<U>::type  +                                     * // expected-error{{declared as a pointer to a reference of type}} +                                     > +{}; + +DependentTemplateSpecializationTypeTester3<HasApply, int> DTSTCheck3; // expected-note{{in instantiation of template class}} + +template<typename T, typename U> +struct DependentTemplateSpecializationTypeTester4 { +  typedef class T::template apply<typename add_reference<U>::type  +                                     * // expected-error{{declared as a pointer to a reference of type}} +                                     > type; +}; + +DependentTemplateSpecializationTypeTester4<HasApply, int> DTSTCheck4; // expected-note{{in instantiation of template class}} + +template<template<class T> class TTP> +struct AcceptedTemplateTemplateParameter { +}; + +template<typename T, typename U> +struct DependentTemplateTemplateArgumentTester { +  typedef AcceptedTemplateTemplateParameter< +            T:: +            template apply< +              typename add_reference<U>::type +              * // expected-error{{declared as a pointer to a reference of type}} +            >:: +            template X> +    type; +}; + +DependentTemplateTemplateArgumentTester<HasApply, int> DTTACheck; // expected-note{{in instantiation of template class}} + +namespace PR9388 { +  namespace std { +    template<typename T>     class vector     { +    }; +  } +  template<typename T> static void foo(std::vector<T*> &V) { +    __PRETTY_FUNCTION__; // expected-warning{{expression result unused}} +  } +  void bar(std::vector<int*> &Blocks) { +    foo(Blocks); // expected-note{{in instantiation of}} +  } + +} diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp new file mode 100644 index 0000000..b317634 --- /dev/null +++ b/clang/test/SemaCXX/nested-name-spec.cpp @@ -0,0 +1,288 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s  +namespace A { +  struct C { +    static int cx; + +    static int cx2; + +    static int Ag1(); +    static int Ag2(); +  }; +  int ax; +  void Af(); +} + +A:: ; // expected-error {{expected unqualified-id}} +// FIXME: there is a member 'ax'; it's just not a class. +::A::ax::undef ex3; // expected-error {{no member named 'ax'}} +A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} + +int A::C::Ag1() { return 0; } + +static int A::C::Ag2() { return 0; } // expected-error{{'static' can}} + +int A::C::cx = 17; + + +static int A::C::cx2 = 17; // expected-error{{'static' can}} + +class C2 { +  void m(); // expected-note{{member declaration does not match because it is not const qualified}} + +  void f(const int& parm); // expected-note{{type of 1st parameter of member declaration does not match definition ('const int &' vs 'int')}} +  void f(int) const; // expected-note{{member declaration does not match because it is const qualified}} +  void f(float); + +  int x; +}; + +void C2::m() const { } // expected-error{{out-of-line definition of 'm' does not match any declaration in 'C2'}} + +void C2::f(int) { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'C2'}} + +void C2::m() { +  x = 0; +} + +namespace B { +  void ::A::Af() {} // expected-error {{cannot define or redeclare 'Af' here because namespace 'B' does not enclose namespace 'A'}} +} + +void f1() { +  void A::Af(); // expected-error {{definition or redeclaration of 'Af' not allowed inside a function}} +} + +void f2() { +  A:: ; // expected-error {{expected unqualified-id}} +  A::C::undef = 0; // expected-error {{no member named 'undef'}} +  ::A::C::cx = 0; +  int x = ::A::ax = A::C::cx; +  x = sizeof(A::C); +  x = sizeof(::A::C::cx); +} + +A::C c1; +struct A::C c2; +struct S : public A::C {}; +struct A::undef; // expected-error {{no struct named 'undef' in namespace 'A'}} + +namespace A2 { +  typedef int INT; +  struct RC; +  struct CC { +    struct NC; +  }; +} + +struct A2::RC { +  INT x; +}; + +struct A2::CC::NC { +  void m() {} +}; + +void f3() { +  N::x = 0; // expected-error {{use of undeclared identifier 'N'}} +  int N; +  N::x = 0; // expected-error {{expected a class or namespace}} +  { int A;           A::ax = 0; } +  { typedef int A;   A::ax = 0; } // expected-error{{expected a class or namespace}} +  { typedef A::C A;  A::ax = 0; } // expected-error {{no member named 'ax'}} +  { typedef A::C A;  A::cx = 0; } +} + +// make sure the following doesn't hit any asserts +void f4(undef::C); // expected-error {{use of undeclared identifier 'undef'}} \ +                      expected-error {{variable has incomplete type 'void'}} + +typedef void C2::f5(int); // expected-error{{typedef declarator cannot be qualified}} + +void f6(int A2::RC::x); // expected-error{{parameter declarator cannot be qualified}} + +int A2::RC::x; // expected-error{{non-static data member defined out-of-line}} + +void A2::CC::NC::m(); // expected-error{{out-of-line declaration of a member must be a definition}} + + +namespace E { +  int X = 5; +   +  namespace Nested { +    enum E { +      X = 0 +    }; + +    void f() { +      return E::X; // expected-error{{expected a class or namespace}} +    } +  } +} + + +class Operators { +  Operators operator+(const Operators&) const; // expected-note{{member declaration does not match because it is const qualified}} +  operator bool(); +}; + +Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition of 'operator+' does not match any declaration in 'Operators'}} +  Operators ops; +  return ops; +} + +Operators Operators::operator+(const Operators&) const { +  Operators ops; +  return ops; +} + +Operators::operator bool() { +  return true; +} + +namespace A { +  void g(int&); // expected-note{{type of 1st parameter of member declaration does not match definition ('int &' vs 'const int &')}} +}  + +void A::f() {} // expected-error{{out-of-line definition of 'f' does not match any declaration in namespace 'A'}} + +void A::g(const int&) { } // expected-error{{out-of-line definition of 'g' does not match any declaration in namespace 'A'}} + +struct Struct { }; + +void Struct::f() { } // expected-error{{out-of-line definition of 'f' does not match any declaration in 'Struct'}} + +void global_func(int); +void global_func2(int); + +namespace N { +  void ::global_func(int) { } // expected-error{{definition or redeclaration of 'global_func' cannot name the global scope}} + +  void f(); +  // FIXME: if we move this to a separate definition of N, things break! +} +void ::global_func2(int) { } // expected-warning{{extra qualification on member 'global_func2'}} + +void N::f() { } // okay + +struct Y;  // expected-note{{forward declaration of 'Y'}} +Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}} + +X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \ +      // expected-error{{C++ requires a type specifier for all declarations}} \ +      // expected-error{{only constructors take base initializers}} + +struct foo_S { +  static bool value; +}; +bool (foo_S::value); + + +namespace somens { +  struct a { }; // expected-note{{candidate constructor (the implicit copy constructor)}} +} + +template <typename T> +class foo { +}; + + +// PR4452 / PR4451 +foo<somens:a> a2;  // expected-error {{unexpected ':' in nested name specifier}} + +somens::a a3 = a2; // expected-error {{no viable conversion}} + +// typedefs and using declarations. +namespace test1 { +  namespace ns { +    class Counter { public: static int count; }; +    typedef Counter counter; +  } +  using ns::counter; + +  class Test { +    void test1() { +      counter c; +      c.count++; +      counter::count++; +    } +  }; +} + +// We still need to do lookup in the lexical scope, even if we push a +// non-lexical scope. +namespace test2 { +  namespace ns { +    extern int *count_ptr; +  } +  namespace { +    int count = 0; +  } + +  int *ns::count_ptr = &count; +} + +// PR6259, invalid case +namespace test3 { +  class A; // expected-note {{forward declaration}} +  void foo(const char *path) { +    A::execute(path); // expected-error {{incomplete type 'test3::A' named in nested name specifier}} +  } +} + +namespace PR7133 { +  namespace A { +    class Foo; +  } + +  namespace A { +    namespace B { +      bool foo(Foo &); +    } +  } + +  bool A::B::foo(Foo &) { +    return false; +  } +} + +class CLASS { +  void CLASS::foo2(); // expected-warning {{extra qualification on member 'foo2'}} +}; + +namespace PR8159 { +  class B { }; + +  class A { +    int A::a; // expected-warning{{extra qualification on member 'a'}} +    static int A::b; // expected-warning{{extra qualification on member 'b'}} +    int ::c; // expected-error{{non-friend class member 'c' cannot have a qualified name}} +  }; +} + +namespace rdar7980179 { +  class A { void f0(); }; // expected-note {{previous}} +  int A::f0() {} // expected-error {{out-of-line definition of 'rdar7980179::A::f0' differs from the declaration in the return type}} +} + +namespace alias = A; +double *dp = (alias::C*)0; // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'alias::C *'}} + +// http://llvm.org/PR10109 +namespace PR10109 { +template<typename T> +struct A { +protected: +  struct B; +  struct B::C; // expected-error {{requires a template parameter list}} \ +               // expected-error {{no struct named 'C'}} \ +    // expected-error{{non-friend class member 'C' cannot have a qualified name}} +}; + +template<typename T> +struct A2 { +protected: +  struct B; +}; +template <typename T> +struct A2<T>::B::C; // expected-error {{no struct named 'C'}} +} diff --git a/clang/test/SemaCXX/new-array-size-conv.cpp b/clang/test/SemaCXX/new-array-size-conv.cpp new file mode 100644 index 0000000..e8bb679 --- /dev/null +++ b/clang/test/SemaCXX/new-array-size-conv.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s + +struct ValueInt +{ +  ValueInt(int v = 0) : ValueLength(v) {} +  operator int () const { return ValueLength; } // expected-note 3{{conversion to integral type 'int' declared here}} +private: +  int ValueLength; +}; + +enum E { e }; +struct ValueEnum { +  operator E() const; // expected-note{{conversion to enumeration type 'E' declared here}} +}; + +struct ValueBoth : ValueInt, ValueEnum { }; + +struct IndirectValueInt : ValueInt { }; +struct TwoValueInts : ValueInt, IndirectValueInt { }; + +void test() { +  (void)new int[ValueInt(10)]; // expected-warning{{implicit conversion from array size expression of type 'ValueInt' to integral type 'int' is a C++11 extension}} +  (void)new int[ValueEnum()]; // expected-warning{{implicit conversion from array size expression of type 'ValueEnum' to enumeration type 'E' is a C++11 extension}} +  (void)new int[ValueBoth()]; // expected-error{{ambiguous conversion of array size expression of type 'ValueBoth' to an integral or enumeration type}} + +  (void)new int[TwoValueInts()]; // expected-error{{ambiguous conversion of array size expression of type 'TwoValueInts' to an integral or enumeration type}} +} diff --git a/clang/test/SemaCXX/new-delete-0x.cpp b/clang/test/SemaCXX/new-delete-0x.cpp new file mode 100644 index 0000000..dcc2e9b --- /dev/null +++ b/clang/test/SemaCXX/new-delete-0x.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu -std=c++11 + +using size_t = decltype(sizeof(0)); +struct noreturn_t {} constexpr noreturn = {}; + +void *operator new [[noreturn]] (size_t, noreturn_t); +void operator delete [[noreturn]] (void*, noreturn_t); + +void good_news() +{ +  auto p = new int[2][[]]; +  auto q = new int[[]][2]; +  auto r = new int*[[]][2][[]]; +  auto s = new (int(*[[]])[2][[]]); +} + +void bad_news(int *ip) +{ +  // attribute-specifiers can go almost anywhere in a new-type-id... +  auto r = new int[[]{return 1;}()][2]; // expected-error {{expected ']'}} +  auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected ']'}} +  // ... but not here: +  auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot appear here}} +  auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} expected-error {{variably modified type}} +} + +void good_deletes() +{ +  delete [&]{ return (int*)0; }(); +  // FIXME: This appears to be legal. +  delete []{ return (int*)0; }(); // unexpected-error {{expected expression}} +} diff --git a/clang/test/SemaCXX/new-delete-cxx0x.cpp b/clang/test/SemaCXX/new-delete-cxx0x.cpp new file mode 100644 index 0000000..c404fab --- /dev/null +++ b/clang/test/SemaCXX/new-delete-cxx0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=i686-pc-linux-gnu + +void ugly_news(int *ip) { +  // These are ill-formed according to one reading of C++98, and at the least +  // have undefined behavior. But they're well-formed, and defined to throw +  // std::bad_array_new_length, in C++11. +  (void)new int[-1]; // expected-warning {{array size is negative}} +  (void)new int[2000000000]; // expected-warning {{array is too large}} +} + + +struct S { +  S(int); +  S(); +  ~S(); +}; + +struct T { // expected-note 2 {{not viable}} +  T(int); // expected-note {{not viable}} +}; + +void fn() { +  (void) new int[2] {1, 2}; +  (void) new S[2] {1, 2}; +  (void) new T[2] {1, 2}; // expected-error {{no matching constructor}} +} diff --git a/clang/test/SemaCXX/new-delete-predefined-decl-2.cpp b/clang/test/SemaCXX/new-delete-predefined-decl-2.cpp new file mode 100644 index 0000000..981476d --- /dev/null +++ b/clang/test/SemaCXX/new-delete-predefined-decl-2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -DQUALIFIED -fsyntax-only -verify %s + +// PR5904 +void f0(int *ptr) { +#ifndef QUALIFIED +  operator delete(ptr); +#endif +} + +void f1(int *ptr) { +  ::operator delete[](ptr); +} diff --git a/clang/test/SemaCXX/new-delete-predefined-decl.cpp b/clang/test/SemaCXX/new-delete-predefined-decl.cpp new file mode 100644 index 0000000..20b15b7 --- /dev/null +++ b/clang/test/SemaCXX/new-delete-predefined-decl.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -DTEMPLATE_OVERLOAD -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#include <stddef.h> + +// Note that each test must be run separately so it can be the first operator +// new declaration in the file. + +#if defined(TEMPLATE_OVERLOAD) +// Don't crash on global template operator new overloads. +template<typename T> void* operator new(size_t, T); +void test_template_overload() { +  (void)new(0) double; +} +#endif + +void test_predefined() { +  (void)new double; +} diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp new file mode 100644 index 0000000..e77e3d6 --- /dev/null +++ b/clang/test/SemaCXX/new-delete.cpp @@ -0,0 +1,501 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu + +#include <stddef.h> + +struct S // expected-note {{candidate}} +{ +  S(int, int, double); // expected-note {{candidate}} +  S(double, int); // expected-note 2 {{candidate}} +  S(float, int); // expected-note 2 {{candidate}} +}; +struct T; // expected-note{{forward declaration of 'T'}} +struct U +{ +  // A special new, to verify that the global version isn't used. +  void* operator new(size_t, S*); // expected-note {{candidate}} +}; +struct V : U +{ +}; + +// PR5823 +void* operator new(const size_t); // expected-note 2 {{candidate}} +void* operator new(size_t, int*); // expected-note 3 {{candidate}} +void* operator new(size_t, float*); // expected-note 3 {{candidate}} +void* operator new(size_t, S); // expected-note 2 {{candidate}} + +struct foo { }; + +void good_news() +{ +  int *pi = new int; +  float *pf = new (pi) float(); +  pi = new int(1); +  pi = new int('c'); +  const int *pci = new const int(); +  S *ps = new S(1, 2, 3.4); +  ps = new (pf) (S)(1, 2, 3.4); +  S *(*paps)[2] = new S*[*pi][2]; +  typedef int ia4[4]; +  ia4 *pai = new (int[3][4]); +  pi = ::new int; +  U *pu = new (ps) U; +  V *pv = new (ps) V; +   +  pi = new (S(1.0f, 2)) int; +   +  (void)new int[true]; + +  // PR7147 +  typedef int a[2]; +  foo* f1 = new foo; +  foo* f2 = new foo[2]; +  typedef foo x[2]; +  typedef foo y[2][2]; +  x* f3 = new y; +} + +struct abstract { +  virtual ~abstract() = 0; +}; + +void bad_news(int *ip) +{ +  int i = 1; // expected-note 2{{here}} +  (void)new; // expected-error {{expected a type}} +  (void)new 4; // expected-error {{expected a type}} +  (void)new () int; // expected-error {{expected expression}} +  (void)new int[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}} +  (void)new int[1][i]; // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +  (void)new (int[1][i]); // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +  (void)new (int[i]); // expected-warning {{when type is in parentheses}} +  (void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}} +  (void)new int(1, 2); // expected-error {{excess elements in scalar initializer}} +  (void)new S(1); // expected-error {{no matching constructor}} +  (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}} +  (void)new const int; // expected-error {{default initialization of an object of const type 'const int'}} +  (void)new float*(ip); // expected-error {{cannot initialize a new value of type 'float *' with an lvalue of type 'int *'}} +  // Undefined, but clang should reject it directly. +  (void)new int[-1]; // expected-error {{array size is negative}} +  (void)new int[2000000000]; // expected-error {{array is too large}} +  (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumeration type, not 'S'}} +  (void)::S::new int; // expected-error {{expected unqualified-id}} +  (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}} +  (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}} +  // This must fail, because the member version shouldn't be found. +  (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}} +  // This must fail, because any member version hides all global versions. +  (void)new U; // expected-error {{no matching function for call to 'operator new'}} +  (void)new (int[]); // expected-error {{array size must be specified in new expressions}} +  (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}} +  // Some lacking cases due to lack of sema support. +} + +void good_deletes() +{ +  delete (int*)0; +  delete [](int*)0; +  delete (S*)0; +  ::delete (int*)0; +} + +void bad_deletes() +{ +  delete 0; // expected-error {{cannot delete expression of type 'int'}} +  delete [0] (int*)0; // expected-error {{expected expression}} +  delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}} +  delete (T*)0; // expected-warning {{deleting pointer to incomplete type}} +  ::S::delete (int*)0; // expected-error {{expected unqualified-id}} +} + +struct X0 { }; + +struct X1 { +  operator int*(); +  operator float(); +}; + +struct X2 { +  operator int*(); // expected-note {{candidate function}} +  operator float*(); // expected-note {{candidate function}} +}; + +void test_delete_conv(X0 x0, X1 x1, X2 x2) { +  delete x0; // expected-error{{cannot delete}} +  delete x1; +  delete x2; // expected-error{{ambiguous conversion of delete expression of type 'X2' to a pointer}} +} + +// PR4782 +class X3 { +public: +  static void operator delete(void * mem, size_t size); +}; + +class X4 { +public: +  static void release(X3 *x); +  static void operator delete(void * mem, size_t size); +}; + + +void X4::release(X3 *x) { +  delete x; +} + +class X5 { +public: +  void Destroy() const { delete this; } +}; + +class Base { +public: +  static void *operator new(signed char) throw(); // expected-error {{'operator new' takes type size_t}} +  static int operator new[] (size_t) throw(); // expected-error {{operator new[]' must return type 'void *'}} +}; + +class Tier {}; +class Comp : public Tier {}; + +class Thai : public Base { +public: +  Thai(const Tier *adoptDictionary); +}; + +void loadEngineFor() { +  const Comp *dict; +  new Thai(dict); +} + +template <class T> struct TBase { +  void* operator new(T size, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}} +}; + +TBase<int> t1; + +class X6 { +public: +  static void operator delete(void*, int); // expected-note {{member found by ambiguous name lookup}} +}; + +class X7 { +public: +  static void operator delete(void*, int); // expected-note {{member found by ambiguous name lookup}} +}; + +class X8 : public X6, public X7 { +}; + +void f(X8 *x8) { +  delete x8; // expected-error {{member 'operator delete' found in multiple base classes of different types}} +} + +class X9 { +public: +  static void operator delete(void*, int); // expected-note {{'operator delete' declared here}} +  static void operator delete(void*, float); // expected-note {{'operator delete' declared here}} +}; + +void f(X9 *x9) { +  delete x9; // expected-error {{no suitable member 'operator delete' in 'X9'}} +} + +struct X10 { +  virtual ~X10(); +}; + +struct X11 : X10 { // expected-error {{no suitable member 'operator delete' in 'X11'}} +  void operator delete(void*, int); // expected-note {{'operator delete' declared here}} +}; + +void f() { +  X11 x11; // expected-note {{implicit default destructor for 'X11' first required here}} +} + +struct X12 { +  void* operator new(size_t, void*); +}; + +struct X13 : X12 { +  using X12::operator new; +}; + +static void* f(void* g) +{ +    return new (g) X13(); +} + +class X14 { +public: +  static void operator delete(void*, const size_t); +}; + +void f(X14 *x14a, X14 *x14b) { +  delete x14a; +} + +class X15 { +private: +  X15(); // expected-note {{declared private here}} +  ~X15(); // expected-note {{declared private here}} +}; + +void f(X15* x) { +  new X15(); // expected-error {{calling a private constructor}} +  delete x; // expected-error {{calling a private destructor}} +} + +namespace PR5918 { // Look for template operator new overloads. +  struct S { template<typename T> static void* operator new(size_t, T); }; +  void test() { +    (void)new(0) S; +  } +} + +namespace Test1 { + +void f() { +  (void)new int[10](1, 2); // expected-error {{array 'new' cannot have initialization arguments}} +   +  typedef int T[10]; +  (void)new T(1, 2); // expected-error {{array 'new' cannot have initialization arguments}} +} + +template<typename T> +void g(unsigned i) { +  (void)new T[1](i); // expected-error {{array 'new' cannot have initialization arguments}} +} + +template<typename T> +void h(unsigned i) { +  (void)new T(i); // expected-error {{array 'new' cannot have initialization arguments}} +} +template void h<unsigned>(unsigned); +template void h<unsigned[10]>(unsigned); // expected-note {{in instantiation of function template specialization 'Test1::h<unsigned int [10]>' requested here}} + +} + +// Don't diagnose access for overload candidates that aren't selected. +namespace PR7436 { +struct S1 { +  void* operator new(size_t); +  void operator delete(void* p); + +private: +  void* operator new(size_t, void*); // expected-note {{declared private here}} +  void operator delete(void*, void*); +}; +class S2 { +  void* operator new(size_t); // expected-note {{declared private here}} +  void operator delete(void* p); // expected-note {{declared private here}} +}; + +void test(S1* s1, S2* s2) {  +  delete s1; +  delete s2; // expected-error {{is a private member}} +  (void)new S1(); +  (void)new (0L) S1(); // expected-error {{is a private member}} +  (void)new S2(); // expected-error {{is a private member}} +} +} + +namespace rdar8018245 { +  struct X0 { +    static const int value = 17; +  }; + +  const int X0::value; + +  struct X1 { +    static int value; +  }; + +  int X1::value; + +  template<typename T> +  int *f() { +    return new (int[T::value]); // expected-warning{{when type is in parentheses, array cannot have dynamic size}} +  } + +  template int *f<X0>(); +  template int *f<X1>(); // expected-note{{in instantiation of}} + +} + +// <rdar://problem/8248780> +namespace Instantiate { +  template<typename T> struct X {  +    operator T*(); +  }; + +  void f(X<int> &xi) { +    delete xi; +  } +} + +namespace PR7810 { +  struct X { +    // cv is ignored in arguments +    static void operator delete(void *const); +  }; +  struct Y { +    // cv is ignored in arguments +    static void operator delete(void *volatile); +  }; +} + +// Don't crash on template delete operators +namespace TemplateDestructors { +  struct S { +    virtual ~S() {} + +    void* operator new(const size_t size); +    template<class T> void* operator new(const size_t, const int, T*); +    void operator delete(void*, const size_t); +    template<class T> void operator delete(void*, const size_t, const int, T*); +  }; +} + +namespace DeleteParam { +  struct X { +    void operator delete(X*); // expected-error{{first parameter of 'operator delete' must have type 'void *'}} +  }; + +  struct Y { +    void operator delete(void* const); +  }; +} + +// <rdar://problem/8427878> +// Test that the correct 'operator delete' is selected to pair with +// the unexpected placement 'operator new'. +namespace PairedDelete { +  template <class T> struct A { +    A(); +    void *operator new(size_t s, double d = 0); +    void operator delete(void *p, double d); +    void operator delete(void *p) { +      T::dealloc(p); +    } +  }; + +  A<int> *test() { +    return new A<int>(); +  } +} + +namespace PR7702 { +  void test1() { +    new DoesNotExist; // expected-error {{unknown type name 'DoesNotExist'}} +  } +} + +namespace ArrayNewNeedsDtor { +  struct A { A(); private: ~A(); }; // expected-note {{declared private here}} +  struct B { B(); A a; }; // expected-error {{field of type 'ArrayNewNeedsDtor::A' has private destructor}} +  B *test9() { +    return new B[5]; // expected-note {{implicit default destructor for 'ArrayNewNeedsDtor::B' first required here}} +  } +} + +namespace DeleteIncompleteClass { +  struct A; // expected-note {{forward declaration}} +  extern A x; +  void f() { delete x; } // expected-error {{deleting incomplete class type}} +} + +namespace DeleteIncompleteClassPointerError { +  struct A; // expected-note {{forward declaration}} +  void f(A *x) { 1+delete x; } // expected-warning {{deleting pointer to incomplete type}} \ +                               // expected-error {{invalid operands to binary expression}} +} + +namespace PR10504 { +  struct A { +    virtual void foo() = 0; +  }; +  void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}} +} + +struct PlacementArg {}; +inline void *operator new[](size_t, const PlacementArg &) throw () { +  return 0; +} +inline void operator delete[](void *, const PlacementArg &) throw () { +} + +namespace r150682 { + +  template <typename X> +  struct S { +    struct Inner {}; +    S() { new Inner[1]; } +  }; + +  struct T { +  }; + +  template<typename X> +  void tfn() { +    new (*(PlacementArg*)0) T[1]; +  } + +  void fn() { +    tfn<int>(); +  } + +} + +namespace P12023 { +  struct CopyCounter +  { +      CopyCounter(); +      CopyCounter(const CopyCounter&); +  }; + +  int main() +  { +    CopyCounter* f = new CopyCounter[10](CopyCounter()); // expected-error {{cannot have initialization arguments}} +      return 0; +  } +} + +namespace PR12061 { +  template <class C> struct scoped_array { +    scoped_array(C* p = __null); +  }; +  template <class Payload> struct Foo { +    Foo() : a_(new scoped_array<int>[5]) { } +    scoped_array< scoped_array<int> > a_; +  }; +  class Bar {}; +  Foo<Bar> x; + +  template <class C> struct scoped_array2 { +    scoped_array2(C* p = __null, C* q = __null); +  }; +  template <class Payload> struct Foo2 { +    Foo2() : a_(new scoped_array2<int>[5]) { } +    scoped_array2< scoped_array2<int> > a_; +  }; +  class Bar2 {}; +  Foo2<Bar2> x2; + +  class MessageLoop { +  public: +    explicit MessageLoop(int type = 0); +  }; +  template <class CookieStoreTestTraits> +  class CookieStoreTest { +  protected: +    CookieStoreTest() { +      new MessageLoop; +    } +  }; +  struct CookieMonsterTestTraits { +  }; +  class DeferredCookieTaskTest : public CookieStoreTest<CookieMonsterTestTraits> +  { +    DeferredCookieTaskTest() {} +  }; +} diff --git a/clang/test/SemaCXX/no-exceptions.cpp b/clang/test/SemaCXX/no-exceptions.cpp new file mode 100644 index 0000000..f739568 --- /dev/null +++ b/clang/test/SemaCXX/no-exceptions.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Various tests for -fno-exceptions + +typedef __SIZE_TYPE__ size_t; + +namespace test0 { +  // rdar://problem/7878149 +  class Foo { +  public: +    void* operator new(size_t x); +  private: +    void operator delete(void *x); +  }; + +  void test() { +    // Under -fexceptions, this does access control for the associated +    // 'operator delete'. +    (void) new Foo(); +  } +} + +namespace test1 { +void f() { +  throw; // expected-error {{cannot use 'throw' with exceptions disabled}} +} + +void g() { +  try { // expected-error {{cannot use 'try' with exceptions disabled}} +    f(); +  } catch (...) { +  } +} + +} diff --git a/clang/test/SemaCXX/no-implicit-builtin-decls.cpp b/clang/test/SemaCXX/no-implicit-builtin-decls.cpp new file mode 100644 index 0000000..d82f7f1 --- /dev/null +++ b/clang/test/SemaCXX/no-implicit-builtin-decls.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() { +  void *p = malloc(sizeof(int) * 10); // expected-error{{use of undeclared identifier 'malloc'}} +} + +int malloc(double); diff --git a/clang/test/SemaCXX/non-empty-class-size-zero.cpp b/clang/test/SemaCXX/non-empty-class-size-zero.cpp new file mode 100644 index 0000000..6b714db --- /dev/null +++ b/clang/test/SemaCXX/non-empty-class-size-zero.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only %s +// rdar://8945175 + +struct X {  +  int array[0];  +  int array1[0];  +  int array2[0];  +  X(); +  ~X(); +}; + +struct Y { +  int first; +  X padding; +  int second; +}; + +int zero_size_array[(sizeof(Y)  == 8) -1]; // no error here! diff --git a/clang/test/SemaCXX/null_in_arithmetic_ops.cpp b/clang/test/SemaCXX/null_in_arithmetic_ops.cpp new file mode 100644 index 0000000..a6c0dbf --- /dev/null +++ b/clang/test/SemaCXX/null_in_arithmetic_ops.cpp @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify -Wno-string-plus-int %s +#include <stddef.h> + +void f() { +  int a; +  bool b; +  void (^c)(); +  class X; +  void (X::*d) (); +  extern void e(); +  int f[2]; +  const void *v; + +  a = 0 ? NULL + a : a + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL - a : a - NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL / a : a / NULL; // expected-warning 2{{use of NULL in arithmetic operation}} \ +                               // expected-warning {{division by zero is undefined}} +  a = 0 ? NULL * a : a * NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL >> a : a >> NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL << a : a << NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL % a : a % NULL; // expected-warning 2{{use of NULL in arithmetic operation}} \ +                                  expected-warning {{remainder by zero is undefined}} +  a = 0 ? NULL & a : a & NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL | a : a | NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  a = 0 ? NULL ^ a : a ^ NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + +  // Check for warnings or errors when doing arithmetic on pointers and other +  // types. +  v = 0 ? NULL + &a : &a + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  v = 0 ? NULL + c : c + NULL; // \ +    expected-error {{invalid operands to binary expression ('long' and 'void (^)()')}} \ +    expected-error {{invalid operands to binary expression ('void (^)()' and 'long')}} +  v = 0 ? NULL + d : d + NULL; // \ +    expected-error {{invalid operands to binary expression ('long' and 'void (X::*)()')}} \ +    expected-error {{invalid operands to binary expression ('void (X::*)()' and 'long')}} +  v = 0 ? NULL + e : e + NULL; // expected-error 2{{arithmetic on a pointer to the function type 'void ()'}} +  v = 0 ? NULL + f : f + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} +  v = 0 ? NULL + "f" : "f" + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + +  // Using two NULLs should only give one error instead of two. +  a = NULL + NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL - NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL / NULL; // expected-warning{{use of NULL in arithmetic operation}} \ +                   // expected-warning{{division by zero is undefined}} +  a = NULL * NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL >> NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL << NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL % NULL; // expected-warning{{use of NULL in arithmetic operation}} \ +                   // expected-warning{{remainder by zero is undefined}} +  a = NULL & NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL | NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a = NULL ^ NULL; // expected-warning{{use of NULL in arithmetic operation}} + +  a += NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a -= NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a /= NULL; // expected-warning{{use of NULL in arithmetic operation}} \ +             // expected-warning{{division by zero is undefined}} +  a *= NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a >>= NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a <<= NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a %= NULL; // expected-warning{{use of NULL in arithmetic operation}} \ +             // expected-warning{{remainder by zero is undefined}} +  a &= NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a |= NULL; // expected-warning{{use of NULL in arithmetic operation}} +  a ^= NULL; // expected-warning{{use of NULL in arithmetic operation}} + +  b = a < NULL || a > NULL; // expected-warning 2{{comparison between NULL and non-pointer ('int' and NULL)}} +  b = NULL < a || NULL > a; // expected-warning 2{{comparison between NULL and non-pointer (NULL and 'int')}} +  b = a <= NULL || a >= NULL; // expected-warning 2{{comparison between NULL and non-pointer ('int' and NULL)}} +  b = NULL <= a || NULL >= a; // expected-warning 2{{comparison between NULL and non-pointer (NULL and 'int')}} +  b = a == NULL || a != NULL; // expected-warning 2{{comparison between NULL and non-pointer ('int' and NULL)}} +  b = NULL == a || NULL != a; // expected-warning 2{{comparison between NULL and non-pointer (NULL and 'int')}} + +  b = &a < NULL || NULL < &a || &a > NULL || NULL > &a; +  b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a; +  b = &a == NULL || NULL == &a || &a != NULL || NULL != &a; + +  b = 0 == a; +  b = 0 == &a; + +  b = NULL < NULL || NULL > NULL; +  b = NULL <= NULL || NULL >= NULL; +  b = NULL == NULL || NULL != NULL; + +  b = ((NULL)) != a;  // expected-warning{{comparison between NULL and non-pointer (NULL and 'int')}} + +  // Check that even non-standard pointers don't warn. +  b = c == NULL || NULL == c || c != NULL || NULL != c; +  b = d == NULL || NULL == d || d != NULL || NULL != d; +  b = e == NULL || NULL == e || e != NULL || NULL != e; +  b = f == NULL || NULL == f || f != NULL || NULL != f; +  b = "f" == NULL || NULL == "f" || "f" != NULL || NULL != "f"; +} diff --git a/clang/test/SemaCXX/nullptr-98.cpp b/clang/test/SemaCXX/nullptr-98.cpp new file mode 100644 index 0000000..0d624c2 --- /dev/null +++ b/clang/test/SemaCXX/nullptr-98.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s +void f(void *); +void g() { f(__nullptr); } diff --git a/clang/test/SemaCXX/nullptr.cpp b/clang/test/SemaCXX/nullptr.cpp new file mode 100644 index 0000000..e313603 --- /dev/null +++ b/clang/test/SemaCXX/nullptr.cpp @@ -0,0 +1,185 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding %s +#include <stdint.h> + +typedef decltype(nullptr) nullptr_t; + +struct A {}; + +int o1(char*); +void o1(uintptr_t); +void o2(char*); // expected-note {{candidate}} +void o2(int A::*); // expected-note {{candidate}} + +nullptr_t f(nullptr_t null) +{ +  // Implicit conversions. +  null = nullptr; +  void *p = nullptr; +  p = null; +  int *pi = nullptr; +  pi = null; +  null = 0; +  int A::*pm = nullptr; +  pm = null; +  void (*pf)() = nullptr; +  pf = null; +  void (A::*pmf)() = nullptr; +  pmf = null; +  bool b = nullptr; + +  // Can't convert nullptr to integral implicitly. +  uintptr_t i = nullptr; // expected-error {{cannot initialize}} + +  // Operators +  (void)(null == nullptr); +  (void)(null <= nullptr); +  (void)(null == (void*)0); +  (void)((void*)0 == nullptr); +  (void)(null <= (void*)0); +  (void)((void*)0 <= nullptr); +  (void)(0 == nullptr); +  (void)(nullptr == 0); +  (void)(nullptr <= 0); +  (void)(0 <= nullptr); +  (void)(1 > nullptr); // expected-error {{invalid operands to binary expression}} +  (void)(1 != nullptr); // expected-error {{invalid operands to binary expression}} +  (void)(1 + nullptr); // expected-error {{invalid operands to binary expression}} +  (void)(0 ? nullptr : 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}} +  (void)(0 ? nullptr : (void*)0); +  (void)(0 ? nullptr : A()); // expected-error {{non-pointer operand type 'A' incompatible with nullptr}} +  (void)(0 ? A() : nullptr); // expected-error {{non-pointer operand type 'A' incompatible with nullptr}} + +  // Overloading +  int t = o1(nullptr); +  t = o1(null); +  o2(nullptr); // expected-error {{ambiguous}} + +  // nullptr is an rvalue, null is an lvalue +  (void)&nullptr; // expected-error {{address expression must be an lvalue}} +  nullptr_t *pn = &null; + +  // You can reinterpret_cast nullptr to an integer. +  (void)reinterpret_cast<uintptr_t>(nullptr); +  (void)reinterpret_cast<uintptr_t>(*pn); + +  int *ip = *pn; +  if (*pn) { } + +  // You can throw nullptr. +  throw nullptr; +} + +// Template arguments can be nullptr. +template <int *PI, void (*PF)(), int A::*PM, void (A::*PMF)()> +struct T {}; + +typedef T<nullptr, nullptr, nullptr, nullptr> NT; + +namespace test1 {  +template<typename T, typename U> struct is_same { +  static const bool value = false; +}; + +template<typename T> struct is_same<T, T> { +  static const bool value = true; +}; + +void *g(void*); +bool g(bool); + +// Test that we prefer g(void*) over g(bool). +static_assert(is_same<decltype(g(nullptr)), void*>::value, ""); +} + +namespace test2 { +  void f(int, ...) __attribute__((sentinel)); + +  void g() { +    // nullptr can be used as the sentinel value. +    f(10, nullptr); +  } +} + +namespace test3 { +  void f(const char*, ...) __attribute__((format(printf, 1, 2))); + +  void g() { +    // Don't warn when using nullptr with %p. +    f("%p", nullptr); +  } +} + +static_assert(__is_scalar(nullptr_t), ""); +static_assert(__is_pod(nullptr_t), ""); +static_assert(sizeof(nullptr_t) == sizeof(void*), ""); + +static_assert(!(nullptr < nullptr), ""); +static_assert(!(nullptr > nullptr), ""); +static_assert(  nullptr <= nullptr, ""); +static_assert(  nullptr >= nullptr, ""); +static_assert(  nullptr == nullptr, ""); +static_assert(!(nullptr != nullptr), ""); + +static_assert(!(0 < nullptr), ""); +static_assert(!(0 > nullptr), ""); +static_assert(  0 <= nullptr, ""); +static_assert(  0 >= nullptr, ""); +static_assert(  0 == nullptr, ""); +static_assert(!(0 != nullptr), ""); + +static_assert(!(nullptr < 0), ""); +static_assert(!(nullptr > 0), ""); +static_assert(  nullptr <= 0, ""); +static_assert(  nullptr >= 0, ""); +static_assert(  nullptr == 0, ""); +static_assert(!(nullptr != 0), ""); + +namespace overloading { +  int &f1(int*); +  float &f1(bool); + +  void test_f1() { +    int &ir = (f1)(nullptr); +  } + +  struct ConvertsToNullPtr { +    operator nullptr_t() const; +  }; + +  void test_conversion(ConvertsToNullPtr ctn) { +    (void)(ctn == ctn); +    (void)(ctn != ctn); +    (void)(ctn <= ctn); +    (void)(ctn >= ctn); +    (void)(ctn < ctn); +    (void)(ctn > ctn); +  } +} + +namespace templates { +  template<typename T, nullptr_t Value> +  struct X {  +    X() { ptr = Value; } + +    T *ptr; +  }; +   +  X<int, nullptr> x; + + +  template<int (*fp)(int), int* p, int A::* pmd, int (A::*pmf)(int)> +  struct X2 {}; +   +  X2<nullptr, nullptr, nullptr, nullptr> x2; +} + +namespace null_pointer_constant { + +// Pending implementation of core issue 903, ensure we don't allow any of the +// C++11 constant evaluation semantics in null pointer constants. +struct S { int n; }; +constexpr int null() { return 0; } +void *p = S().n; // expected-error {{cannot initialize}} +void *q = null(); // expected-error {{cannot initialize}} + +} diff --git a/clang/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/clang/test/SemaCXX/nullptr_in_arithmetic_ops.cpp new file mode 100644 index 0000000..9671353 --- /dev/null +++ b/clang/test/SemaCXX/nullptr_in_arithmetic_ops.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fsyntax-only -fblocks -std=c++11 -verify %s + +void foo() { +  int a; +  bool b; + +  a = 0 ? nullptr + a : a + nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr - a : a - nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr / a : a / nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr * a : a * nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr >> a : a >> nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr << a : a << nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr % a : a % nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr & a : a & nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr | a : a | nullptr; // expected-error 2{{invalid operands to binary expression}} +  a = 0 ? nullptr ^ a : a ^ nullptr; // expected-error 2{{invalid operands to binary expression}} + +  // Using two nullptrs should only give one error instead of two. +  a = nullptr + nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr - nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr / nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr * nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr >> nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr << nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr % nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr & nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr | nullptr; // expected-error{{invalid operands to binary expression}} +  a = nullptr ^ nullptr; // expected-error{{invalid operands to binary expression}} + +  a += nullptr; // expected-error{{invalid operands to binary expression}} +  a -= nullptr; // expected-error{{invalid operands to binary expression}} +  a /= nullptr; // expected-error{{invalid operands to binary expression}} +  a *= nullptr; // expected-error{{invalid operands to binary expression}} +  a >>= nullptr; // expected-error{{invalid operands to binary expression}} +  a <<= nullptr; // expected-error{{invalid operands to binary expression}} +  a %= nullptr; // expected-error{{invalid operands to binary expression}} +  a &= nullptr; // expected-error{{invalid operands to binary expression}} +  a |= nullptr; // expected-error{{invalid operands to binary expression}} +  a ^= nullptr; // expected-error{{invalid operands to binary expression}} + +  b = a < nullptr || nullptr < a; // expected-error 2{{invalid operands to binary expression}} +  b = a > nullptr || nullptr > a; // expected-error 2{{invalid operands to binary expression}} +  b = a <= nullptr || nullptr <= a; // expected-error 2{{invalid operands to binary expression}} +  b = a >= nullptr || nullptr >= a; // expected-error 2{{invalid operands to binary expression}} +  b = a == nullptr || nullptr == a; // expected-error 2{{invalid operands to binary expression}} +  b = a != nullptr || nullptr != a; // expected-error 2{{invalid operands to binary expression}} + +  b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a; +  b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a; +  b = &a == nullptr || nullptr == &a || &a != nullptr || nullptr != &a; + +  b = nullptr < nullptr || nullptr > nullptr; +  b = nullptr <= nullptr || nullptr >= nullptr; +  b = nullptr == nullptr || nullptr != nullptr; + +  b = ((nullptr)) != a;  // expected-error{{invalid operands to binary expression}} + +  void (^c)(); +  c = nullptr; +  b = c == nullptr || nullptr == c || c != nullptr || nullptr != c; +   +  class X; +  void (X::*d) (); +  d = nullptr; +  b = d == nullptr || nullptr == d || d != nullptr || nullptr != d; + +  extern void e(); +  b = e == nullptr || nullptr == e || e != nullptr || nullptr != e; + +  int f[2]; +  b = f == nullptr || nullptr == f || f != nullptr || nullptr != f; +  b = "f" == nullptr || nullptr == "f" || "f" != nullptr || nullptr != "f"; +} diff --git a/clang/test/SemaCXX/offsetof.cpp b/clang/test/SemaCXX/offsetof.cpp new file mode 100644 index 0000000..a5f5d34 --- /dev/null +++ b/clang/test/SemaCXX/offsetof.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof + +struct NonPOD { +  virtual void f(); +  int m; +}; + +struct P { +  NonPOD fieldThatPointsToANonPODType; +}; + +void f() { +  int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-warning{{offset of on non-POD type 'P'}} +} + +struct Base { int x; }; +struct Derived : Base { int y; }; +int o = __builtin_offsetof(Derived, x); // expected-warning{{offset of on non-POD type}} + +const int o2 = sizeof(__builtin_offsetof(Derived, x)); + +struct HasArray { +  int array[17]; +}; + +// Constant and non-constant offsetof expressions +void test_ice(int i) { +  int array0[__builtin_offsetof(HasArray, array[5])]; +  int array1[__builtin_offsetof(HasArray, array[i])]; +} + +// Bitfields +struct has_bitfields { +  int i : 7; +  int j : 12; // expected-note{{bit-field is declared here}} +}; + +int test3 = __builtin_offsetof(struct has_bitfields, j); // expected-error{{cannot compute offset of bit-field 'j'}} + +// offsetof referring to members of a base class. +struct Base1 {  +  int x; +}; + +struct Base2 { +  int y; +}; + +struct Derived2 : public Base1, public Base2 { +  int z;  +}; + +int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1]; +int derived2[__builtin_offsetof(Derived2, y)  == 4? 1 : -1]; +int derived3[__builtin_offsetof(Derived2, z)  == 8? 1 : -1]; + +// offsetof referring to anonymous struct in base. +// PR7769 +struct foo { +    struct { +        int x; +    }; +}; + +struct bar : public foo  { +}; + +int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1]; + +struct LtoRCheck { +  int a[10]; +  int f(); +}; +int ltor = __builtin_offsetof(struct LtoRCheck, a[LtoRCheck().f]); // \ +  expected-error {{reference to non-static member function must be called}} diff --git a/clang/test/SemaCXX/operator-arrow-temporary.cpp b/clang/test/SemaCXX/operator-arrow-temporary.cpp new file mode 100644 index 0000000..8e79609 --- /dev/null +++ b/clang/test/SemaCXX/operator-arrow-temporary.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR9615 + +struct Resource { +  void doit(); +}; + +template<int x> struct Lock { +  ~Lock() { int a[x]; } // expected-error {{declared as an array with a negative size}} +  Resource* operator->() { return 0; } +}; + +struct Accessor { +  Lock<-1> operator->(); +}; + +// Make sure we try to instantiate the destructor for Lock here +void f() { Accessor acc; acc->doit(); } // expected-note {{requested here}} + diff --git a/clang/test/SemaCXX/out-of-line-def-mismatch.cpp b/clang/test/SemaCXX/out-of-line-def-mismatch.cpp new file mode 100644 index 0000000..6ade5b8 --- /dev/null +++ b/clang/test/SemaCXX/out-of-line-def-mismatch.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s + +namespace N2 { +  struct S1; + +  namespace N1 { +    class C1 {}; + +    struct S2 { +      void func(S1*); // expected-note {{type of 1st parameter of member declaration does not match definition ('N2::S1 *' vs 'N2::N1::S1 *')}} +      void func(C1&, unsigned, const S1*); // expected-note {{type of 3rd parameter of member declaration does not match definition ('const N2::S1 *' vs 'const N2::N1::S1 *')}} +      void func(const S1*, unsigned); //expected-note {{type of 1st parameter of member declaration does not match definition ('const N2::S1 *' vs 'N2::N1::S1')}} +      void func(unsigned, const S1*); // expected-note {{type of 1st parameter of member declaration does not match definition ('unsigned int' vs 'unsigned int *')}} +    }; + +    struct S1 {}; +  } +} + +void N2::N1::S2::func(S1*) {} // expected-error {{out-of-line definition of 'func' does not match any declaration in 'N2::N1::S2'}} +void N2::N1::S2::func(C1&, unsigned, const S1*) {} // expected-error {{out-of-line definition of 'func' does not match any declaration in 'N2::N1::S2'}} +void N2::N1::S2::func(S1*, double) {} // expected-error {{out-of-line definition of 'func' does not match any declaration in 'N2::N1::S2'}} +void N2::N1::S2::func(S1, unsigned) {} // expected-error {{out-of-line definition of 'func' does not match any declaration in 'N2::N1::S2'}} +void N2::N1::S2::func(unsigned*, S1*) {} // expected-error {{out-of-line definition of 'func' does not match any declaration in 'N2::N1::S2'}} diff --git a/clang/test/SemaCXX/overload-0x.cpp b/clang/test/SemaCXX/overload-0x.cpp new file mode 100644 index 0000000..677d16a --- /dev/null +++ b/clang/test/SemaCXX/overload-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s  + +namespace test0 { +  struct A { // expected-note {{candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'const test0::A', but method is not marked const}} expected-note {{candidate function (the implicit move assignment operator) not viable: 'this' argument has type 'const test0::A', but method is not marked const}} +    A &operator=(void*); // expected-note {{candidate function not viable: 'this' argument has type 'const test0::A', but method is not marked const}} +  }; + +  void test(const A &a) { +    a = "help"; // expected-error {{no viable overloaded '='}} +  } +} diff --git a/clang/test/SemaCXX/overload-call-copycon.cpp b/clang/test/SemaCXX/overload-call-copycon.cpp new file mode 100644 index 0000000..6720cb6 --- /dev/null +++ b/clang/test/SemaCXX/overload-call-copycon.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -Wnon-pod-varargs +class X { }; // expected-note {{the implicit copy constructor}} \ +             // expected-note{{the implicit default constructor}} + +int& copycon(X x); // expected-note{{passing argument to parameter}} +float& copycon(...); + +void test_copycon(X x, X const xc, X volatile xv) { +  int& i1 = copycon(x); +  int& i2 = copycon(xc); +  copycon(xv); // expected-error{{no matching constructor}} +} + +class A { +public: +  A(A&); // expected-note{{would lose const qualifier}} \ +         // expected-note{{no known conversion}} +}; + +class B : public A { }; // expected-note{{would lose const qualifier}} \ +// expected-note{{would lose volatile qualifier}} \ +// expected-note 2{{requires 0 arguments}} + +short& copycon2(A a); // expected-note{{passing argument to parameter}} +int& copycon2(B b); // expected-note 2{{passing argument to parameter}} +float& copycon2(...); + +void test_copycon2(A a, const A ac, B b, B const bc, B volatile bv) { +  int& i1 = copycon2(b); +  copycon2(bc); // expected-error{{no matching constructor}} +  copycon2(bv); // expected-error{{no matching constructor}} +  short& s1 = copycon2(a); +  copycon2(ac); // expected-error{{no matching constructor}} +} + +int& copycon3(A a); // expected-note{{passing argument to parameter 'a' here}} +float& copycon3(...); + +void test_copycon3(B b, const B bc) { +  int& i1 = copycon3(b); +  copycon3(bc); // expected-error{{no matching constructor}} +} + +class C : public B { }; + +float& copycon4(A a); +int& copycon4(B b); + +void test_copycon4(C c) { +  int& i = copycon4(c); +}; diff --git a/clang/test/SemaCXX/overload-call.cpp b/clang/test/SemaCXX/overload-call.cpp new file mode 100644 index 0000000..b5e1214 --- /dev/null +++ b/clang/test/SemaCXX/overload-call.cpp @@ -0,0 +1,570 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +int* f(int) { return 0; } +float* f(float) { return 0; } +void f(); + +void test_f(int iv, float fv) { +  float* fp = f(fv); +  int* ip = f(iv); +} + +int* g(int, float, int); // expected-note {{candidate function}} +float* g(int, int, int); // expected-note {{candidate function}} +double* g(int, float, float); // expected-note {{candidate function}} +char* g(int, float, ...); // expected-note {{candidate function}} +void g(); + +void test_g(int iv, float fv) { +  int* ip1 = g(iv, fv, 0); +  float* fp1 = g(iv, iv, 0); +  double* dp1 = g(iv, fv, fv); +  char* cp1 = g(0, 0); +  char* cp2 = g(0, 0, 0, iv, fv); + +  double* dp2 = g(0, fv, 1.5); // expected-error {{call to 'g' is ambiguous}} +} + +double* h(double f); +int* h(int); + +void test_h(float fv, unsigned char cv) { +  double* dp = h(fv); +  int* ip = h(cv); +} + +int* i(int); +double* i(long); + +void test_i(short sv, int iv, long lv, unsigned char ucv) { +  int* ip1 = i(sv); +  int* ip2 = i(iv); +  int* ip3 = i(ucv); +  double* dp1 = i(lv); +} + +int* j(void*); +double* j(bool); + +void test_j(int* ip) { +  int* ip1 = j(ip); +} + +int* k(char*); +double* k(bool); + +void test_k() { +  int* ip1 = k("foo"); // expected-warning{{conversion from string literal to 'char *' is deprecated}} +  int* ip2 = k(("foo")); // expected-warning{{conversion from string literal to 'char *' is deprecated}} +  double* dp1 = k(L"foo"); +} + +int* l(wchar_t*); +double* l(bool); + +void test_l() { +  int* ip1 = l(L"foo"); // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}} +  double* dp1 = l("foo"); +} + +int* m(const char*); +double* m(char*); + +void test_m() { +  int* ip = m("foo"); +} + +int* n(char*); +double* n(void*); +class E; + +void test_n(E* e) { +  char ca[7]; +  int* ip1 = n(ca); +  int* ip2 = n("foo"); // expected-warning{{conversion from string literal to 'char *' is deprecated}} + +  float fa[7]; +  double* dp1 = n(fa); + +  double* dp2 = n(e); +} + +enum PromotesToInt { +  PromotesToIntValue = -1 +}; + +enum PromotesToUnsignedInt { +  PromotesToUnsignedIntValue = __INT_MAX__ * 2U +}; + +int* o(int); +double* o(unsigned int); +float* o(long); + +void test_o() { +  int* ip1 = o(PromotesToIntValue); +  double* dp1 = o(PromotesToUnsignedIntValue); +} + +int* p(int); +double* p(double); + +void test_p() { +  int* ip = p((short)1); +  double* dp = p(1.0f); +} + +struct Bits { +  signed short int_bitfield : 5; +  unsigned int uint_bitfield : 8; +}; + +int* bitfields(int, int); +float* bitfields(unsigned int, int); + +void test_bitfield(Bits bits, int x) { +  int* ip = bitfields(bits.int_bitfield, 0); +  float* fp = bitfields(bits.uint_bitfield, 0u); +} + +int* multiparm(long, int, long); // expected-note {{candidate function}} +float* multiparm(int, int, int); // expected-note {{candidate function}} +double* multiparm(int, int, short); // expected-note {{candidate function}} + +void test_multiparm(long lv, short sv, int iv) { +  int* ip1 = multiparm(lv, iv, lv); +  int* ip2 = multiparm(lv, sv, lv); +  float* fp1 = multiparm(iv, iv, iv); +  float* fp2 = multiparm(sv, iv, iv); +  double* dp1 = multiparm(sv, sv, sv); +  double* dp2 = multiparm(iv, sv, sv); +  multiparm(sv, sv, lv); // expected-error {{call to 'multiparm' is ambiguous}} +} + +// Test overloading based on qualification vs. no qualification +// conversion. +int* quals1(int const * p); +char* quals1(int * p); + +int* quals2(int const * const * pp); +char* quals2(int * * pp); + +int* quals3(int const * * const * ppp); +char* quals3(int *** ppp); + +void test_quals(int * p, int * * pp, int * * * ppp) { +  char* q1 = quals1(p); +  char* q2 = quals2(pp); +  char* q3 = quals3(ppp); +} + +// Test overloading based on qualification ranking (C++ 13.3.2)p3. +int* quals_rank1(int const * p); +float* quals_rank1(int const volatile *p); +char* quals_rank1(char*); +double* quals_rank1(const char*); + +int* quals_rank2(int const * const * pp); +float* quals_rank2(int * const * pp); + +void quals_rank3(int const * const * const volatile * p); // expected-note{{candidate function}} +void quals_rank3(int const * const volatile * const * p); // expected-note{{candidate function}} + +void quals_rank3(int const *); // expected-note{{candidate function}} +void quals_rank3(int volatile *); // expected-note{{candidate function}} + +void test_quals_ranking(int * p, int volatile *pq, int * * pp, int * * * ppp) { +  int* q1 = quals_rank1(p); +  float* q2 = quals_rank1(pq);  +  double* q3 = quals_rank1("string literal"); +  char a[17]; +  const char* ap = a; +  char* q4 = quals_rank1(a); +  double* q5 = quals_rank1(ap); + +  float* q6 = quals_rank2(pp); + +  quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous}} + +  quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous}} +  quals_rank3(pq); +} + +// Test overloading based on derived-to-base conversions +class A { }; +class B : public A { }; +class C : public B { }; +class D : public C { }; + +int* derived1(A*); +char* derived1(const A*); +float* derived1(void*); + +int* derived2(A*); +float* derived2(B*); + +int* derived3(A*); +float* derived3(const B*); +char* derived3(C*); + +void test_derived(B* b, B const* bc, C* c, const C* cc, void* v, D* d) { +  int* d1 = derived1(b); +  char* d2 = derived1(bc); +  int* d3 = derived1(c); +  char* d4 = derived1(cc); +  float* d5 = derived1(v); + +  float* d6 = derived2(b); +  float* d7 = derived2(c); + +  char* d8 = derived3(d); +} + +void derived4(C*); // expected-note{{candidate function not viable: cannot convert from base class pointer 'A *' to derived class pointer 'C *' for 1st argument}} + +void test_base(A* a) { +  derived4(a); // expected-error{{no matching function for call to 'derived4}} +} + +// Test overloading of references.  +// (FIXME: tests binding to determine candidate sets, not overload  +//  resolution per se). +int* intref(int&); +float* intref(const int&); + +void intref_test() { +  float* ir1 = intref(5); +  float* ir2 = intref(5.5); // expected-warning{{implicit conversion turns literal floating-point number into integer}} +} + +void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}} + +void test_base(A& a) { +  derived5(a); // expected-error{{no matching function for call to 'derived5}} +} + +// Test reference binding vs. standard conversions. +int& bind_vs_conv(const double&); +float& bind_vs_conv(int); + +void bind_vs_conv_test() +{ +  int& i1 = bind_vs_conv(1.0f); +  float& f1 = bind_vs_conv((short)1); +} + +// Test that cv-qualifiers get subsumed in the reference binding. +struct X { }; +struct Y { }; +struct Z : X, Y { }; + +int& cvqual_subsume(X&); // expected-note{{candidate function}} +float& cvqual_subsume(const Y&); // expected-note{{candidate function}} + +int& cvqual_subsume2(const X&); // expected-note{{candidate function}} +float& cvqual_subsume2(const volatile Y&); // expected-note{{candidate function}} + +Z get_Z(); + +void cvqual_subsume_test(Z z) { +  cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous}} +  int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous}} +} + +// Test overloading with cv-qualification differences in reference +// binding. +int& cvqual_diff(X&); +float& cvqual_diff(const X&); + +void cvqual_diff_test(X x, Z z) { +  int& i1 = cvqual_diff(x); +  int& i2 = cvqual_diff(z); +} + +// Test overloading with derived-to-base differences in reference +// binding. +struct Z2 : Z { }; + +int& db_rebind(X&); +long& db_rebind(Y&); +float& db_rebind(Z&); + +void db_rebind_test(Z2 z2) { +  float& f1 = db_rebind(z2); +} + +class string { }; +class opt : public string { }; + +struct SR { +  SR(const string&); +}; + +void f(SR) { } + +void g(opt o) { +  f(o); +} + + +namespace PR5756 { +  int &a(void*, int); +  float &a(void*, float); +  void b() {  +    int &ir = a(0,0); +    (void)ir; +  } +} + +// Tests the exact text used to note the candidates +namespace test1 { +  template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} +  void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}  +  void foo(int n); // expected-note {{candidate function not viable: requires 1 argument, but 2 were provided}} +  void foo(unsigned n = 10); // expected-note {{candidate function not viable: requires at most 1 argument, but 2 were provided}} +  void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}} +  void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} +  void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} + +  void test() { +    foo(4, "hello"); //expected-error {{no matching function for call to 'foo'}} +  } +} + +// PR 6014 +namespace test2 { +  struct QFixed { +    QFixed(int i); +    QFixed(long i); +  }; + +  bool operator==(const QFixed &f, int i); + +  class qrgb666 { +    inline operator unsigned int () const; + +    inline bool operator==(const qrgb666 &v) const; +    inline bool operator!=(const qrgb666 &v) const { return !(*this == v); } +  }; +} + +// PR 6117 +namespace test3 { +  struct Base {}; +  struct Incomplete; + +  void foo(Base *); // expected-note 2 {{cannot convert argument of incomplete type}} +  void foo(Base &); // expected-note 2 {{cannot convert argument of incomplete type}} + +  void test(Incomplete *P) { +    foo(P); // expected-error {{no matching function for call to 'foo'}} +    foo(*P); // expected-error {{no matching function for call to 'foo'}} +  } +} + +namespace DerivedToBaseVsVoid { +  struct A { }; +  struct B : A { }; +   +  float &f(void *); +  int &f(const A*); +   +  void g(B *b) { +    int &ir = f(b); +  } +} + +// PR 6398 + PR 6421 +namespace test4 { +  class A; +  class B { +    static void foo(); // expected-note {{not viable}} +    static void foo(int*); // expected-note {{not viable}} +    static void foo(long*); // expected-note {{not viable}} + +    void bar(A *a) {  +      foo(a); // expected-error {{no matching function for call}} +    } +  }; +} + +namespace DerivedToBase { +  struct A { }; +  struct B : A { }; +  struct C : B { }; +   +  int &f0(const A&); +  float &f0(B); +   +  void g() { +    float &fr = f0(C()); +  } +} + +namespace PR6483 { +  struct X0 { +    operator const unsigned int & () const; +  }; + +  struct X1 { +    operator unsigned int & () const; +  }; + +  void f0(const bool &); +  void f1(bool &); // expected-note 2{{not viable}} + +  void g(X0 x0, X1 x1) { +    f0(x0); +    f1(x0); // expected-error{{no matching function for call}} +    f0(x1); +    f1(x1); // expected-error{{no matching function for call}} +  }   +} + +namespace PR6078 { +  struct A { +    A(short); // expected-note{{candidate constructor}} +    A(long); // expected-note{{candidate constructor}} +  }; +  struct S { +    typedef void ft(A); +    operator ft*(); +  }; + +  void f() { +    S()(0); // expected-error{{conversion from 'int' to 'PR6078::A' is ambiguous}} +  } +} + +namespace PR6177 { +  struct String { String(char const*); }; + +  void f(bool const volatile&); // expected-note{{passing argument to parameter here}} +  void f(String); + +  void g() { f(""); } // expected-error{{volatile lvalue reference to type 'const volatile bool' cannot bind to a value of unrelated type 'const char [1]'}} +} + +namespace PR7095 { +  struct X { }; + +  struct Y { +    operator const X*(); + +  private: +    operator X*(); +  }; + +  void f(const X *); +  void g(Y y) { f(y); } +} + +namespace PR7224 { +  class A {}; +  class B : public A {}; + +  int &foo(A *const d); +  float &foo(const A *const d); + +  void bar() +  { +    B *const d = 0; +    B const *const d2 = 0; +    int &ir = foo(d); +    float &fr = foo(d2); +  } +} + +namespace NontrivialSubsequence { +  struct X0; + +  class A { +    operator X0 *(); +  public: +    operator const X0 *(); +  }; +  +  A a; +  void foo( void const * ); + +  void g() { +    foo(a); +  } +} + +// rdar://rdar8499524 +namespace rdar8499524 { +  struct W {}; +  struct S { +      S(...); +  }; + +  void g(const S&); +  void f() { +    g(W()); +  } +} + +namespace rdar9173984 { +  template <typename T, unsigned long N> int &f(const T (&)[N]); +  template <typename T> float &f(const T *); + +  void test() { +    int arr[2] = {0, 0}; +    int *arrp = arr; +    int &ir = f(arr); +    float &fr = f(arrp); +  } +} + +namespace PR9507 { +  void f(int * const&); // expected-note{{candidate function}} +  void f(int const(&)[1]); // expected-note{{candidate function}} +  +  int main() { +    int n[1]; +    f(n); // expected-error{{call to 'f' is ambiguous}} +  } +} + +namespace rdar9803316 { +  void foo(float); +  int &foo(int); + +  void bar() { +    int &ir = (&foo)(0); +  } +} + +namespace IncompleteArg { +  // Ensure that overload resolution attempts to complete argument types when +  // performing ADL. +  template<typename T> struct S { +    friend int f(const S&); +  }; +  extern S<int> s; +  int k = f(s); + +  template<typename T> struct Op { +    friend bool operator==(const Op &, const Op &); +  }; +  extern Op<char> op; +  bool b = op == op; + +  // ... and not in other cases! Nothing here requires U<int()> to be complete. +  // (Note that instantiating U<int()> will fail.) +  template<typename T> struct U { +    T t; +  }; +  struct Consumer { +    template<typename T> +    int operator()(const U<T> &); +  }; +  template<typename T> U<T> &make(); +  Consumer c; +  int n = sizeof(c(make<int()>())); +} + +namespace PR12142 { +  void fun(int (*x)[10]); // expected-note{{candidate function not viable: 1st argument ('const int (*)[10]') would lose const qualifier}} +  void g() { fun((const int(*)[10])0); } // expected-error{{no matching function for call to 'fun'}} +} diff --git a/clang/test/SemaCXX/overload-decl.cpp b/clang/test/SemaCXX/overload-decl.cpp new file mode 100644 index 0000000..c610ff7 --- /dev/null +++ b/clang/test/SemaCXX/overload-decl.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +void f(); +void f(int); +void f(int, float);  +void f(int, int); +void f(int, ...); + +typedef float Float; +void f(int, Float); // expected-note {{previous declaration is here}} + +int f(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +void g(void); // expected-note {{previous declaration is here}} +int g(); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +typedef int INT; + +class X { +  void f(); +  void f(int); // expected-note {{previous declaration is here}} +  void f() const; + +  void f(INT); // expected-error{{cannot be redeclared}} + +  void g(int); // expected-note {{previous declaration is here}} +  void g(int, float); // expected-note {{previous declaration is here}} +  int g(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +  static void g(float); +  static void g(int); // expected-error {{static and non-static member functions with the same parameter types cannot be overloaded}} +}; diff --git a/clang/test/SemaCXX/overload-member-call.cpp b/clang/test/SemaCXX/overload-member-call.cpp new file mode 100644 index 0000000..37c9552 --- /dev/null +++ b/clang/test/SemaCXX/overload-member-call.cpp @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X { +  int& f(int) const; // expected-note 2 {{candidate function}} +  float& f(int); // expected-note 2 {{candidate function}} + +  void test_f(int x) const { +    int& i = f(x); +  } + +  void test_f2(int x) { +    float& f2 = f(x); +  } + +  int& g(int) const; // expected-note 2 {{candidate function}} +  float& g(int); // expected-note 2 {{candidate function}} +  static double& g(double); // expected-note 2 {{candidate function}} + +  void h(int); + +  void test_member() { +    float& f1 = f(0); +    float& f2 = g(0); +    double& d1 = g(0.0); +  } + +  void test_member_const() const { +    int &i1 = f(0); +    int &i2 = g(0); +    double& d1 = g(0.0); +  } + +  static void test_member_static() { +    double& d1 = g(0.0); +    g(0); // expected-error{{call to 'g' is ambiguous}} +  } +}; + +void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp) { +  int& i1 = xc.f(0); +  int& i2 = xcp->f(0); +  float& f1 = x.f(0); +  float& f2 = xp->f(0); +  xv.f(0); // expected-error{{no matching member function for call to 'f'}} +  xvp->f(0); // expected-error{{no matching member function for call to 'f'}} + +  int& i3 = xc.g(0); +  int& i4 = xcp->g(0); +  float& f3 = x.g(0); +  float& f4 = xp->g(0); +  double& d1 = xp->g(0.0); +  double& d2 = X::g(0.0); +  X::g(0); // expected-error{{call to 'g' is ambiguous}} +   +  X::h(0); // expected-error{{call to non-static member function without an object argument}} +} + +struct X1 { +  int& member(); +  float& member() const; +}; + +struct X2 : X1 { }; + +void test_X2(X2 *x2p, const X2 *cx2p) { +  int &ir = x2p->member(); +  float &fr = cx2p->member(); +} + +// Tests the exact text used to note the candidates +namespace test1 { +  class A { +    template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} +    void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}}  +    void foo(int n); // expected-note {{candidate function not viable: requires 1 argument, but 2 were provided}} +    void foo(unsigned n = 10); // expected-note {{candidate function not viable: requires at most 1 argument, but 2 were provided}} +    void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}} +    void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} +    void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} + +    void bar(double d); //expected-note {{candidate function not viable: 'this' argument has type 'const test1::A', but method is not marked const}} +    void bar(int i); //expected-note {{candidate function not viable: 'this' argument has type 'const test1::A', but method is not marked const}} + +    void baz(A &d); // expected-note {{candidate function not viable: 1st argument ('const test1::A') would lose const qualifier}} +    void baz(int i); // expected-note {{candidate function not viable: no known conversion from 'const test1::A' to 'int' for 1st argument}}  +  }; + +  void test() { +    A a; +    a.foo(4, "hello"); //expected-error {{no matching member function for call to 'foo'}} + +    const A b = A(); +    b.bar(0); //expected-error {{no matching member function for call to 'bar'}} + +    a.baz(b); //expected-error {{no matching member function for call to 'baz'}} +  } +} + diff --git a/clang/test/SemaCXX/overload-value-dep-arg.cpp b/clang/test/SemaCXX/overload-value-dep-arg.cpp new file mode 100644 index 0000000..c1834a7 --- /dev/null +++ b/clang/test/SemaCXX/overload-value-dep-arg.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class C { +  C(void*); +}; + +int f(const C&); +int f(unsigned long); + +template<typename T> int f(const T* t) { +  return f(reinterpret_cast<unsigned long>(t)); +} + diff --git a/clang/test/SemaCXX/overloaded-builtin-operators-0x.cpp b/clang/test/SemaCXX/overloaded-builtin-operators-0x.cpp new file mode 100644 index 0000000..6a5a162 --- /dev/null +++ b/clang/test/SemaCXX/overloaded-builtin-operators-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -std=c++11 -verify %s  + +template <class T> +struct X +{ +   operator T() const {return T();} +}; + +void test_char16t(X<char16_t> x) { +   bool b = x == char16_t(); +} diff --git a/clang/test/SemaCXX/overloaded-builtin-operators.cpp b/clang/test/SemaCXX/overloaded-builtin-operators.cpp new file mode 100644 index 0000000..b3c0808 --- /dev/null +++ b/clang/test/SemaCXX/overloaded-builtin-operators.cpp @@ -0,0 +1,239 @@ +// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify %s  +struct yes; +struct no; + +struct Short { +  operator short(); +}; + +struct Long { +  operator long(); +}; + +enum E1 { }; +struct Enum1 { +  operator E1(); +}; + +enum E2 { }; +struct Enum2 { +  operator E2(); +}; + + +struct X {  +  void f(); +}; + +typedef void (X::*pmf)(); +struct Xpmf { +  operator pmf(); +}; + +yes& islong(long); +yes& islong(unsigned long); // FIXME: shouldn't be needed +no& islong(int); + +void f(Short s, Long l, Enum1 e1, Enum2 e2, Xpmf pmf) { +  // C++ [over.built]p8 +  int i1 = +e1; +  int i2 = -e2; + +  // C++  [over.built]p10: +  int i3 = ~s; +  bool b1 = !s; + +  // C++ [over.built]p12 +  (void)static_cast<yes&>(islong(s + l)); +  (void)static_cast<no&>(islong(s + s)); + +  // C++ [over.built]p16 +  (void)(pmf == &X::f); +  (void)(pmf == 0); +   +  // C++ [over.built]p17 +  (void)static_cast<yes&>(islong(s % l)); +  (void)static_cast<yes&>(islong(l << s)); +  (void)static_cast<no&>(islong(s << l)); +  (void)static_cast<yes&>(islong(e1 % l)); +  // FIXME: should pass (void)static_cast<no&>(islong(e1 % e2)); +} + +struct ShortRef { // expected-note{{candidate function (the implicit copy assignment operator)}} +  operator short&(); +}; + +struct LongRef { +  operator volatile long&(); +}; + +struct XpmfRef { // expected-note{{candidate function (the implicit copy assignment operator)}} +  operator pmf&(); +}; + +struct E2Ref { +  operator E2&(); +}; + +void g(ShortRef sr, LongRef lr, E2Ref e2_ref, XpmfRef pmf_ref) { +  // C++ [over.built]p3 +  short s1 = sr++; + +  // C++ [over.built]p3 +  long l1 = lr--; + +  // C++ [over.built]p18 +  short& sr1 = (sr *= lr); +  volatile long& lr1 = (lr *= sr); + +  // C++ [over.built]p20: +  E2 e2r2; +  e2r2 = e2_ref; +   +  pmf &pmr = (pmf_ref = &X::f); // expected-error{{no viable overloaded '='}} +  pmf pmr2; +  pmr2 = pmf_ref; +                +  // C++ [over.built]p22 +  short& sr2 = (sr %= lr); +  volatile long& lr2 = (lr <<= sr); + +  bool b1 = (sr && lr) || (sr || lr); +} + +struct VolatileIntPtr { +  operator int volatile *(); +}; + +struct ConstIntPtr { +  operator int const *(); +}; + +struct VolatileIntPtrRef { +  operator int volatile *&(); +}; + +struct ConstIntPtrRef { +  operator int const *&(); +}; + +void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr, +                    VolatileIntPtrRef vipr, ConstIntPtrRef cipr) { +  const int& cir1 = cip[sr]; +  const int& cir2 = sr[cip]; +  volatile int& vir1 = vip[sr]; +  volatile int& vir2 = sr[vip]; +  bool b1 = (vip == cip); +  long p1 = vip - cip; + +  // C++ [over.built]p5: +  int volatile *vip1 = vipr++; +  int const *cip1 = cipr++; +  int volatile *&vipr1 = ++vipr; +  int const *&cipr1 = --cipr; + +  // C++ [over.built]p6: +  int volatile &ivr = *vip; + +  // C++ [over.built]p8: +  int volatile *vip2 = +vip; +  int i1 = +sr; +  int i2 = -sr; + +  // C++ [over.built]p13: +  int volatile &ivr2 = vip[17]; +  int const &icr2 = 17[cip]; +} + +// C++ [over.match.open]p4 + +void test_assign_restrictions(ShortRef& sr) { +  sr = (short)0; // expected-error{{no viable overloaded '='}} +} + +struct Base { }; +struct Derived1 : Base { }; +struct Derived2 : Base { }; + +template<typename T> +struct ConvertibleToPtrOf { +  operator T*(); +}; + +bool test_with_base_ptrs(ConvertibleToPtrOf<Derived1> d1,  +                         ConvertibleToPtrOf<Derived2> d2) { +  return d1 == d2; // expected-error{{invalid operands}} +} + +// DR425 +struct A { +  template< typename T > operator T() const; +}; + +void test_dr425(A a) { +  // FIXME: lots of candidates here! +  (void)(1.0f * a); // expected-error{{ambiguous}} \ +                    // expected-note 4{{candidate}} \ +                    // expected-note {{remaining 77 candidates omitted; pass -fshow-overloads=all to show them}} +} + +// pr5432 +enum e {X}; + +const int a[][2] = {{1}}; + +int test_pr5432() { +  return a[X][X]; +} + +void f() { +  (void)__extension__(A()); +} + +namespace PR7319 { +  typedef enum { Enum1, Enum2, Enum3 } MyEnum; + +  template<typename X> bool operator>(const X &inX1, const X &inX2); + +  void f() { +    MyEnum e1, e2; +    if (e1 > e2) {} +  } +} + +namespace PR8477 { +  struct Foo { +    operator bool(); +    operator const char *(); +  }; + +  bool doit() { +    Foo foo; +    long long zero = 0; +    (void)(foo + zero); +    (void)(foo - zero); +    (void)(zero + foo); +    (void)(zero[foo]); +    (void)(foo - foo); // expected-error{{use of overloaded operator '-' is ambiguous}} \ +    // expected-note 4{{built-in candidate operator-}} \ +    // expected-note{{candidates omitted}} +    return foo[zero] == zero; +  } +} + +namespace PR7851 { +  struct X { +    operator const void *() const; +    operator void *(); + +    operator const unsigned *() const; +    operator unsigned *(); +  }; + +  void f() { +    X x; +    x[0] = 1; +    *x = 0; +    (void)(x - x); +  } +} diff --git a/clang/test/SemaCXX/overloaded-name.cpp b/clang/test/SemaCXX/overloaded-name.cpp new file mode 100644 index 0000000..6da0354 --- /dev/null +++ b/clang/test/SemaCXX/overloaded-name.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int ovl(int); // expected-note 3{{possible target for call}} +float ovl(float); // expected-note 3{{possible target for call}} + +template<typename T> T ovl(T); // expected-note 3{{possible target for call}} + +void test(bool b) { +  (void)((void)0, ovl); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +  // PR7863 +  (void)(b? ovl : &ovl); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +  (void)(b? ovl<float> : &ovl); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} +  (void)(b? ovl<float> : ovl<float>); +} + +namespace rdar9623945 { +  void f(...) { +  } +   +  class X { +  public: +    const char* text(void); +    void g(void) { +      f(text()); +      f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}} +      f(text()); +      f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}} +    } +  }; +} diff --git a/clang/test/SemaCXX/overloaded-operator-decl.cpp b/clang/test/SemaCXX/overloaded-operator-decl.cpp new file mode 100644 index 0000000..4519a2d --- /dev/null +++ b/clang/test/SemaCXX/overloaded-operator-decl.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +struct X {  +  X(); +  X(int);  +}; + +X operator+(X, X); +X operator-(X, X) { X x; return x; } + +struct Y { +  Y operator-() const; +  void operator()(int x = 17) const; +  int operator[](int); + +  static int operator+(Y, Y); // expected-error{{overloaded 'operator+' cannot be a static member function}} +}; + + +void f(X x) { +  x = operator+(x, x); +} + +X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} + +X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}} + +X operator/(X, X, ...); // expected-error{{overloaded 'operator/' cannot be variadic}} + +X operator%(Y); // expected-error{{overloaded 'operator%' must be a binary operator (has 1 parameter)}} + +void operator()(Y&, int, int); // expected-error{{overloaded 'operator()' must be a non-static member function}} + +typedef int INT; +typedef float FLOAT; +Y& operator++(Y&); +Y operator++(Y&, INT); +X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'FLOAT' (aka 'float'))}} + +int operator+; // expected-error{{'operator+' cannot be the name of a variable or data member}} + +namespace PR6238 { +  static struct { +    void operator()(); +  } plus; +} + +struct PR10839 { +  operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}} +  int operator+; // expected-error{{'operator+' cannot be the name of a variable or data member}} +}; diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp new file mode 100644 index 0000000..8ecb54d --- /dev/null +++ b/clang/test/SemaCXX/overloaded-operator.cpp @@ -0,0 +1,417 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +class X { }; + +X operator+(X, X); + +void f(X x) { +  x = x + x; +} + +struct Y; +struct Z; + +struct Y { +  Y(const Z&); +}; + +struct Z { +  Z(const Y&); +}; + +Y operator+(Y, Y); +bool operator-(Y, Y); // expected-note{{candidate function}} +bool operator-(Z, Z); // expected-note{{candidate function}} + +void g(Y y, Z z) { +  y = y + z; +  bool b = y - z; // expected-error{{use of overloaded operator '-' is ambiguous}} +} + +struct A { +  bool operator==(Z&); // expected-note 2{{candidate function}} +}; + +A make_A(); + +bool operator==(A&, Z&); // expected-note 3{{candidate function}} + +void h(A a, const A ac, Z z) { +  make_A() == z; // expected-warning{{equality comparison result unused}} +  a == z; // expected-error{{use of overloaded operator '==' is ambiguous}} +  ac == z; // expected-error{{invalid operands to binary expression ('const A' and 'Z')}} +} + +struct B { +  bool operator==(const B&) const; + +  void test(Z z) { +    make_A() == z; // expected-warning{{equality comparison result unused}} +  } +}; + +// we shouldn't see warnings about self-comparison, +// this is a member function, we dunno what it'll do +bool i(B b) +{ +  return b == b; +} + +enum Enum1 { }; +enum Enum2 { }; + +struct E1 { +  E1(Enum1) { } +}; + +struct E2 { +  E2(Enum2); +}; + +// C++ [over.match.oper]p3 - enum restriction. +float& operator==(E1, E2);  // expected-note{{candidate function}} + +void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2, Enum1 next_enum1) { +  float &f1 = (e1 == e2); +  float &f2 = (enum1 == e2);  +  float &f3 = (e1 == enum2);  +  float &f4 = (enum1 == next_enum1);  // expected-error{{non-const lvalue reference to type 'float' cannot bind to a temporary of type 'bool'}} +} + +// PR5244 - Argument-dependent lookup would include the two operators below, +// which would break later assumptions and lead to a crash. +class pr5244_foo +{ +  pr5244_foo(int); +  pr5244_foo(char); +}; + +bool operator==(const pr5244_foo& s1, const pr5244_foo& s2); // expected-note{{candidate function}} +bool operator==(char c, const pr5244_foo& s); // expected-note{{candidate function}} + +enum pr5244_bar +{ +    pr5244_BAR +}; + +class pr5244_baz +{ +public: +    pr5244_bar quux; +}; + +void pr5244_barbaz() +{ +  pr5244_baz quuux; +  (void)(pr5244_BAR == quuux.quux); +} + + + +struct PostInc { +  PostInc operator++(int); +  PostInc& operator++(); +}; + +struct PostDec { +  PostDec operator--(int); +  PostDec& operator--(); +}; + +void incdec_test(PostInc pi, PostDec pd) { +  const PostInc& pi1 = pi++; +  const PostDec& pd1 = pd--; +  PostInc &pi2 = ++pi; +  PostDec &pd2 = --pd; +} + +struct SmartPtr { +  int& operator*(); +  long& operator*() const volatile; +}; + +void test_smartptr(SmartPtr ptr, const SmartPtr cptr,  +                   const volatile SmartPtr cvptr) { +  int &ir = *ptr; +  long &lr = *cptr; +  long &lr2 = *cvptr; +} + + +struct ArrayLike { +  int& operator[](int); +}; + +void test_arraylike(ArrayLike a) { +  int& ir = a[17]; +} + +struct SmartRef { +  int* operator&(); +}; + +void test_smartref(SmartRef r) { +  int* ip = &r; +} + +bool& operator,(X, Y); + +void test_comma(X x, Y y) { +  bool& b1 = (x, y); +  X& xr = (x, x); // expected-warning {{expression result unused}} +} + +struct Callable { +  int& operator()(int, double = 2.71828); // expected-note{{candidate function}} +  float& operator()(int, double, long, ...); // expected-note{{candidate function}} + +  double& operator()(float); // expected-note{{candidate function}} +}; + +struct Callable2 { +  int& operator()(int i = 0); +  double& operator()(...) const; +}; + +struct DerivesCallable : public Callable { +}; + +void test_callable(Callable c, Callable2 c2, const Callable2& c2c, +                   DerivesCallable dc) { +  int &ir = c(1); +  float &fr = c(1, 3.14159, 17, 42); + +  c(); // expected-error{{no matching function for call to object of type 'Callable'}} + +  double &dr = c(1.0f); + +  int &ir2 = c2(); +  int &ir3 = c2(1); +  double &fr2 = c2c(); +   +  int &ir4 = dc(17); +  double &fr3 = dc(3.14159f); +} + +typedef float FLOAT; +typedef int& INTREF; +typedef INTREF Func1(FLOAT, double); +typedef float& Func2(int, double); + +struct ConvertToFunc { +  operator Func1*(); // expected-note 2{{conversion candidate of type 'INTREF (*)(FLOAT, double)'}} +  operator Func2&(); // expected-note 2{{conversion candidate of type 'float &(&)(int, double)'}} +  void operator()(); +}; + +struct ConvertToFuncDerived : ConvertToFunc { }; + +void test_funcptr_call(ConvertToFunc ctf, ConvertToFuncDerived ctfd) { +  int &i1 = ctf(1.0f, 2.0); +  float &f1 = ctf((short int)1, 1.0f); +  ctf((long int)17, 2.0); // expected-error{{call to object of type 'ConvertToFunc' is ambiguous}} +  ctf(); + +  int &i2 = ctfd(1.0f, 2.0); +  float &f2 = ctfd((short int)1, 1.0f); +  ctfd((long int)17, 2.0); // expected-error{{call to object of type 'ConvertToFuncDerived' is ambiguous}} +  ctfd(); +} + +struct HasMember { +  int m; +}; + +struct Arrow1 { +  HasMember* operator->(); +}; + +struct Arrow2 { +  Arrow1 operator->(); // expected-note{{candidate function}} +}; + +void test_arrow(Arrow1 a1, Arrow2 a2, const Arrow2 a3) { +  int &i1 = a1->m; +  int &i2 = a2->m; +  a3->m; // expected-error{{no viable overloaded 'operator->'}} +} + +struct CopyConBase { +}; + +struct CopyCon : public CopyConBase { +  CopyCon(const CopyConBase &Base); + +  CopyCon(const CopyConBase *Base) { +    *this = *Base; +  } +}; + +namespace N { +  struct X { }; +} + +namespace M { +  N::X operator+(N::X, N::X); +} + +namespace M { +  void test_X(N::X x) { +    (void)(x + x); +  } +} + +struct AA { bool operator!=(AA&); }; +struct BB : AA {}; +bool x(BB y, BB z) { return y != z; } + + +struct AX {  +  AX& operator ->();	 // expected-note {{declared here}} +  int b; +};  + +void m() { +  AX a;  +  a->b = 0; // expected-error {{circular pointer delegation detected}} +} + +struct CircA { +  struct CircB& operator->(); // expected-note {{declared here}} +  int val; +}; +struct CircB { +  struct CircC& operator->(); // expected-note {{declared here}} +}; +struct CircC { +  struct CircA& operator->(); // expected-note {{declared here}} +}; + +void circ() { +  CircA a; +  a->val = 0; // expected-error {{circular pointer delegation detected}} +} + +// PR5360: Arrays should lead to built-in candidates for subscript. +typedef enum { +  LastReg = 23, +} Register; +class RegAlloc { +  int getPriority(Register r) { +    return usepri[r]; +  } +  int usepri[LastReg + 1]; +}; + +// PR5546: Don't generate incorrect and ambiguous overloads for multi-level +// arrays. +namespace pr5546 +{ +  enum { X }; +  extern const char *const sMoveCommands[][2][2]; +  const char* a() { return sMoveCommands[X][0][0]; } +  const char* b() { return (*(sMoveCommands+X))[0][0]; } +} + +// PR5512 and its discussion +namespace pr5512 { +  struct Y { +    operator short(); +    operator float(); +  }; +  void g_test(Y y) { +    short s = 0; +    // DR507, this should be ambiguous, but we special-case assignment +    s = y; +    // Note: DR507, this is ambiguous as specified +    //s += y; +  } + +  struct S {}; +  void operator +=(int&, S); +  void f(S s) { +    int i = 0; +    i += s; +  } + +  struct A {operator int();}; +  int a; +  void b(A x) { +    a += x; +  } +} + +// PR5900 +namespace pr5900 { +  struct NotAnArray {}; +  void test0() { +    NotAnArray x; +    x[0] = 0; // expected-error {{does not provide a subscript operator}} +  } + +  struct NonConstArray { +    int operator[](unsigned); // expected-note {{candidate}} +  }; +  int test1() { +    const NonConstArray x = NonConstArray(); +    return x[0]; // expected-error {{no viable overloaded operator[] for type}} +  } + +  // Not really part of this PR, but implemented at the same time. +  struct NotAFunction {}; +  void test2() { +    NotAFunction x; +    x(); // expected-error {{does not provide a call operator}} +  } +} + +// Operator lookup through using declarations. +namespace N { +  struct X2 { }; +} + +namespace N2 { +  namespace M { +    namespace Inner { +      template<typename T> +      N::X2 &operator<<(N::X2&, const T&); +    } +    using Inner::operator<<; +  } +} + +void test_lookup_through_using() { +  using namespace N2::M; +  N::X2 x; +  x << 17; +} + +namespace rdar9136502 { +  struct X { +    int i(); +    int i(int); +  }; + +  struct Y { +    Y &operator<<(int); +  }; + +  void f(X x, Y y) { +    y << x.i; // expected-error{{reference to non-static member function must be called}} +  } +} + +namespace rdar9222009 { +class StringRef { +  inline bool operator==(StringRef LHS, StringRef RHS) { // expected-error{{overloaded 'operator==' must be a binary operator (has 3 parameters)}} +    return !(LHS == RHS); // expected-error{{invalid operands to binary expression ('rdar9222009::StringRef' and 'rdar9222009::StringRef')}} +  } +}; + +} + +namespace PR11784 { +  struct A { A& operator=(void (*x)()); }; +  void f(); +  void f(int); +  void g() { A x; x = f; } +} diff --git a/clang/test/SemaCXX/pascal-strings.cpp b/clang/test/SemaCXX/pascal-strings.cpp new file mode 100644 index 0000000..89194b5 --- /dev/null +++ b/clang/test/SemaCXX/pascal-strings.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -fpascal-strings +const wchar_t *pascalString = L"\pThis is a Pascal string"; + +unsigned char a[3] = "\pa"; +unsigned char b[3] = "\pab"; +unsigned char c[3] = "\pabc"; // expected-error {{initializer-string for char array is too long}} diff --git a/clang/test/SemaCXX/pragma-pack.cpp b/clang/test/SemaCXX/pragma-pack.cpp new file mode 100644 index 0000000..1bc738b --- /dev/null +++ b/clang/test/SemaCXX/pragma-pack.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple i686-apple-darwin9 -fsyntax-only -verify %s + +namespace rdar8745206 { + +struct Base { +  int i; +}; + +#pragma pack(push, 1) +struct Sub : public Base { +  char c; +}; +#pragma pack(pop) + +int check[sizeof(Sub) == 5 ? 1 : -1]; + +} + +namespace check2 { + +struct Base { +  virtual ~Base(); +  int x; +}; + +#pragma pack(push, 1) +struct Sub : virtual Base { +  char c; +}; +#pragma pack(pop) + +int check[sizeof(Sub) == 13 ? 1 : -1]; + +} diff --git a/clang/test/SemaCXX/pragma-unused.cpp b/clang/test/SemaCXX/pragma-unused.cpp new file mode 100644 index 0000000..c9ddffa --- /dev/null +++ b/clang/test/SemaCXX/pragma-unused.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -Wunused -verify %s + +struct S { +  void m(int x, int y) { +    int z; +    #pragma unused(x,y,z) +  } +}; diff --git a/clang/test/SemaCXX/pragma-visibility.cpp b/clang/test/SemaCXX/pragma-visibility.cpp new file mode 100644 index 0000000..e3ef97a --- /dev/null +++ b/clang/test/SemaCXX/pragma-visibility.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test1 __attribute__((visibility("hidden"))) { // expected-note{{surrounding namespace with visibility attribute starts here}} +#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}} +} + +// GCC 4.6 accepts this, but the "hidden" leaks past the namespace end. +namespace test2 __attribute__((visibility("hidden"))) { +#pragma GCC visibility push(protected) // expected-error{{#pragma visibility push with no matching #pragma visibility pop}} +} // expected-note{{surrounding namespace with visibility attribute ends here}} + +#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}} + +// <rdar://problem/10871094> +struct A { +  #pragma GCC visibility push(protected) +  #pragma GCC visibility pop +}; + +void f() { +  #pragma GCC visibility push(protected) +  #pragma GCC visibility pop +} diff --git a/clang/test/SemaCXX/prefetch-enum.cpp b/clang/test/SemaCXX/prefetch-enum.cpp new file mode 100644 index 0000000..3c77dae --- /dev/null +++ b/clang/test/SemaCXX/prefetch-enum.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify +// PR5679 + +enum X { A = 3 }; + +void Test() { +  char ch; +  __builtin_prefetch(&ch, 0, A); +} diff --git a/clang/test/SemaCXX/primary-base.cpp b/clang/test/SemaCXX/primary-base.cpp new file mode 100644 index 0000000..a6cbbad --- /dev/null +++ b/clang/test/SemaCXX/primary-base.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class A { virtual void f(); }; +class B : virtual A { }; + +class C : B { }; + +// Since A is already a primary base class, C should be the primary base class +// of F. +class F : virtual A, virtual C { }; + +int sa[sizeof(F) == sizeof(A) ? 1 : -1]; diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp new file mode 100644 index 0000000..a8f6683 --- /dev/null +++ b/clang/test/SemaCXX/pseudo-destructors.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A {}; + +enum Foo { F }; +typedef Foo Bar; // expected-note{{type 'Bar' (aka 'Foo') is declared here}} + +typedef int Integer; +typedef double Double; + +void g(); + +namespace N { +  typedef Foo Wibble; +  typedef int OtherInteger; +} + +template <typename T> +void cv_test(const volatile T* cvt) { +  cvt->T::~T(); // no-warning +} + +void f(A* a, Foo *f, int *i, double *d, int ii) { +  a->~A(); +  a->A::~A(); +   +  a->~foo(); // expected-error{{identifier 'foo' in object destruction expression does not name a type}} +   +  a->~Bar(); // expected-error{{destructor type 'Bar' (aka 'Foo') in object destruction expression does not match the type 'A' of the object being destroyed}} +   +  f->~Bar(); +  f->~Foo(); +  i->~Bar(); // expected-error{{does not match}} +   +  g().~Bar(); // expected-error{{non-scalar}} +   +  f->::~Bar(); +  f->N::~Wibble(); // FIXME: technically, Wibble isn't a class-name +   +  f->::~Bar(17, 42); // expected-error{{cannot have any arguments}} + +  i->~Integer(); +  i->Integer::~Integer(); +  i->N::~OtherInteger(); +  i->N::OtherInteger::~OtherInteger(); +  i->N::OtherInteger::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}} +  i->N::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}} +  i->Integer::~Double(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('Double' (aka 'double')) in pseudo-destructor expression}} + +  ii->~Integer(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} +  ii.~Integer(); + +  cv_test(a); +  cv_test(f); +  cv_test(i); +  cv_test(d); +} + + +typedef int Integer; + +void destroy_without_call(int *ip) { +  ip->~Integer; // expected-error{{called immediately}} +} + +// PR5530 +namespace N1 { +  class X0 { }; +} + +void test_X0(N1::X0 &x0) { +  x0.~X0(); +} + +namespace PR11339 { +  template<class T> +  void destroy(T* p) { +    p->~T(); // ok +    p->~oops(); // expected-error{{expected the class name after '~' to name a destructor}} +  } + +  template void destroy(int*); // expected-note{{in instantiation of function template specialization}} +} diff --git a/clang/test/SemaCXX/ptrtomember-overload-resolution.cpp b/clang/test/SemaCXX/ptrtomember-overload-resolution.cpp new file mode 100644 index 0000000..787e330 --- /dev/null +++ b/clang/test/SemaCXX/ptrtomember-overload-resolution.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +// 13.3.3.2 Ranking implicit conversion sequences +// conversion of A::* to B::* is better than conversion of A::* to C::*, +struct A { +int Ai; +};  + +struct B : public A {};  +struct C : public B {};  + +const char * f(int C::*){ return ""; }  +int f(int B::*) { return 1; }  + +struct D : public C {};  + +const char * g(int B::*){ return ""; }  +int g(int D::*) { return 1; }  + +void test()  +{ +  int i = f(&A::Ai); + +  const char * str = g(&A::Ai); +} + +// conversion of B::* to C::* is better than conversion of A::* to C::* +typedef void (A::*pmfa)(); +typedef void (B::*pmfb)(); +typedef void (C::*pmfc)(); + +struct X { +	operator pmfa(); +	operator pmfb(); +}; + + +void g(pmfc); + +void test2(X x)  +{ +    g(x); +} + diff --git a/clang/test/SemaCXX/ptrtomember.cpp b/clang/test/SemaCXX/ptrtomember.cpp new file mode 100644 index 0000000..aee535e --- /dev/null +++ b/clang/test/SemaCXX/ptrtomember.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct  S { +	int i; + +	int mem(int); +}; + +int foo(int S::* ps, S *s) +{ +    return (s->*ps)(1); // expected-error {{called object type 'int' is not a function or function pointer}} +} + +struct S2 { +  int bitfield : 1; +}; + +int S2::*pf = &S2::bitfield; // expected-error {{address of bit-field requested}} + +struct S3 { +  void m(); +}; + +void f3(S3* p, void (S3::*m)()) { +    p->*m; // expected-error {{reference to non-static member function must be called}} +    (void)(p->*m); // expected-error {{reference to non-static member function must be called}} +    (void)(void*)(p->*m); // expected-error {{reference to non-static member function must be called}} expected-error {{cannot cast from type 'void' to pointer type 'void *'}} +    (void)reinterpret_cast<void*>(p->*m); // expected-error {{reference to non-static member function must be called}} expected-error {{reinterpret_cast from 'void' to 'void *' is not allowed}} +    if (p->*m) {} // expected-error {{reference to non-static member function must be called}} expected-error {{value of type 'void' is not contextually convertible to 'bool'}} +    if (!(p->*m)) {} // expected-error {{reference to non-static member function must be called}} expected-error {{invalid argument type 'void' to unary expression}} +    if (p->m) {}; // expected-error {{reference to non-static member function must be called}} expected-error {{value of type 'void' is not contextually convertible to 'bool'}} +    if (!p->m) {}; // expected-error {{reference to non-static member function must be called}} expected-error {{invalid argument type 'void' to unary expression}} +} diff --git a/clang/test/SemaCXX/qual-id-test.cpp b/clang/test/SemaCXX/qual-id-test.cpp new file mode 100644 index 0000000..9994d75 --- /dev/null +++ b/clang/test/SemaCXX/qual-id-test.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +namespace A +{ +    namespace B +    { +        struct base // expected-note{{object type}} +        { +            void x() {} +            void y() {} +        }; +    } + +    struct member +    { +        void foo(); +    }; + +    struct middleman +    { +        member * operator->() { return 0; } +    }; + +    struct sub : B::base +    { +        void x() {} +        middleman operator->() { return middleman(); } +    }; +} + +struct bad +{ +  int x(); +}; + +namespace C +{ +    void fun() +    { +        A::sub a; + +        a.x(); +     +        a.sub::x(); +        a.base::x(); + +        a.B::base::x(); // expected-error{{use of undeclared identifier 'B'}} + +        a.A::sub::x(); +        a.A::B::base::x(); + +        a.bad::x(); // expected-error{{'bad::x' is not a member of class 'A::sub'}} + +        a->foo(); +        a->member::foo(); +        a->A::member::foo(); +    } + +    void fun2() +    { +        A::sub *a; + +        a->x(); + +        a->sub::x(); +        a->base::x(); + +        a->B::base::x(); // expected-error{{use of undeclared identifier 'B'}} + +        a->A::sub::x(); +        a->A::B::base::x(); + +        a->bad::x(); // expected-error{{'bad::x' is not a member of class 'A::sub'}} + +        (*a)->foo(); +        (*a)->member::foo(); +        (*a)->A::member::foo(); +    } + +    void fun3() +    { +        int i; +        i.foo(); // expected-error{{member reference base type 'int' is not a structure or union}} +    } + +    void fun4a() { +      A::sub *a; +       +      typedef A::member base; // expected-note{{current scope}} +      a->base::x(); // expected-error{{ambiguous}}       +    } + +    void fun4b() { +      A::sub *a; +       +      typedef A::B::base base; +      a->base::x(); +    } +   +    template<typename T> +    void fun5() +    { +        T a; +        a.x(); +        a->foo(); + +        a.A::sub::x(); +        a.A::B::base::x(); +        a->A::member::foo(); + +        a.bad::x(); // expected-error{{'bad::x' is not a member of class 'A::sub'}} +    } + +  void test_fun5() { +    fun5<A::sub>(); // expected-note{{instantiation}} +  } +   +  template<typename T> +  void fun6() { +    T a; +    a.sub::x(); +    a.base::x(); +    a->member::foo(); +    a.B::base::x(); // expected-error{{use of undeclared identifier 'B'}} +   } +   +  void test_fun6() { +    fun6<A::sub>(); // expected-note{{instantiation}} +  } +   +} + +// PR4703 +struct a { +  int a; +  static int sa; +}; + +a a; + +int a::sa = a.a; // expected-error {{invalid use of non-static data member 'a'}} + + +namespace PR6645 { +  typedef int foo; +  namespace Inner { +    typedef int PR6645::foo; // expected-error{{typedef declarator cannot be qualified}} \ +    // expected-error{{cannot define or redeclare 'foo' here because namespace 'Inner' does not enclose namespace 'PR6645'}} +  } +} diff --git a/clang/test/SemaCXX/qualification-conversion.cpp b/clang/test/SemaCXX/qualification-conversion.cpp new file mode 100644 index 0000000..f1af5bf --- /dev/null +++ b/clang/test/SemaCXX/qualification-conversion.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s  +int* quals1(int const * p); +int* quals2(int const * const * pp); +int* quals3(int const * * const * ppp); // expected-note{{candidate function}} + +void test_quals(int * p, int * * pp, int * * * ppp) { +  int const * const * pp2 = pp;  +  quals1(p); +  quals2(pp); +  quals3(ppp); // expected-error {{no matching}} +} + +struct A {}; +void mquals1(int const A::*p); +void mquals2(int const A::* const A::*pp); +void mquals3(int const A::* A::* const A::*ppp);  // expected-note{{candidate function}} + +void test_mquals(int A::*p, int A::* A::*pp, int A::* A::* A::*ppp) { +  int const A::* const A::* pp2 = pp; +  mquals1(p); +  mquals2(pp); +  mquals3(ppp); // expected-error {{no matching}} +} + +void aquals1(int const (*p)[1]); +void aquals2(int * const (*pp)[1]); +void aquals2a(int const * (*pp2)[1]); // expected-note{{candidate function}} + +void test_aquals(int (*p)[1], int * (*pp)[1], int * (*pp2)[1]) { +  int const (*p2)[1] = p; +  aquals1(p); +  aquals2(pp); +  aquals2a(pp2); // expected-error {{no matching}} +} diff --git a/clang/test/SemaCXX/qualified-id-lookup.cpp b/clang/test/SemaCXX/qualified-id-lookup.cpp new file mode 100644 index 0000000..d65a468 --- /dev/null +++ b/clang/test/SemaCXX/qualified-id-lookup.cpp @@ -0,0 +1,153 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +namespace Ns { +  int f(); // expected-note{{previous declaration is here}} + +  enum E { +    Enumerator +  }; +} +namespace Ns { +  double f(); // expected-error{{functions that differ only in their return type cannot be overloaded}} + +  int x = Enumerator; +} + +namespace Ns2 { +  float f(); +} + +int y = Ns::Enumerator; + +namespace Ns2 { +  float f(int); // expected-note{{previous declaration is here}} +} + +namespace Ns2 { +  double f(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} +} + +namespace N { +  int& f1(); +} + +namespace N { +  struct f1 { +    static int member; + +    typedef int type; + +    void foo(type); +  }; + +  void test_f1() { +    int &i1 = f1(); +  } +} + +void N::f1::foo(int i) {  +  f1::member = i;  +  f1::type &ir = i; +} + +namespace N { +  float& f1(int x) { +    N::f1::type& i1 = x; +    f1::type& i2 = x; +  } + +  struct f2 { +    static int member; +  }; +  void f2(); +} + +int i1 = N::f1::member; +typedef struct N::f1 type1; +int i2 = N::f2::member; +typedef struct N::f2 type2; + +void test_f1(int i) { +  int &v1 = N::f1(); +  float &v2 = N::f1(i); +  int v3 = ::i1; +  int v4 = N::f1::member; +} + +typedef int f2_type; +namespace a { +  typedef int f2_type(int, int); + +  void test_f2() { +    ::f2_type(1, 2); // expected-error {{excess elements in scalar initializer}} +  } +} + +// PR clang/3291 +namespace a {   +  namespace a {   // A1 +    namespace a { // A2 +      int i; +    } +  } +} + +void test_a() { +  a::a::i = 3; // expected-error{{no member named 'i'}} +  a::a::a::i = 4; +} +   +struct Undef { // expected-note{{definition of 'Undef' is not complete until the closing '}'}} +  typedef int type; + +  Undef::type member; + +  static int size = sizeof(Undef); // expected-error{{invalid application of 'sizeof' to an incomplete type 'Undef'}} + +  int f(); +}; + +int Undef::f() { +  return sizeof(Undef); +} + +// PR clang/5667 +namespace test1 { +  template <typename T> struct is_class { +    enum { value = 0 }; +  }; + +  template <typename T> class ClassChecker { +    bool isClass() { +      return is_class<T>::value; +    } +  }; + +  template class ClassChecker<int>;   +} + +namespace PR6830 { +  namespace foo { + +    class X { +    public: +      X() {} +    }; + +  }  // namespace foo + +  class Z { +  public: +    explicit Z(const foo::X& x) {} + +    void Work() {} +  }; + +  void Test() { +    Z(foo::X()).Work(); +  } +} + +namespace pr12339 { +  extern "C" void i; +  pr12339::FOO  // expected-error{{no type named 'FOO' in namespace 'pr12339'}} +}  // expected-error{{expected unqualified-id}} diff --git a/clang/test/SemaCXX/qualified-member-enum.cpp b/clang/test/SemaCXX/qualified-member-enum.cpp new file mode 100644 index 0000000..83b0a59 --- /dev/null +++ b/clang/test/SemaCXX/qualified-member-enum.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +// Check that this doesn't crash. +struct A { +  enum {LABEL}; +}; +int f() { +  return A().A::LABEL; +} + diff --git a/clang/test/SemaCXX/qualified-names-diag.cpp b/clang/test/SemaCXX/qualified-names-diag.cpp new file mode 100644 index 0000000..c8b5746 --- /dev/null +++ b/clang/test/SemaCXX/qualified-names-diag.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace foo { +  namespace wibble { +    struct x { int y; }; + +    namespace bar { +      namespace wonka { +        struct x { +          struct y { }; +        }; +      } +    } +  } +} + +namespace bar { +  typedef int y; + +  struct incomplete; // expected-note{{forward declaration of 'bar::incomplete'}} +} +void test() { +  foo::wibble::x a; +  ::bar::y b; +  a + b; // expected-error{{invalid operands to binary expression ('foo::wibble::x' and '::bar::y' (aka 'int'))}} + +  ::foo::wibble::bar::wonka::x::y c; +  c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' and '::bar::y' (aka 'int'))}} + +  (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete'}} +} + +int ::foo::wibble::bar::wonka::x::y::* ptrmem; + diff --git a/clang/test/SemaCXX/qualified-names-print.cpp b/clang/test/SemaCXX/qualified-names-print.cpp new file mode 100644 index 0000000..2099268 --- /dev/null +++ b/clang/test/SemaCXX/qualified-names-print.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -ast-print %s 2>&1 | grep "N::M::X<INT>::value" +namespace N { +  namespace M { +    template<typename T> +    struct X { +      enum { value }; +    }; +  } +} + +typedef int INT; + +int test() { +  return N::M::X<INT>::value; +} diff --git a/clang/test/SemaCXX/redeclared-alias-template.cpp b/clang/test/SemaCXX/redeclared-alias-template.cpp new file mode 100644 index 0000000..09e9d0d --- /dev/null +++ b/clang/test/SemaCXX/redeclared-alias-template.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template<typename T> using A = int; // expected-note 2{{previous}} +template<typename T> using A = char; // expected-error {{type alias template redefinition with different types ('char' vs 'int')}} +template<typename T1, typename T2> using A = T1; // expected-error {{too many template parameters in template redeclaration}} + +template<typename T1, typename T2> using B = T1; // expected-note {{previous}} +template<typename T2, typename T1> using B = T1; // expected-error {{type alias template redefinition with different types}} + + +template<typename> struct S; +template<template<typename> class F> using FInt = F<int>; +template<typename X> using SXRInt = FInt<S<X>::template R>; +template<typename X> using SXRInt = typename S<X>::template R<int>; // ok, redeclaration. + +template<template<typename> class> struct TT; + +namespace FilterLookup { +  TT<A> f(); // expected-note {{previous declaration is here}} + +  template<typename> using A = int; +  TT<A> f(); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} diff --git a/clang/test/SemaCXX/redeclared-auto.cpp b/clang/test/SemaCXX/redeclared-auto.cpp new file mode 100644 index 0000000..87ad6bd --- /dev/null +++ b/clang/test/SemaCXX/redeclared-auto.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +extern int a; +auto a = 0; // expected-note 2{{here}} +auto a = 0; // expected-error {{redefinition}} +int a = 0; // expected-error {{redefinition}} +extern auto a; // expected-error {{requires an initializer}} + +extern int b; // expected-note {{here}} +auto b = 0.0; // expected-error {{different type}} + +struct S { +  static int a; +  static int b; // expected-note {{here}} +}; + +auto S::a = 0; // expected-note 2{{here}} +auto S::a; // expected-error {{redefinition}} expected-error {{requires an initializer}} +int S::a = 0; // expected-error {{redefinition}} + +auto S::b = 0.0; // expected-error {{different type}} + +void f() { +  extern int a; +  extern auto a; // expected-error {{requires an initializer}} +} diff --git a/clang/test/SemaCXX/ref-init-ambiguous.cpp b/clang/test/SemaCXX/ref-init-ambiguous.cpp new file mode 100644 index 0000000..ce47e10 --- /dev/null +++ b/clang/test/SemaCXX/ref-init-ambiguous.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +enum E2 { }; + +struct A {  +  operator E2&(); // expected-note 3 {{candidate function}} +}; + +struct B {  +  operator E2&(); // expected-note 3 {{candidate function}} +}; + +struct C : B, A {  +}; + +void test(C c) { +  const E2 &e2 = c; // expected-error {{reference initialization of type 'const E2 &' with initializer of type 'C' is ambiguous}} +} + +void foo(const E2 &);// expected-note{{passing argument to parameter here}} + +const E2 & re(C c) { +    foo(c); // expected-error {{reference initialization of type 'const E2 &' with initializer of type 'C' is ambiguous}} + +    return c; // expected-error {{reference initialization of type 'const E2 &' with initializer of type 'C' is ambiguous}} +} + + diff --git a/clang/test/SemaCXX/references.cpp b/clang/test/SemaCXX/references.cpp new file mode 100644 index 0000000..70d3799 --- /dev/null +++ b/clang/test/SemaCXX/references.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +int g(int); + +void f() { +  int i; +  int &r = i; +  r = 1; +  int *p = &r; +  int &rr = r; +  int (&rg)(int) = g; +  rg(i); +  int a[3]; +  int (&ra)[3] = a; +  ra[1] = i; +  int *Q; +  int *& P = Q; +  P[1] = 1; +} + +typedef int t[1]; +void test2() { +    t a; +    t& b = a; + + +    int c[3]; +    int (&rc)[3] = c; +} + +// C++ [dcl.init.ref]p5b1 +struct A { }; +struct B : A { } b; + +void test3() { +  double d = 2.0; +  double& rd = d; // rd refers to d +  const double& rcd = d; // rcd refers to d + +  A& ra = b; // ra refers to A subobject in b +  const A& rca = b; // rca refers to A subobject in b +} + +B fB(); + +// C++ [dcl.init.ref]p5b2 +void test4() { +  double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}} +  int i = 2; +  double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}} + +  const A& rca = fB(); +} + +void test5() { +  //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 +  const volatile int cvi = 1; +  const int& r = cvi; // expected-error{{binding of reference to type 'const int' to a value of type 'const volatile int' drops qualifiers}} +} + +// C++ [dcl.init.ref]p3 +int& test6(int& x) { +  int& yo; // expected-error{{declaration of reference variable 'yo' requires an initializer}} + +  return x; +} +int& not_initialized_error; // expected-error{{declaration of reference variable 'not_initialized_error' requires an initializer}} +extern int& not_initialized_okay; + +class Test6 { // expected-warning{{class 'Test6' does not declare any constructor to initialize its non-modifiable members}} +  int& okay; // expected-note{{reference member 'okay' will never be initialized}} +}; + +struct C : B, A { }; + +void test7(C& c) { +  A& a1 = c; // expected-error {{ambiguous conversion from derived class 'C' to base class 'A':}} +} + +// C++ [dcl.ref]p1, C++ [dcl.ref]p4 +void test8(int& const,// expected-error{{'const' qualifier may not be applied to a reference}} +            +           void&,     // expected-error{{cannot form a reference to 'void'}} +           int& &)    // expected-error{{type name declared as a reference to a reference}} +{ +  typedef int& intref; +  typedef intref& intrefref; // C++ DR 106: reference collapsing + +  typedef intref const intref_c; // okay. FIXME: how do we verify that this is the same type as intref? +} + + +class string { +  char *Data; +  unsigned Length; +public: +  string();  +  ~string(); +}; + +string getInput(); + +void test9() { +  string &s = getInput(); // expected-error{{lvalue reference}} +} + +void test10() { +  __attribute((vector_size(16))) typedef int vec4; +  typedef __attribute__(( ext_vector_type(4) )) int ext_vec4; +   +  vec4 v; +  int &a = v[0]; // expected-error{{non-const reference cannot bind to vector element}} +  const int &b = v[0]; +   +  ext_vec4 ev; +  int &c = ev.x; // expected-error{{non-const reference cannot bind to vector element}} +  const int &d = ev.x; +} + +namespace PR7149 { +  template<typename T> struct X0 +  { +    T& first; +    X0(T& p1) : first(p1) { } +  }; + + +  void f() +  { +    int p1[1]; +    X0< const int[1]> c(p1); +  } +} + +namespace PR8608 { +  bool& f(unsigned char& c) { return (bool&)c; } +} + +// The following crashed trying to recursively evaluate the LValue. +const int &do_not_crash = do_not_crash; diff --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp new file mode 100644 index 0000000..7f41b93 --- /dev/null +++ b/clang/test/SemaCXX/reinterpret-cast.cpp @@ -0,0 +1,292 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast %s + +#include <stdint.h> + +enum test { testval = 1 }; +struct structure { int m; }; +typedef void (*fnptr)(); + +// Test the conversion to self. +void self_conversion() +{ +  // T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't +  // cast away constness, and is integral, enumeration, pointer or  +  // pointer-to-member. +  int i = 0; +  (void)reinterpret_cast<int>(i); + +  test e = testval; +  (void)reinterpret_cast<test>(e); + +  // T*->T* is allowed +  int *pi = 0; +  (void)reinterpret_cast<int*>(pi); + +  const int structure::*psi = 0; +  (void)reinterpret_cast<const int structure::*>(psi); + +  structure s; +  (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}} + +  float f = 0.0f; +  (void)reinterpret_cast<float>(f); // expected-error {{reinterpret_cast from 'float' to 'float' is not allowed}} +} + +// Test conversion between pointer and integral types, as in /3 and /4. +void integral_conversion() +{ +  void *vp = reinterpret_cast<void*>(testval); +  intptr_t i = reinterpret_cast<intptr_t>(vp); +  (void)reinterpret_cast<float*>(i); +  fnptr fnp = reinterpret_cast<fnptr>(i); +  (void)reinterpret_cast<char>(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}} +  (void)reinterpret_cast<intptr_t>(fnp); +} + +void pointer_conversion() +{ +  int *p1 = 0; +  float *p2 = reinterpret_cast<float*>(p1); +  structure *p3 = reinterpret_cast<structure*>(p2); +  typedef int **ppint; +  ppint *deep = reinterpret_cast<ppint*>(p3); +  (void)reinterpret_cast<fnptr*>(deep); +} + +void constness() +{ +  int ***const ipppc = 0; +  // Valid: T1* -> T2 const* +  int const *icp = reinterpret_cast<int const*>(ipppc); +  // Invalid: T1 const* -> T2* +  (void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'const int *' to 'int *' casts away qualifiers}} +  // Invalid: T1*** -> T2 const* const** +  int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***' to 'const int *const **' casts away qualifiers}} +  // Valid: T1* -> T2* +  int *ip = reinterpret_cast<int*>(icpcpp); +  // Valid: T* -> T const* +  (void)reinterpret_cast<int const*>(ip); +  // Valid: T*** -> T2 const* const* const* +  (void)reinterpret_cast<int const* const* const*>(ipppc); +} + +void fnptrs() +{ +  typedef int (*fnptr2)(int); +  fnptr fp = 0; +  (void)reinterpret_cast<fnptr2>(fp); +  void *vp = reinterpret_cast<void*>(fp); +  (void)reinterpret_cast<fnptr>(vp); +} + +void refs() +{ +  long l = 0; +  char &c = reinterpret_cast<char&>(l); +  // Bad: from rvalue +  (void)reinterpret_cast<int&>(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}} +} + +void memptrs() +{ +  const int structure::*psi = 0; +  (void)reinterpret_cast<const float structure::*>(psi); +  (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'const int structure::*' to 'int structure::*' casts away qualifiers}} + +  void (structure::*psf)() = 0; +  (void)reinterpret_cast<int (structure::*)()>(psf); + +  (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'const int structure::*' to 'void (structure::*)()' is not allowed}} +  (void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (structure::*)()' to 'int structure::*' is not allowed}} + +  // Cannot cast from integers to member pointers, not even the null pointer +  // literal. +  (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (structure::*)()' is not allowed}} +  (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int structure::*' is not allowed}} +} + +namespace PR5545 { +// PR5545 +class A; +class B; +void (A::*a)(); +void (B::*b)() = reinterpret_cast<void (B::*)()>(a); +} + +// <rdar://problem/8018292> +void const_arrays() { +  typedef char STRING[10]; +  const STRING *s; +  const char *c; + +  (void)reinterpret_cast<char *>(s); // expected-error {{reinterpret_cast from 'const STRING *' (aka 'char const (*)[10]') to 'char *' casts away qualifiers}} +  (void)reinterpret_cast<const STRING *>(c); +} + +namespace PR9564 { +  struct a { int a : 10; }; a x; +  int *y = &reinterpret_cast<int&>(x.a); // expected-error {{not allowed}} + +  __attribute((ext_vector_type(4))) typedef float v4; +  float& w(v4 &a) { return reinterpret_cast<float&>(a[1]); } // expected-error {{not allowed}} +} + +void dereference_reinterpret_cast() { +  struct A {}; +  typedef A A2; +  class B {}; +  typedef B B2; +  A a; +  B b; +  A2 a2; +  B2 b2; +  long l; +  double d; +  float f; +  char c; +  unsigned char uc; +  void* v_ptr; +  (void)reinterpret_cast<double&>(l);  // expected-warning {{reinterpret_cast from 'long' to 'double &' has undefined behavior}} +  (void)*reinterpret_cast<double*>(&l);  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}} +  (void)reinterpret_cast<double&>(f);  // expected-warning {{reinterpret_cast from 'float' to 'double &' has undefined behavior}} +  (void)*reinterpret_cast<double*>(&f);  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'float *' has undefined behavior}} +  (void)reinterpret_cast<float&>(l);  // expected-warning {{reinterpret_cast from 'long' to 'float &' has undefined behavior}} +  (void)*reinterpret_cast<float*>(&l);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'long *' has undefined behavior}} +  (void)reinterpret_cast<float&>(d);  // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}} +  (void)*reinterpret_cast<float*>(&d);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}} + +  // TODO: add warning for tag types +  (void)reinterpret_cast<A&>(b); +  (void)*reinterpret_cast<A*>(&b); +  (void)reinterpret_cast<B&>(a); +  (void)*reinterpret_cast<B*>(&a); +  (void)reinterpret_cast<A2&>(b2); +  (void)*reinterpret_cast<A2*>(&b2); +  (void)reinterpret_cast<B2&>(a2); +  (void)*reinterpret_cast<B2*>(&a2); + +  // Casting to itself is allowed +  (void)reinterpret_cast<A&>(a); +  (void)*reinterpret_cast<A*>(&a); +  (void)reinterpret_cast<B&>(b); +  (void)*reinterpret_cast<B*>(&b); +  (void)reinterpret_cast<long&>(l); +  (void)*reinterpret_cast<long*>(&l); +  (void)reinterpret_cast<double&>(d); +  (void)*reinterpret_cast<double*>(&d); +  (void)reinterpret_cast<char&>(c); +  (void)*reinterpret_cast<char*>(&c); + +  // Casting to and from chars are allowable +  (void)reinterpret_cast<A&>(c); +  (void)*reinterpret_cast<A*>(&c); +  (void)reinterpret_cast<B&>(c); +  (void)*reinterpret_cast<B*>(&c); +  (void)reinterpret_cast<long&>(c); +  (void)*reinterpret_cast<long*>(&c); +  (void)reinterpret_cast<double&>(c); +  (void)*reinterpret_cast<double*>(&c); +  (void)reinterpret_cast<char&>(l); +  (void)*reinterpret_cast<char*>(&l); +  (void)reinterpret_cast<char&>(d); +  (void)*reinterpret_cast<char*>(&d); +  (void)reinterpret_cast<char&>(f); +  (void)*reinterpret_cast<char*>(&f); + +  // Casting from void pointer. +  (void)*reinterpret_cast<A*>(v_ptr); +  (void)*reinterpret_cast<B*>(v_ptr); +  (void)*reinterpret_cast<long*>(v_ptr); +  (void)*reinterpret_cast<double*>(v_ptr); +  (void)*reinterpret_cast<float*>(v_ptr); + +  // Casting to void pointer +  (void)*reinterpret_cast<void*>(&a); +  (void)*reinterpret_cast<void*>(&b); +  (void)*reinterpret_cast<void*>(&l); +  (void)*reinterpret_cast<void*>(&d); +  (void)*reinterpret_cast<void*>(&f); +} + +void reinterpret_cast_whitelist () { +  // the dynamic type of the object +  int a; +  float b; +  (void)reinterpret_cast<int&>(a); +  (void)*reinterpret_cast<int*>(&a); +  (void)reinterpret_cast<float&>(b); +  (void)*reinterpret_cast<float*>(&b); + +  // a cv-qualified version of the dynamic object +  (void)reinterpret_cast<const int&>(a); +  (void)*reinterpret_cast<const int*>(&a); +  (void)reinterpret_cast<volatile int&>(a); +  (void)*reinterpret_cast<volatile int*>(&a); +  (void)reinterpret_cast<const volatile int&>(a); +  (void)*reinterpret_cast<const volatile int*>(&a); +  (void)reinterpret_cast<const float&>(b); +  (void)*reinterpret_cast<const float*>(&b); +  (void)reinterpret_cast<volatile float&>(b); +  (void)*reinterpret_cast<volatile float*>(&b); +  (void)reinterpret_cast<const volatile float&>(b); +  (void)*reinterpret_cast<const volatile float*>(&b); + +  // a type that is the signed or unsigned type corresponding to the dynamic +  // type of the object +  signed d; +  unsigned e; +  (void)reinterpret_cast<signed&>(d); +  (void)*reinterpret_cast<signed*>(&d); +  (void)reinterpret_cast<signed&>(e); +  (void)*reinterpret_cast<signed*>(&e); +  (void)reinterpret_cast<unsigned&>(d); +  (void)*reinterpret_cast<unsigned*>(&d); +  (void)reinterpret_cast<unsigned&>(e); +  (void)*reinterpret_cast<unsigned*>(&e); + +  // a type that is the signed or unsigned type corresponding a cv-qualified +  // version of the dynamic type the object +  (void)reinterpret_cast<const signed&>(d); +  (void)*reinterpret_cast<const signed*>(&d); +  (void)reinterpret_cast<const signed&>(e); +  (void)*reinterpret_cast<const signed*>(&e); +  (void)reinterpret_cast<const unsigned&>(d); +  (void)*reinterpret_cast<const unsigned*>(&d); +  (void)reinterpret_cast<const unsigned&>(e); +  (void)*reinterpret_cast<const unsigned*>(&e); +  (void)reinterpret_cast<volatile signed&>(d); +  (void)*reinterpret_cast<volatile signed*>(&d); +  (void)reinterpret_cast<volatile signed&>(e); +  (void)*reinterpret_cast<volatile signed*>(&e); +  (void)reinterpret_cast<volatile unsigned&>(d); +  (void)*reinterpret_cast<volatile unsigned*>(&d); +  (void)reinterpret_cast<volatile unsigned&>(e); +  (void)*reinterpret_cast<volatile unsigned*>(&e); +  (void)reinterpret_cast<const volatile signed&>(d); +  (void)*reinterpret_cast<const volatile signed*>(&d); +  (void)reinterpret_cast<const volatile signed&>(e); +  (void)*reinterpret_cast<const volatile signed*>(&e); +  (void)reinterpret_cast<const volatile unsigned&>(d); +  (void)*reinterpret_cast<const volatile unsigned*>(&d); +  (void)reinterpret_cast<const volatile unsigned&>(e); +  (void)*reinterpret_cast<const volatile unsigned*>(&e); + +  // an aggregate or union type that includes one of the aforementioned types +  // among its members (including, recursively, a member of a subaggregate or +  // contained union) +  // TODO: checking is not implemented for tag types + +  // a type that is a (possible cv-qualified) base class type of the dynamic +  // type of the object +  // TODO: checking is not implemented for tag types + +  // a char or unsigned char type +  (void)reinterpret_cast<char&>(a); +  (void)*reinterpret_cast<char*>(&a); +  (void)reinterpret_cast<unsigned char&>(a); +  (void)*reinterpret_cast<unsigned char*>(&a); +  (void)reinterpret_cast<char&>(b); +  (void)*reinterpret_cast<char*>(&b); +  (void)reinterpret_cast<unsigned char&>(b); +  (void)*reinterpret_cast<unsigned char*>(&b); +} diff --git a/clang/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp b/clang/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp new file mode 100644 index 0000000..9cdf5a1 --- /dev/null +++ b/clang/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s + +void fnptrs() +{ +  typedef void (*fnptr)(); +  fnptr fp = 0; +  void *vp = reinterpret_cast<void*>(fp); // expected-warning {{cast between pointer-to-function and pointer-to-object is an extension}} +  (void)reinterpret_cast<fnptr>(vp); // expected-warning {{cast between pointer-to-function and pointer-to-object is an extension}} +} diff --git a/clang/test/SemaCXX/return-noreturn.cpp b/clang/test/SemaCXX/return-noreturn.cpp new file mode 100644 index 0000000..617de00 --- /dev/null +++ b/clang/test/SemaCXX/return-noreturn.cpp @@ -0,0 +1,140 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default +// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default + +// A destructor may be marked noreturn and should still influence the CFG. +void pr6884_abort() __attribute__((noreturn)); + +struct pr6884_abort_struct { +  pr6884_abort_struct() {} +  ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); } +}; + +struct other { ~other() {} }; + +// Ensure that destructors from objects are properly modeled in the CFG despite +// the presence of switches, case statements, labels, and blocks. These tests +// try to cover bugs reported in both PR6884 and PR10063. +namespace abort_struct_complex_cfgs { +  int basic(int x) { +    switch (x) { default: pr6884_abort(); } +  } +  int f1(int x) { +    switch (x) default: pr6884_abort_struct(); +  } +  int f2(int x) { +    switch (x) { default: pr6884_abort_struct(); } +  } +  int f2_positive(int x) { +    switch (x) { default: ; } +  } // expected-warning {{control reaches end of non-void function}} +  int f3(int x) { +    switch (x) { default: { pr6884_abort_struct(); } } +  } +  int f4(int x) { +    switch (x) default: L1: L2: case 4: pr6884_abort_struct(); +  } +  int f5(int x) { +    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); } +  } +  int f6(int x) { +    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } +  } + +  // Test that these constructs work even when extraneous blocks are created +  // before and after the switch due to implicit destructors. +  int g1(int x) { +    other o; +    switch (x) default: pr6884_abort_struct(); +  } +  int g2(int x) { +    other o; +    switch (x) { default: pr6884_abort_struct(); } +  } +  int g2_positive(int x) { +    other o; +    switch (x) { default: ; } +  } // expected-warning {{control reaches end of non-void function}} +  int g3(int x) { +    other o; +    switch (x) { default: { pr6884_abort_struct(); } } +  } +  int g4(int x) { +    other o; +    switch (x) default: L1: L2: case 4: pr6884_abort_struct(); +  } +  int g5(int x) { +    other o; +    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); } +  } +  int g6(int x) { +    other o; +    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } +  } + +  // Test that these constructs work even with variables carrying the no-return +  // destructor instead of temporaries. +  int h1(int x) { +    other o; +    switch (x) default: pr6884_abort_struct a; +  } +  int h2(int x) { +    other o; +    switch (x) { default: pr6884_abort_struct a; } +  } +  int h3(int x) { +    other o; +    switch (x) { default: { pr6884_abort_struct a; } } +  } +  int h4(int x) { +    other o; +    switch (x) default: L1: L2: case 4: pr6884_abort_struct a; +  } +  int h5(int x) { +    other o; +    switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; } +  } +  int h6(int x) { +    other o; +    switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; } +  } +} + +// PR9380 +struct PR9380 { +  ~PR9380(); +}; +struct PR9380_B : public PR9380 { +  PR9380_B( const PR9380& str ); +}; +void test_PR9380(const PR9380& aKey) { +  const PR9380& flatKey = PR9380_B(aKey); +} + +// Array of objects with destructors.  This is purely a coverage test case. +void test_array() { +  PR9380 a[2]; +} + +// Test classes wrapped in typedefs.  This is purely a coverage test case +// for CFGImplictDtor::getDestructorDecl(). +void test_typedefs() { +  typedef PR9380 PR9380_Ty; +  PR9380_Ty test; +  PR9380_Ty test2[20]; +} + +// PR9412 - Handle CFG traversal with null successors. +enum PR9412_MatchType { PR9412_Exact }; + +template <PR9412_MatchType type> int PR9412_t() { +  switch (type) { +    case PR9412_Exact: +    default: +        break; +  } +} // expected-warning {{control reaches end of non-void function}} + +void PR9412_f() { +    PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<0>' requested here}} +} + diff --git a/clang/test/SemaCXX/return-stack-addr.cpp b/clang/test/SemaCXX/return-stack-addr.cpp new file mode 100644 index 0000000..fbbaf83 --- /dev/null +++ b/clang/test/SemaCXX/return-stack-addr.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int* ret_local() { +  int x = 1; +  return &x; // expected-warning {{address of stack memory}} +} + +int* ret_local_array() { +  int x[10]; +  return x; // expected-warning {{address of stack memory}} +} + +int* ret_local_array_element(int i) { +  int x[10]; +  return &x[i]; // expected-warning {{address of stack memory}} +} + +int *ret_local_array_element_reversed(int i) { +  int x[10]; +  return &i[x]; // expected-warning {{address of stack memory}} +} + +int* ret_local_array_element_const_index() { +  int x[10]; +  return &x[2];  // expected-warning {{address of stack memory}} +} + +int& ret_local_ref() { +  int x = 1; +  return x;  // expected-warning {{reference to stack memory}} +} + +int* ret_local_addrOf() { +  int x = 1; +  return &*&x; // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_paren() { +  int x = 1; +  return (&(*(&x))); // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_ptr_arith() { +  int x = 1; +  return &*(&x+1); // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_ptr_arith2() { +  int x = 1; +  return &*(&x+1); // expected-warning {{address of stack memory}} +} + +int* ret_local_field() { +  struct { int x; } a; +  return &a.x; // expected-warning {{address of stack memory}} +} + +int& ret_local_field_ref() { +  struct { int x; } a; +  return a.x; // expected-warning {{reference to stack memory}} +} + +int* ret_conditional(bool cond) { +  int x = 1; +  int y = 2; +  return cond ? &x : &y; // expected-warning {{address of stack memory}} +} + +int* ret_conditional_rhs(int *x, bool cond) { +  int y = 1; +  return cond ? x : &y;  // expected-warning {{address of stack memory}} +} + +void* ret_c_cast() { +  int x = 1; +  return (void*) &x;  // expected-warning {{address of stack memory}} +} + +int* ret_static_var() { +  static int x = 1; +  return &x;  // no warning. +} + +int z = 1; + +int* ret_global() { +  return &z;  // no warning. +} + +int* ret_parameter(int x) { +  return &x;  // expected-warning {{address of stack memory}} +} + + +void* ret_cpp_static_cast(short x) { +  return static_cast<void*>(&x); // expected-warning {{address of stack memory}} +} + +int* ret_cpp_reinterpret_cast(double x) { +  return reinterpret_cast<int*>(&x); // expected-warning {{address of stack me}} +} + +int* ret_cpp_reinterpret_cast_no_warning(long x) { +  return reinterpret_cast<int*>(x); // no-warning +} + +int* ret_cpp_const_cast(const int x) { +  return const_cast<int*>(&x);  // expected-warning {{address of stack memory}} +} + +// PR 7999 - handle the case where a field is itself a reference. +template <typename T> struct PR7999 { +  PR7999(T& t) : value(t) {} +  T& value; +}; + +struct PR7999_X {}; + +PR7999_X& PR7999_f(PR7999<PR7999_X> s) { return s.value; } // no-warning +void test_PR7999(PR7999_X& x) { (void)PR7999_f(x); } // no-warning + +// PR 8774: Don't try to evaluate parameters with default arguments like +// variables with an initializer, especially in templates where the default +// argument may not be an expression (yet). +namespace PR8774 { +  template <typename U> struct B { }; +  template <typename V> V f(typename B<V>::type const &v = B<V>::value()) { +    return v; +  } +  template <> struct B<const char *> { +    typedef const char *type; +    static const char *value(); +  }; +  void g() { +    const char *t; +    f<const char*>(t); +  } +} + +// TODO: test case for dynamic_cast.  clang does not yet have +// support for C++ classes to write such a test case. diff --git a/clang/test/SemaCXX/return.cpp b/clang/test/SemaCXX/return.cpp new file mode 100644 index 0000000..2f98a27 --- /dev/null +++ b/clang/test/SemaCXX/return.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -Wignored-qualifiers -verify + +int test1() { +  throw; +} + +// PR5071 +template<typename T> T f() { } + +template<typename T> +void g(T t) { +  return t * 2; // okay +} + +template<typename T> +T h() { +  return 17; +} + +// Don't warn on cv-qualified class return types, only scalar return types. +namespace ignored_quals { +struct S {}; +const S class_c(); +const volatile S class_cv(); + +const int scalar_c(); // expected-warning{{'const' type qualifier on return type has no effect}} +int const scalar_c2(); // expected-warning{{'const' type qualifier on return type has no effect}} + +const +char* +const // expected-warning{{'const' type qualifier on return type has no effect}} +f(); + +char +const* +const // expected-warning{{'const' type qualifier on return type has no effect}} +g(); + +char* const h(); // expected-warning{{'const' type qualifier on return type has no effect}} +char* volatile i(); // expected-warning{{'volatile' type qualifier on return type has no effect}} + +char* +volatile // expected-warning{{'const volatile' type qualifiers on return type have no effect}} +const +j(); + +const volatile int scalar_cv(); // expected-warning{{'const volatile' type qualifiers on return type have no effect}} +} + +namespace PR9328 { +  typedef char *PCHAR; +  class Test  +  { +    const PCHAR GetName() { return 0; } // expected-warning{{'const' type qualifier on return type has no effect}} +  }; +} + +class foo  { +  operator int * const (); +}; + +namespace PR10057 { +  struct S { +    ~S(); +  }; + +  template <class VarType> +  void Test(const VarType& value) { +    return S() = value; +  } +} + +namespace return_has_expr { +  struct S { +    S() { +      return 42; // expected-error {{constructor 'S' should not return a value}} +    } +    ~S() { +      return 42; // expected-error {{destructor '~S' should not return a value}} +    } +  }; +} diff --git a/clang/test/SemaCXX/runtimediag-ppe.cpp b/clang/test/SemaCXX/runtimediag-ppe.cpp new file mode 100644 index 0000000..0e8451b --- /dev/null +++ b/clang/test/SemaCXX/runtimediag-ppe.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Make sure diagnostics that we don't print based on runtime control +// flow are delayed correctly in cases where we can't immediately tell whether +// the context is unevaluated. + +namespace std { +  class type_info; +} + +int& NP(int); +void test1() { (void)typeid(NP(1 << 32)); } + +class Poly { virtual ~Poly(); }; +Poly& P(int); +void test2() { (void)typeid(P(1 << 32)); } // expected-warning {{shift count >= width of type}} + +void test3() { 1 ? (void)0 : (void)typeid(P(1 << 32)); } diff --git a/clang/test/SemaCXX/rval-references-examples.cpp b/clang/test/SemaCXX/rval-references-examples.cpp new file mode 100644 index 0000000..110ae26 --- /dev/null +++ b/clang/test/SemaCXX/rval-references-examples.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> +class unique_ptr { +  T *ptr; + +  unique_ptr(const unique_ptr&) = delete; // expected-note 3{{function has been explicitly marked deleted here}} +  unique_ptr &operator=(const unique_ptr&) = delete; // expected-note{{candidate function has been explicitly deleted}} +public: +  unique_ptr() : ptr(0) { } +  unique_ptr(unique_ptr &&other) : ptr(other.ptr) { other.ptr = 0; } +  explicit unique_ptr(T *ptr) : ptr(ptr) { } + +  ~unique_ptr() { delete ptr; } + +  unique_ptr &operator=(unique_ptr &&other) { // expected-note{{candidate function not viable: no known conversion from 'unique_ptr<int>' to 'unique_ptr<int> &&' for 1st argument}} +    if (this == &other) +      return *this; + +    delete ptr; +    ptr = other.ptr; +    other.ptr = 0; +    return *this; +  } +}; + +template<typename T> +struct remove_reference { +  typedef T type; +}; + +template<typename T> +struct remove_reference<T&> { +  typedef T type; +}; + +template<typename T> +struct remove_reference<T&&> { +  typedef T type; +}; + + +template <class T> typename remove_reference<T>::type&& move(T&& t) { +  return static_cast<typename remove_reference<T>::type&&>(t); +} + +template <class T> T&& forward(typename remove_reference<T>::type& t) { +  return static_cast<T&&>(t); +} + +template <class T> T&& forward(typename remove_reference<T>::type&& t) { +  return static_cast<T&&>(t); +} + +template<typename T, typename ...Args> +unique_ptr<T> make_unique_ptr(Args &&...args) { +  return unique_ptr<T>(new T(forward<Args>(args)...)); +} + +template<typename T> void accept_unique_ptr(unique_ptr<T>); // expected-note{{passing argument to parameter here}} + +unique_ptr<int> test_unique_ptr() { +  // Simple construction +  unique_ptr<int> p; +  unique_ptr<int> p1(new int); + +  // Move construction +  unique_ptr<int> p2(make_unique_ptr<int>(17)); +  unique_ptr<int> p3 = make_unique_ptr<int>(17); + +  // Copy construction (failures) +  unique_ptr<int> p4(p); // expected-error{{call to deleted constructor of 'unique_ptr<int>'}} +  unique_ptr<int> p5 = p; // expected-error{{call to deleted constructor of 'unique_ptr<int>'}} + +  // Move assignment +  p2 = move(p); +  p2 = make_unique_ptr<int>(0); + +  // Copy assignment (failures); +  p2 = p3; // expected-error{{overload resolution selected deleted operator '='}} + +  // Implicit copies +  accept_unique_ptr(make_unique_ptr<double>(0.0)); +  accept_unique_ptr(move(p2)); + +  // Implicit copies (failures); +  accept_unique_ptr(p); // expected-error{{call to deleted constructor of 'unique_ptr<int>'}} + +  return p; +} + +namespace perfect_forwarding { +  struct A { }; + +  struct F0 { +    void operator()(A&, const A&, A&&, const A&&, A&&, const A&&); // expected-note{{candidate function not viable: 5th argument ('const perfect_forwarding::A') would lose const qualifier}} +  }; + +  template<typename F, typename ...Args> +  void forward(F f, Args &&...args) { +    f(static_cast<Args&&>(args)...); // expected-error{{no matching function for call to object of type 'perfect_forwarding::F0'}} +  } + +  template<typename T> T get(); + +  void test_forward() { +    forward(F0(), get<A&>(), get<A const&>(), get<A>(), get<const A>(), +            get<A&&>(), get<const A&&>()); +    forward(F0(), get<A&>(), get<A const&>(), get<A>(), get<const A>(), // expected-note{{in instantiation of function template specialization 'perfect_forwarding::forward<perfect_forwarding::F0, perfect_forwarding::A &, const perfect_forwarding::A &, perfect_forwarding::A, const perfect_forwarding::A, const perfect_forwarding::A, const perfect_forwarding::A>' requested here}} +            get<const A&&>(), get<const A&&>()); +  } +}; diff --git a/clang/test/SemaCXX/rval-references.cpp b/clang/test/SemaCXX/rval-references.cpp new file mode 100644 index 0000000..fc341e8 --- /dev/null +++ b/clang/test/SemaCXX/rval-references.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s + +typedef int&& irr; +typedef irr& ilr_c1; // Collapses to int& +typedef int& ilr; +typedef ilr&& ilr_c2; // Collapses to int& + +irr ret_irr() { +  return 0; // expected-warning {{returning reference to local temporary}} +} + +struct not_int {}; + +int over(int&); +not_int over(int&&); + +int over2(const int&); +not_int over2(int&&); + +struct conv_to_not_int_rvalue { +  operator not_int &&(); +}; + +typedef void (fun_type)(); +void fun(); +fun_type &&make_fun(); + +void f() { +  int &&virr1; // expected-error {{declaration of reference variable 'virr1' requires an initializer}} +  int &&virr2 = 0; +  int &&virr3 = virr2; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}} +  int i1 = 0; +  int &&virr4 = i1; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}} +  int &&virr5 = ret_irr(); +  int &&virr6 = static_cast<int&&>(i1); +  (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}} + +  int i2 = over(i1); +  not_int ni1 = over(0); +  int i3 = over(virr2); +  not_int ni2 = over(ret_irr()); + +  int i4 = over2(i1); +  not_int ni3 = over2(0); + +  ilr_c1 vilr1 = i1; +  ilr_c2 vilr2 = i1; + +  conv_to_not_int_rvalue cnir; +  not_int &&ni4 = cnir; +  not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'not_int' cannot bind to a value of unrelated type 'conv_to_not_int_rvalue'}} +  not_int &&ni6 = conv_to_not_int_rvalue(); + +  fun_type &&fun_ref = fun; // works because functions are special +  fun_type &&fun_ref2 = make_fun(); // same +  fun_type &fun_lref = make_fun(); // also special + +  try { +  } catch(int&&) { // expected-error {{cannot catch exceptions by rvalue reference}} +  } +} + +int&& should_warn(int i) { +  // FIXME: The stack address return test doesn't reason about casts. +  return static_cast<int&&>(i); // xpected-warning {{returning reference to temporary}} +} +int&& should_not_warn(int&& i) { // But GCC 4.4 does +  return static_cast<int&&>(i); +} + + +// Test the return dance. This also tests IsReturnCopyElidable. +struct MoveOnly { +  MoveOnly(); +  MoveOnly(const MoveOnly&) = delete;	// expected-note {{candidate constructor}} \ +  // expected-note 3{{explicitly marked deleted here}} +  MoveOnly(MoveOnly&&);	// expected-note {{candidate constructor}} +  MoveOnly(int&&);	// expected-note {{candidate constructor}} +}; + +MoveOnly gmo; +MoveOnly returningNonEligible() { +  int i; +  static MoveOnly mo; +  MoveOnly &r = mo; +  if (0) // Copy from global can't be elided +    return gmo; // expected-error {{call to deleted constructor}} +  else if (0) // Copy from local static can't be elided +    return mo; // expected-error {{call to deleted constructor}} +  else if (0) // Copy from reference can't be elided +    return r; // expected-error {{call to deleted constructor}} +  else // Construction from different type can't be elided +    return i; // expected-error {{no viable conversion from 'int' to 'MoveOnly'}} +} diff --git a/clang/test/SemaCXX/scope-check.cpp b/clang/test/SemaCXX/scope-check.cpp new file mode 100644 index 0000000..b659de0 --- /dev/null +++ b/clang/test/SemaCXX/scope-check.cpp @@ -0,0 +1,209 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-unreachable-code +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++11 %s -Wno-unreachable-code + +namespace test0 { +  struct D { ~D(); }; + +  int f(bool b) { +    if (b) { +      D d; +      goto end; +    } + +  end: +    return 1; +  } +} + +namespace test1 { +  struct C { C(); }; + +  int f(bool b) { +    if (b) +      goto foo; // expected-error {{goto into protected scope}} +    C c; // expected-note {{jump bypasses variable initialization}} +  foo: +    return 1; +  } +} + +namespace test2 { +  struct C { C(); }; + +  int f(void **ip) { +    static void *ips[] = { &&lbl1, &&lbl2 }; + +    C c; +    goto *ip; +  lbl1: +    return 0; +  lbl2: +    return 1; +  } +} + +namespace test3 { +  struct C { C(); }; + +  int f(void **ip) { +    static void *ips[] = { &&lbl1, &&lbl2 }; + +    goto *ip; +  lbl1: { +    C c; +    return 0; +  } +  lbl2: +    return 1; +  } +} + +namespace test4 { +  struct C { C(); }; +  struct D { ~D(); }; + +  int f(void **ip) { +    static void *ips[] = { &&lbl1, &&lbl2 }; + +    C c0; + +    goto *ip; // expected-error {{indirect goto might cross protected scopes}} +    C c1; // expected-note {{jump bypasses variable initialization}} +  lbl1: // expected-note {{possible target of indirect goto}} +    return 0; +  lbl2: +    return 1; +  } +} + +namespace test5 { +  struct C { C(); }; +  struct D { ~D(); }; + +  int f(void **ip) { +    static void *ips[] = { &&lbl1, &&lbl2 }; +    C c0; + +    goto *ip; +  lbl1: // expected-note {{possible target of indirect goto}} +    return 0; +  lbl2: +    if (ip[1]) { +      D d; // expected-note {{jump exits scope of variable with non-trivial destructor}} +      ip += 2; +      goto *ip; // expected-error {{indirect goto might cross protected scopes}} +    } +    return 1; +  } +} + +namespace test6 { +  struct C { C(); }; + +  unsigned f(unsigned s0, unsigned s1, void **ip) { +    static void *ips[] = { &&lbl1, &&lbl2, &&lbl3, &&lbl4 }; +    C c0; + +    goto *ip; +  lbl1: +    s0++; +    goto *++ip; +  lbl2: +    s0 -= s1; +    goto *++ip; +  lbl3: { +    unsigned tmp = s0; +    s0 = s1; +    s1 = tmp; +    goto *++ip; +  } +  lbl4: +    return s0; +  } +} + +// C++0x says it's okay to skip non-trivial initializers on static +// locals, and we implement that in '03 as well. +namespace test7 { +  struct C { C(); }; + +  void test() { +    goto foo; +    static C c; +  foo: +    return; +  } +} + +// PR7789 +namespace test8 { +  void test1(int c) { +    switch (c) { +    case 0: +      int x = 56; // expected-note {{jump bypasses variable initialization}} +    case 1:       // expected-error {{switch case is in protected scope}} +      x = 10; +    } +  } + +  void test2() { +    goto l2;     // expected-error {{goto into protected scope}} +  l1: int x = 5; // expected-note {{jump bypasses variable initialization}} +  l2: x++; +  } +} + +namespace test9 { +  struct S { int i; }; +  void test1() { +    goto foo; +    S s; +  foo: +    return; +  } +  unsigned test2(unsigned x, unsigned y) { +    switch (x) { +    case 2: +      S s; +      if (y > 42) return x + y; +    default: +      return x - 2; +    } +  } +} + +// http://llvm.org/PR10462 +namespace PR10462 { +enum MyEnum { +  something_valid, +  something_invalid +}; + +bool recurse() { +  MyEnum K; +  switch (K) { // expected-warning {{enumeration value 'something_invalid' not handled in switch}} +    case something_valid: +    case what_am_i_thinking: // expected-error {{use of undeclared identifier}} +      int *X = 0; +      if (recurse()) { +      } + +      break; +  } +} + + +namespace test10 { +
 +int test() {
 +  static void *ps[] = { &&a0 };
 +  goto *&&a0; // expected-error {{goto into protected scope}}
 +  int a = 3; // expected-note {{jump bypasses variable initialization}}
 + a0:
 +  return 0;
 +} + +} + +} + diff --git a/clang/test/SemaCXX/shift.cpp b/clang/test/SemaCXX/shift.cpp new file mode 100644 index 0000000..d5a5bed --- /dev/null +++ b/clang/test/SemaCXX/shift.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -Wall -Wshift-sign-overflow -ffreestanding -fsyntax-only -verify %s + +#include <limits.h> + +#define WORD_BIT (sizeof(int) * CHAR_BIT) + +template <int N> void f() { +  (void)(N << 30); // expected-warning {{bits to represent, but 'int' only has}} +  (void)(30 << N); // expected-warning {{bits to represent, but 'int' only has}} +} + +void test() { +  f<30>(); // expected-note {{instantiation}} +} diff --git a/clang/test/SemaCXX/short-enums.cpp b/clang/test/SemaCXX/short-enums.cpp new file mode 100644 index 0000000..ca713b7 --- /dev/null +++ b/clang/test/SemaCXX/short-enums.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fshort-enums -fsyntax-only %s + +// This shouldn't crash: PR9474 + +enum E { VALUE_1 }; + +template <typename T> +struct A {}; + +template <E Enum> +struct B : A<B<Enum> > {}; + +void bar(int x) { +  switch (x) { +    case sizeof(B<VALUE_1>): ; +  } +}
\ No newline at end of file diff --git a/clang/test/SemaCXX/short-wchar-sign.cpp b/clang/test/SemaCXX/short-wchar-sign.cpp new file mode 100644 index 0000000..9a177c0 --- /dev/null +++ b/clang/test/SemaCXX/short-wchar-sign.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -pedantic -verify %s +// RUN: %clang_cc1 -fshort-wchar -fsyntax-only -pedantic -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -pedantic -verify %s + +// Check that short wchar_t is unsigned, and that regular wchar_t is not. +int test[(wchar_t(-1)<wchar_t(0)) == (sizeof(wchar_t) == 4) ?1:-1]; diff --git a/clang/test/SemaCXX/sourceranges.cpp b/clang/test/SemaCXX/sourceranges.cpp new file mode 100644 index 0000000..0537aa2 --- /dev/null +++ b/clang/test/SemaCXX/sourceranges.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s + +template<class T> +class P { + public: +  P(T* t) {} +}; + +namespace foo { +class A {}; +enum B {}; +typedef int C; +} + +int main() { +  // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::A *' +  P<foo::A> p14 = new foo::A; +  // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::B *' +  P<foo::B> p24 = new foo::B; +  // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::C *' +  P<foo::C> pr4 = new foo::C; +} + +foo::A getName() { +  // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A' +  return foo::A(); +} diff --git a/clang/test/SemaCXX/statements.cpp b/clang/test/SemaCXX/statements.cpp new file mode 100644 index 0000000..6d04c84 --- /dev/null +++ b/clang/test/SemaCXX/statements.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify + +void foo() {  +  return foo(); +} + +// PR6451 - C++ Jump checking +struct X { +  X(); +}; + +void test2() { +  goto later;  // expected-error {{goto into protected scope}} +  X x;         // expected-note {{jump bypasses variable initialization}}  +later: +  ; +} + +namespace PR6536 { +  struct A {}; +  void a() { goto out; A x; out: return; } +} diff --git a/clang/test/SemaCXX/static-array-member.cpp b/clang/test/SemaCXX/static-array-member.cpp new file mode 100644 index 0000000..8f57549 --- /dev/null +++ b/clang/test/SemaCXX/static-array-member.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +struct X0 { +  static int array[]; +   +  int x; +  int y; +}; + +int X0::array[sizeof(X0) * 2]; + +template<typename T, int N> +struct X1 { +  static T array[]; +}; + +template<typename T, int N> +T X1<T, N>::array[N]; diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp new file mode 100644 index 0000000..364e4e4 --- /dev/null +++ b/clang/test/SemaCXX/static-assert.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=x86_64-linux-gnu + +int f(); // expected-note {{declared here}} + +static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +static_assert(true, "true is not false"); +static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} + +void g() { +    static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} +} + +class C { +    static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} +}; + +template<int N> struct T { +    static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}} +}; + +T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}} +T<2> t2; + +template<typename T> struct S { +    static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}} +}; + +S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}} +S<int> s2; + +static_assert(false, L"\xFFFFFFFF"); // expected-error {{static_assert failed L"\xFFFFFFFF"}} +static_assert(false, u"\U000317FF"); // expected-error {{static_assert failed u"\U000317FF"}} +// FIXME: render this as u8"\u03A9" +static_assert(false, u8"Ω"); // expected-error {{static_assert failed u8"\316\251"}} +static_assert(false, L"\u1234"); // expected-error {{static_assert failed L"\x1234"}} +static_assert(false, L"\x1ff" "0\x123" "fx\xfffff" "goop"); // expected-error {{static_assert failed L"\x1FF""0\x123""fx\xFFFFFgoop"}} diff --git a/clang/test/SemaCXX/static-cast-complete-type.cpp b/clang/test/SemaCXX/static-cast-complete-type.cpp new file mode 100644 index 0000000..6d76f81 --- /dev/null +++ b/clang/test/SemaCXX/static-cast-complete-type.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> struct S { +  S(int); +}; + +struct T; // expected-note{{forward declaration of 'T'}} + +void f() { +  S<int> s0 = static_cast<S<int> >(0); +  S<void*> s1 = static_cast<S<void*> >(00); + +  (void)static_cast<T>(10); // expected-error{{'T' is an incomplete type}} +} diff --git a/clang/test/SemaCXX/static-cast.cpp b/clang/test/SemaCXX/static-cast.cpp new file mode 100644 index 0000000..7fb016e --- /dev/null +++ b/clang/test/SemaCXX/static-cast.cpp @@ -0,0 +1,197 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A {}; +struct B : public A {};             // Single public base. +struct C1 : public virtual B {};    // Single virtual base. +struct C2 : public virtual B {}; +struct D : public C1, public C2 {}; // Diamond +struct E : private A {};            // Single private base. expected-note 3 {{declared private here}} +struct F : public C1 {};            // Single path to B with virtual. +struct G1 : public B {}; +struct G2 : public B {}; +struct H : public G1, public G2 {}; // Ambiguous path to B. + +enum Enum { En1, En2 }; +enum Onom { On1, On2 }; + +struct Co1 { operator int(); }; +struct Co2 { Co2(int); }; +struct Co3 { }; +struct Co4 { Co4(Co3); operator Co3(); }; + +// Explicit implicits +void t_529_2() +{ +  int i = 1; +  (void)static_cast<float>(i); +  double d = 1.0; +  (void)static_cast<float>(d); +  (void)static_cast<int>(d); +  (void)static_cast<char>(i); +  (void)static_cast<unsigned long>(i); +  (void)static_cast<int>(En1); +  (void)static_cast<double>(En1); +  (void)static_cast<int&>(i); +  (void)static_cast<const int&>(i); + +  int ar[1]; +  (void)static_cast<const int*>(ar); +  (void)static_cast<void (*)()>(t_529_2); + +  (void)static_cast<void*>(0); +  (void)static_cast<void*>((int*)0); +  (void)static_cast<volatile const void*>((const int*)0); +  (void)static_cast<A*>((B*)0); +  (void)static_cast<A&>(*((B*)0)); +  (void)static_cast<const B*>((C1*)0); +  (void)static_cast<B&>(*((C1*)0)); +  (void)static_cast<A*>((D*)0); +  (void)static_cast<const A&>(*((D*)0)); +  (void)static_cast<int B::*>((int A::*)0); +  (void)static_cast<void (B::*)()>((void (A::*)())0); + +  (void)static_cast<int>(Co1()); +  (void)static_cast<Co2>(1); +  (void)static_cast<Co3>(static_cast<Co4>(Co3())); + +  // Bad code below + +  (void)static_cast<void*>((const int*)0); // expected-error {{static_cast from 'const int *' to 'void *' is not allowed}} +  (void)static_cast<A*>((E*)0); // expected-error {{cannot cast 'E' to its private base class 'A'}} +  (void)static_cast<A*>((H*)0); // expected-error {{ambiguous conversion}} +  (void)static_cast<int>((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}} +  (void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'B **' to 'A **' is not allowed}} +  (void)static_cast<char&>(i); // expected-error {{non-const lvalue reference to type 'char' cannot bind to a value of unrelated type 'int'}} +} + +// Anything to void +void t_529_4() +{ +  static_cast<void>(1); +  static_cast<void>(t_529_4); +} + +// Static downcasts +void t_529_5_8() +{ +  (void)static_cast<B*>((A*)0); +  (void)static_cast<B&>(*((A*)0)); +  (void)static_cast<const G1*>((A*)0); +  (void)static_cast<const G1&>(*((A*)0)); + +  // Bad code below + +  (void)static_cast<C1*>((A*)0); // expected-error {{cannot cast 'A *' to 'C1 *' via virtual base 'B'}} +  (void)static_cast<C1&>(*((A*)0)); // expected-error {{cannot cast 'A' to 'C1 &' via virtual base 'B'}} +  (void)static_cast<D*>((A*)0); // expected-error {{cannot cast 'A *' to 'D *' via virtual base 'B'}} +  (void)static_cast<D&>(*((A*)0)); // expected-error {{cannot cast 'A' to 'D &' via virtual base 'B'}} +  (void)static_cast<B*>((const A*)0); // expected-error {{static_cast from 'const A *' to 'B *' casts away qualifiers}} +  (void)static_cast<B&>(*((const A*)0)); // expected-error {{static_cast from 'const A' to 'B &' casts away qualifiers}} +  (void)static_cast<E*>((A*)0); // expected-error {{cannot cast private base class 'A' to 'E'}} +  (void)static_cast<E&>(*((A*)0)); // expected-error {{cannot cast private base class 'A' to 'E'}} +  (void)static_cast<H*>((A*)0); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}} +  (void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous cast from base 'A' to derived 'H':\n    struct A -> struct B -> struct G1 -> struct H\n    struct A -> struct B -> struct G2 -> struct H}} +  (void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'B *' to 'E *' is not allowed}} +  (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'E' cannot bind to a value of unrelated type 'B'}} + +  // TODO: Test inaccessible base in context where it's accessible, i.e. +  // member function and friend. + +  // TODO: Test DR427. This requires user-defined conversions, though. +} + +// Enum conversions +void t_529_7() +{ +  (void)static_cast<Enum>(1); +  (void)static_cast<Enum>(1.0); +  (void)static_cast<Onom>(En1); + +  // Bad code below + +  (void)static_cast<Enum>((int*)0); // expected-error {{static_cast from 'int *' to 'Enum' is not allowed}} +} + +// Void pointer to object pointer +void t_529_10() +{ +  (void)static_cast<int*>((void*)0); +  (void)static_cast<const A*>((void*)0); + +  // Bad code below + +  (void)static_cast<int*>((const void*)0); // expected-error {{static_cast from 'const void *' to 'int *' casts away qualifiers}} +  (void)static_cast<void (*)()>((void*)0); // expected-error {{static_cast from 'void *' to 'void (*)()' is not allowed}} +} + +// Member pointer upcast. +void t_529_9() +{ +  (void)static_cast<int A::*>((int B::*)0); + +  // Bad code below +  (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} +  (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} +} + +// PR 5261 - static_cast should instantiate template if possible +namespace pr5261 { +  struct base {}; +  template<typename E> struct derived : public base {}; +  template<typename E> struct outer { +    base *pb; +    ~outer() { (void)static_cast<derived<E>*>(pb); } +  }; +  outer<int> EntryList; +} + + +// Initialization by constructor +struct X0; + +struct X1 { +  X1(); +  X1(X1&); +  X1(const X0&); +   +  operator X0() const; +}; + +struct X0 { }; + +void test_ctor_init() { +  (void)static_cast<X1>(X1()); +} + +// Casting away constness +struct X2 { +}; + +struct X3 : X2 { +}; + +struct X4 { +  typedef const X3 X3_typedef; +   +  void f() const { +    (void)static_cast<X3_typedef*>(x2); +  } +   +  const X2 *x2; +}; + +// PR5897 - accept static_cast from const void* to const int (*)[1]. +void PR5897() { (void)static_cast<const int(*)[1]>((const void*)0); } + +namespace PR6072 { +  struct A { };  +  struct B : A { void f(int); void f(); };  // expected-note 2{{candidate function}} +  struct C : B { }; +  struct D { }; + +  void f() { +    (void)static_cast<void (A::*)()>(&B::f); +    (void)static_cast<void (B::*)()>(&B::f); +    (void)static_cast<void (C::*)()>(&B::f); +    (void)static_cast<void (D::*)()>(&B::f); // expected-error{{address of overloaded function 'f' cannot be static_cast to type 'void (PR6072::D::*)()'}} +  } +} diff --git a/clang/test/SemaCXX/static-initializers.cpp b/clang/test/SemaCXX/static-initializers.cpp new file mode 100644 index 0000000..ca49fce --- /dev/null +++ b/clang/test/SemaCXX/static-initializers.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +int f() { +  return 10; +} + +void g() { +  static int a = f(); +} + +static int b = f(); diff --git a/clang/test/SemaCXX/storage-class.cpp b/clang/test/SemaCXX/storage-class.cpp new file mode 100644 index 0000000..01cfbfc --- /dev/null +++ b/clang/test/SemaCXX/storage-class.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +extern const int PR6495a = 42; +extern int PR6495b = 42; // expected-warning{{'extern' variable has an initializer}} +extern const int PR6495c[] = {42,43,44}; + +extern struct Test1 {}; // expected-warning {{'extern' ignored on this declaration}} +extern "C" struct Test0 {}; // no warning diff --git a/clang/test/SemaCXX/string-plus-int.cpp b/clang/test/SemaCXX/string-plus-int.cpp new file mode 100644 index 0000000..5752f8f --- /dev/null +++ b/clang/test/SemaCXX/string-plus-int.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-array-bounds %s -fpascal-strings +// RUN: %clang_cc1 -fdiagnostics-parseable-fixits -x c++ %s 2>&1 -Wno-array-bounds -fpascal-strings | FileCheck %s + +void consume(const char* c) {} +void consume(const unsigned char* c) {} +void consume(const wchar_t* c) {} +void consumeChar(char c) {} + +enum MyEnum { +  kMySmallEnum = 1, +  kMyEnum = 5 +}; + +enum OperatorOverloadEnum { +  kMyOperatorOverloadedEnum = 5 +}; + +const char* operator+(const char* c, OperatorOverloadEnum e) { +  return "yo"; +} + +const char* operator+(OperatorOverloadEnum e, const char* c) { +  return "yo"; +} + +void f(int index) { +  // Should warn. +  // CHECK: fix-it:"{{.*}}":{31:11-31:11}:"&" +  // CHECK: fix-it:"{{.*}}":{31:17-31:18}:"[" +  // CHECK: fix-it:"{{.*}}":{31:20-31:20}:"]" +  consume("foo" + 5);  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} +  consume("foo" + index);  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} +  consume("foo" + kMyEnum);  // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + +  consume(5 + "foo");  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} +  consume(index + "foo");  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} +  consume(kMyEnum + "foo");  // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + +  // FIXME: suggest replacing with "foo"[5] +  consumeChar(*("foo" + 5));  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} +  consumeChar(*(5 + "foo"));  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + +  consume(L"foo" + 5);  // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + +  // Should not warn. +  consume(&("foo"[3])); +  consume(&("foo"[index])); +  consume(&("foo"[kMyEnum])); +  consume("foo" + kMySmallEnum); +  consume(kMySmallEnum + "foo"); + +  consume(L"foo" + 2); + +  consume("foo" + 3);  // Points at the \0 +  consume("foo" + 4);  // Points 1 past the \0, which is legal too. +  consume("\pfoo" + 4);  // Pascal strings don't have a trailing \0, but they +                         // have a leading length byte, so this is fine too. + +  consume("foo" + kMyOperatorOverloadedEnum); +  consume(kMyOperatorOverloadedEnum + "foo"); + +  #define A "foo" +  #define B "bar" +  consume(A B + sizeof(A) - 1); +} + diff --git a/clang/test/SemaCXX/struct-class-redecl.cpp b/clang/test/SemaCXX/struct-class-redecl.cpp new file mode 100644 index 0000000..5c59578 --- /dev/null +++ b/clang/test/SemaCXX/struct-class-redecl.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -fsyntax-only -Wmismatched-tags -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wmismatched-tags %s 2>&1 | FileCheck %s +class X; // expected-note 2{{here}} +typedef struct X * X_t; // expected-warning{{previously declared}} +union X { int x; float y; }; // expected-error{{use of 'X' with tag type that does not match previous declaration}} + +template<typename T> struct Y; // expected-note{{did you mean class here?}} +template<class U> class Y { }; // expected-warning{{previously declared}} + +class A; +class A;  // expected-note{{previous use is here}} +struct A;  // expected-warning{{struct 'A' was previously declared as a class}} + +class B;  // expected-note{{did you mean struct here?}} +class B;  // expected-note{{previous use is here}}\ +          // expected-note{{did you mean struct here?}} +struct B;  // expected-warning{{struct 'B' was previously declared as a class}} +struct B {};  // expected-warning{{'B' defined as a struct here but previously declared as a class}} + +class C;  // expected-note{{previous use is here}} +struct C;  // expected-warning{{struct 'C' was previously declared as a class}}\ +           // expected-note{{previous use is here}}\ +           // expected-note{{did you mean class here?}} +class C;  // expected-warning{{class 'C' was previously declared as a struct}}\ +          // expected-note{{previous use is here}} +struct C;  // expected-warning{{struct 'C' was previously declared as a class}}\ +           // expected-note{{did you mean class here?}} +class C {};  // expected-warning{{'C' defined as a class here but previously declared as a struct}} + +struct D {};  // expected-note{{previous definition is here}}\ +              // expected-note{{previous use is here}} +class D {};  // expected-error{{redefinition of 'D'}} +struct D; +class D;  // expected-warning{{class 'D' was previously declared as a struct}}\ +          // expected-note{{did you mean struct here?}} + +class E; +class E; +class E {}; +class E; + +struct F; +struct F; +struct F {}; +struct F; + +template<class U> class G;  // expected-note{{previous use is here}}\ +                            // expected-note{{did you mean struct here?}} +template<class U> struct G;  // expected-warning{{struct template 'G' was previously declared as a class template}} +template<class U> struct G {};  // expected-warning{{'G' defined as a struct template here but previously declared as a class template}} + +/* +*** 'X' messages *** +CHECK: warning: struct 'X' was previously declared as a class +CHECK: {{^}}typedef struct X * X_t; +CHECK: {{^}}        ^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class X; +CHECK: {{^}}      ^{{$}} +CHECK: error: use of 'X' with tag type that does not match previous declaration +CHECK: {{^}}union X { int x; float y; }; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}class{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class X; +CHECK: {{^}}      ^{{$}} +*** 'Y' messages *** +CHECK: warning: 'Y' defined as a class template here but +      previously declared as a struct template +CHECK: {{^}}template<class U> class Y { }; +CHECK: {{^}}                  ^{{$}} +CHECK: note: did you mean class here? +CHECK: {{^}}template<typename T> struct Y; +CHECK: {{^}}                     ^~~~~~{{$}} +CHECK: {{^}}                     class{{$}} +*** 'A' messages *** +CHECK: warning: struct 'A' was previously declared as a class +CHECK: {{^}}struct A; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class A; +CHECK: {{^}}      ^{{$}} +*** 'B' messages *** +CHECK: warning: struct 'B' was previously declared as a class +CHECK: {{^}}struct B; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class B; +CHECK: {{^}}      ^{{$}} +CHECK: 'B' defined as a struct here but previously declared as a class +CHECK: {{^}}struct B {}; +CHECK: {{^}}^{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}class B; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}struct{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}class B; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}struct{{$}} +*** 'C' messages *** +CHECK: warning: struct 'C' was previously declared as a class +CHECK: {{^}}struct C; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class C; +CHECK: {{^}}      ^{{$}} +CHECK: warning: class 'C' was previously declared as a struct +CHECK: {{^}}class C; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}struct C; +CHECK: {{^}}       ^{{$}} +CHECK: warning: struct 'C' was previously declared as a class +CHECK: {{^}}struct C; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class C; +CHECK: {{^}}      ^{{$}} +CHECK: warning: 'C' defined as a class here but previously declared as a struct +CHECK: {{^}}class C {}; +CHECK: {{^}}^{{$}} +CHECK: note: did you mean class here? +CHECK: {{^}}struct C; +CHECK: {{^}}^~~~~~{{$}} +CHECK: {{^}}class{{$}} +CHECK: note: did you mean class here? +CHECK: {{^}}struct C; +CHECK: {{^}}^~~~~~{{$}} +CHECK: {{^}}class{{$}} +*** 'D' messages *** +CHECK: error: redefinition of 'D' +CHECK: {{^}}class D {}; +CHECK: {{^}}      ^{{$}} +CHECK: note: previous definition is here +CHECK: {{^}}struct D {}; +CHECK: {{^}}       ^{{$}} +CHECK: warning: class 'D' was previously declared as a struct +CHECK: {{^}}class D; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}struct D {}; +CHECK: {{^}}       ^{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}class D; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}struct{{$}} +*** 'E' messages *** +*** 'F' messages *** +*** 'G' messages *** +CHECK: warning: struct template 'G' was previously declared as a class template +CHECK: {{^}}template<class U> struct G; +CHECK: {{^}}                  ^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}template<class U> class G; +CHECK: {{^}}                        ^{{$}} +CHECK: warning: 'G' defined as a struct template here but previously declared as a class template +CHECK: {{^}}template<class U> struct G {}; +CHECK: {{^}}                  ^{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}template<class U> class G; +CHECK: {{^}}                  ^~~~~ +CHECK: {{^}}                  struct +*/ diff --git a/clang/test/SemaCXX/switch-0x.cpp b/clang/test/SemaCXX/switch-0x.cpp new file mode 100644 index 0000000..2e74da0 --- /dev/null +++ b/clang/test/SemaCXX/switch-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// PR5518 +struct A {  +  explicit operator int(); // expected-note{{conversion to integral type}} +}; + +void x() {  +  switch(A()) { // expected-error{{explicit conversion to}} +  } +} diff --git a/clang/test/SemaCXX/switch.cpp b/clang/test/SemaCXX/switch.cpp new file mode 100644 index 0000000..517faa9 --- /dev/null +++ b/clang/test/SemaCXX/switch.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +void test() { +  bool x = true; +  switch (x) { // expected-warning {{bool}} +    case 0: +      break; +  } + +  int n = 3; +  switch (n && true) { // expected-warning {{bool}} +    case 1: +      break; +  } +} + +// PR5518 +struct A {  +  operator int(); // expected-note{{conversion to integral type}} +}; + +void x() {  +  switch(A()) { +  } +} + +enum E { e1, e2 }; +struct B : A { +  operator E() const; // expected-note{{conversion to enumeration type}} +}; + +void x2() { +  switch (B()) { // expected-error{{multiple conversions}} +  } +} + +struct C; // expected-note{{forward declaration}} + +void x3(C &c) { +  switch (c) { // expected-error{{incomplete class type}} +  } +} + +namespace test3 { +  enum En { A, B, C }; +  template <En how> void foo() { +    int x = 0, y = 5; + +    switch (how) { //expected-warning {{no case matching constant switch condition '2'}} +    case A: x *= y; break; +    case B: x += y; break; +    // No case for C, but it's okay because we have a constant condition. +    } +  } + +  template void foo<A>(); +  template void foo<B>(); +  template void foo<C>(); //expected-note {{in instantiation}} +} + +// PR9304 and rdar://9045501 +void click_check_header_sizes() { +  switch (0 == 8) {  // expected-warning {{switch condition has boolean value}} +  case 0: ; +  } +} + +void local_class(int n) { +  for (;;) switch (n) { +  case 0: +    struct S { +      void f() { +        case 1: // expected-error {{'case' statement not in switch statement}} +        break; // expected-error {{'break' statement not in loop or switch statement}} +        default: // expected-error {{'default' statement not in switch statement}} +        continue; // expected-error {{'continue' statement not in loop statement}} +      } +    }; +    S().f(); +    []{ +      case 2: // expected-error {{'case' statement not in switch statement}} +      break; // expected-error {{'break' statement not in loop or switch statement}} +      default: // expected-error {{'default' statement not in switch statement}} +      continue; // expected-error {{'continue' statement not in loop statement}} +    }(); +  } +} diff --git a/clang/test/SemaCXX/tag-ambig.cpp b/clang/test/SemaCXX/tag-ambig.cpp new file mode 100644 index 0000000..6403cf3 --- /dev/null +++ b/clang/test/SemaCXX/tag-ambig.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/9168556> +typedef struct Point Point; + +namespace NameSpace { +  class Point; +} + +using namespace NameSpace; + +class Test +{ +public: +  struct Point { }; +  virtual bool testMethod (Test::Point& p) = 0; +}; + +// PR8151 +namespace A { struct Face {}; } +namespace B { struct Face {}; } +using namespace A; +using namespace B; +  +class C { +  struct Face; +  Face *mFaces; +}; diff --git a/clang/test/SemaCXX/templated-friend-decl.cpp b/clang/test/SemaCXX/templated-friend-decl.cpp new file mode 100644 index 0000000..c0034cd --- /dev/null +++ b/clang/test/SemaCXX/templated-friend-decl.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s + +template <typename T> +struct Foo { +  template <typename U> +  struct Bar {}; + +  // The templated declaration for class Bar should not be instantiated when +  // Foo<int> is. This is to protect against PR5848; for now, this "parses" but +  // requires a rewrite of the templated friend code to be properly fixed. +  template <typename U> +  friend struct Bar; +}; + +Foo<int> x; diff --git a/clang/test/SemaCXX/this.cpp b/clang/test/SemaCXX/this.cpp new file mode 100644 index 0000000..27ee1e8 --- /dev/null +++ b/clang/test/SemaCXX/this.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}} + +void f() { +  int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}} +} diff --git a/clang/test/SemaCXX/trailing-return-0x.cpp b/clang/test/SemaCXX/trailing-return-0x.cpp new file mode 100644 index 0000000..c219b77 --- /dev/null +++ b/clang/test/SemaCXX/trailing-return-0x.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template <class T> +struct only +{ +    only(T) {} + +    template <class U> +    only(U) +    { +        static_assert(sizeof(U) == 0, "expected type failure"); +    } +}; + +auto f() -> int +{ +    return 0; +} + +auto g(); // expected-error{{return without trailing return type}} + +int h() -> int; // expected-error{{trailing return type must specify return type 'auto', not 'int'}} + +int i(); +auto i() -> int; +int i() {} + +using T = auto (int) -> auto (*)(char) -> void; // expected-note {{previous}} +using T = void; // expected-error {{type alias redefinition with different types ('void' vs 'auto (int) -> auto (*)(char) -> void')}} + +using U = auto (int) -> auto (*)(char) -> void; +using U = void (*(int))(char); // ok + +int x; + +template <class T> +auto i(T x) -> decltype(x) +{ +    return x; +} + +only<double> p1 = i(1.0); + +template <class T> +struct X +{ +    auto f(T x) -> T { return x; } + +    template <class U> +    auto g(T x, U y) -> decltype(x + y) +    { +        return x + y; +    } + +  template<typename U> +  struct nested { +    template <class V> +    auto h(T x, U y, V z) -> decltype(x + y + z) +    { +        return x + y + z; +    } +  }; + +  template<typename U> +  nested<U> get_nested(); +}; + +X<int> xx; +only<int> p2 = xx.f(0L); +only<double> p3 = xx.g(0L, 1.0); +only<double> p4 = xx.get_nested<double>().h(0L, 1.0, 3.14f); diff --git a/clang/test/SemaCXX/trivial-constructor.cpp b/clang/test/SemaCXX/trivial-constructor.cpp new file mode 100644 index 0000000..bda206b --- /dev/null +++ b/clang/test/SemaCXX/trivial-constructor.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +struct T1 { +}; +static_assert(__has_trivial_constructor(T1), "T1 has trivial constructor!"); + +struct T2 { +  T2(); +}; +static_assert(!__has_trivial_constructor(T2), "T2 has a user-declared constructor!"); + +struct T3 { +  virtual void f(); +}; +static_assert(!__has_trivial_constructor(T3), "T3 has a virtual function!"); + +struct T4 : virtual T3 { +}; +static_assert(!__has_trivial_constructor(T4), "T4 has a virtual base class!"); + +struct T5 : T1 { +}; +static_assert(__has_trivial_constructor(T5), "All the direct base classes of T5 have trivial constructors!"); + +struct T6 { +  T5 t5; +  T1 t1[2][2]; +  static T2 t2; +}; +static_assert(__has_trivial_constructor(T6), "All nonstatic data members of T6 have trivial constructors!"); + +struct T7 { +  T4 t4; +}; +static_assert(!__has_trivial_constructor(T7), "t4 does not have a trivial constructor!"); + +struct T8 : T2 { +}; +static_assert(!__has_trivial_constructor(T8), "The base class T2 does not have a trivial constructor!"); diff --git a/clang/test/SemaCXX/trivial-destructor.cpp b/clang/test/SemaCXX/trivial-destructor.cpp new file mode 100644 index 0000000..db415cf --- /dev/null +++ b/clang/test/SemaCXX/trivial-destructor.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +struct T1 { +}; +static_assert(__has_trivial_destructor(T1), "T1 has trivial destructor!"); + +struct T2 { +  ~T2(); +}; +static_assert(!__has_trivial_destructor(T2), "T2 has a user-declared destructor!"); + +struct T3 { +  virtual void f(); +}; +static_assert(__has_trivial_destructor(T3), "T3 has a virtual function (but still a trivial destructor)!"); + +struct T4 : virtual T3 { +}; +static_assert(__has_trivial_destructor(T4), "T4 has a virtual base class! (but still a trivial destructor)!"); + +struct T5 : T1 { +}; +static_assert(__has_trivial_destructor(T5), "All the direct base classes of T5 have trivial destructors!"); + +struct T6 { +  T5 t5; +  T1 t1[2][2]; +  static T2 t2; +}; +static_assert(__has_trivial_destructor(T6), "All nonstatic data members of T6 have trivial destructors!"); + +struct T7 { +  T2 t2; +}; +static_assert(!__has_trivial_destructor(T7), "t2 does not have a trivial destructor!"); + +struct T8 : T2 { +}; +static_assert(!__has_trivial_destructor(T8), "The base class T2 does not have a trivial destructor!"); diff --git a/clang/test/SemaCXX/type-convert-construct.cpp b/clang/test/SemaCXX/type-convert-construct.cpp new file mode 100644 index 0000000..479af21 --- /dev/null +++ b/clang/test/SemaCXX/type-convert-construct.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +void f() { +  float v1 = float(1); +  int v2 = typeof(int)(1,2); // expected-error {{excess elements in scalar initializer}} +  typedef int arr[]; +  int v3 = arr(); // expected-error {{array types cannot be value-initialized}} +  int v4 = int(); +  int v5 = int; // expected-error {{expected '(' for function-style cast or type construction}} +  typedef int T; +  int *p; +  bool v6 = T(0) == p; +  char *str; +  str = "a string"; // expected-warning{{conversion from string literal to 'char *' is deprecated}} +  wchar_t *wstr; +  wstr = L"a wide string"; // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}} +} diff --git a/clang/test/SemaCXX/type-definition-in-specifier.cpp b/clang/test/SemaCXX/type-definition-in-specifier.cpp new file mode 100644 index 0000000..a614e6c --- /dev/null +++ b/clang/test/SemaCXX/type-definition-in-specifier.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct S0; +struct S1; +struct S2; +struct S3; +struct S4; +struct S5; +struct S6; + +struct S0 { int x; }; + +void f0() { +  typedef struct S1 { int x; } S1_typedef; + +  (void)((struct S2 { int x; }*)0); // expected-error{{can not be defined}} + +  struct S3 { int x; } s3; + +  (void)static_cast<struct S4 { int x; } *>(0); // expected-error{{can not be defined}} +} + +struct S5 { int x; } f1() { return S5(); } // expected-error{{result type}} + +void f2(struct S6 { int x; } p); // expected-error{{parameter type}} diff --git a/clang/test/SemaCXX/type-dependent-exprs.cpp b/clang/test/SemaCXX/type-dependent-exprs.cpp new file mode 100644 index 0000000..398c3cb --- /dev/null +++ b/clang/test/SemaCXX/type-dependent-exprs.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class X {  +public: +  virtual int f(); +}; + +void g(int); // expected-note{{candidate function}} + +template<typename T> +T f(T x) { +  (void)(x + 0); +  (void)T(0); +  (void)(x += 0); +  (void)(x? x : x); +  (void)static_cast<int>(x); +  (void)reinterpret_cast<int>(x); +  (void)dynamic_cast<X*>(&x); +  (void)const_cast<int>(x); +  return g(x); +  h(x); // h is a dependent name +  g(1, 1); // expected-error{{no matching function for call}} +  h(1); // expected-error{{use of undeclared identifier 'h'}} +  return 0; +} + +// This one entered into an infinite loop. +template <unsigned long N> +void rdar8520617() { +  if (N > 1) { } +} + +int f2() { +  rdar8520617<0>(); +} + diff --git a/clang/test/SemaCXX/type-formatting.cpp b/clang/test/SemaCXX/type-formatting.cpp new file mode 100644 index 0000000..3fe9278 --- /dev/null +++ b/clang/test/SemaCXX/type-formatting.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X0 { }; +struct X1 { }; + +template<typename T> +void f0() { +  const T *t = (const X0*)0; // expected-error{{cannot initialize a variable of type 'const X1 *' with an rvalue of type 'const X0 *'}} +} +template void f0<X1>(); // expected-note{{instantiation of}} diff --git a/clang/test/SemaCXX/type-traits-incomplete.cpp b/clang/test/SemaCXX/type-traits-incomplete.cpp new file mode 100644 index 0000000..c0a520e --- /dev/null +++ b/clang/test/SemaCXX/type-traits-incomplete.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  + +struct S; // expected-note 2 {{forward declaration of 'S'}} + +void f() { +  __is_pod(S); // expected-error{{incomplete type 'S' used in type trait expression}} +  __is_pod(S[]); // expected-error{{incomplete type 'S' used in type trait expression}} +} diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp new file mode 100644 index 0000000..f53939a --- /dev/null +++ b/clang/test/SemaCXX/type-traits.cpp @@ -0,0 +1,1818 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 %s  +#define T(b) (b) ? 1 : -1 +#define F(b) (b) ? -1 : 1 + +struct NonPOD { NonPOD(int); }; + +// PODs +enum Enum { EV }; +struct POD { Enum e; int i; float f; NonPOD* p; }; +struct Empty {}; +typedef Empty EmptyAr[10]; +typedef int Int; +typedef Int IntAr[10]; +typedef Int IntArNB[]; +class Statics { static int priv; static NonPOD np; }; +union EmptyUnion {}; +union Union { int i; float f; }; +struct HasFunc { void f (); }; +struct HasOp { void operator *(); }; +struct HasConv { operator int(); }; +struct HasAssign { void operator =(int); }; + +struct HasAnonymousUnion { +  union { +    int i; +    float f; +  }; +}; + +typedef int Vector __attribute__((vector_size(16))); +typedef int VectorExt __attribute__((ext_vector_type(4))); + +// Not PODs +typedef const void cvoid; +struct Derives : POD {}; +typedef Derives DerivesAr[10]; +typedef Derives DerivesArNB[]; +struct DerivesEmpty : Empty {}; +struct HasCons { HasCons(int); }; +struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); }; +struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; +struct HasDefaultTrivialCopyAssign {  +  HasDefaultTrivialCopyAssign &operator =(const HasDefaultTrivialCopyAssign&) +    = default;  +}; +struct TrivialMoveButNotCopy {  +  TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default; +  TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&); +}; +struct NonTrivialDefault { +  NonTrivialDefault(); +}; + +struct HasDest { ~HasDest(); }; +class  HasPriv { int priv; }; +class  HasProt { protected: int prot; }; +struct HasRef { int i; int& ref; HasRef() : i(0), ref(i) {} }; +struct HasNonPOD { NonPOD np; }; +struct HasVirt { virtual void Virt() {}; }; +typedef NonPOD NonPODAr[10]; +typedef HasVirt VirtAr[10]; +typedef NonPOD NonPODArNB[]; +union NonPODUnion { int i; Derives n; }; +struct DerivesHasCons : HasCons {}; +struct DerivesHasCopyAssign : HasCopyAssign {}; +struct DerivesHasMoveAssign : HasMoveAssign {}; +struct DerivesHasDest : HasDest {}; +struct DerivesHasPriv : HasPriv {}; +struct DerivesHasProt : HasProt {}; +struct DerivesHasRef : HasRef {}; +struct DerivesHasVirt : HasVirt {}; + +struct HasNoThrowCopyAssign { +  void operator =(const HasNoThrowCopyAssign&) throw(); +}; +struct HasMultipleCopyAssign { +  void operator =(const HasMultipleCopyAssign&) throw(); +  void operator =(volatile HasMultipleCopyAssign&); +}; +struct HasMultipleNoThrowCopyAssign { +  void operator =(const HasMultipleNoThrowCopyAssign&) throw(); +  void operator =(volatile HasMultipleNoThrowCopyAssign&) throw(); +}; + +struct HasNoThrowConstructor { HasNoThrowConstructor() throw(); }; +struct HasNoThrowConstructorWithArgs { +  HasNoThrowConstructorWithArgs(HasCons i = HasCons(0)) throw(); +}; + +struct HasNoThrowCopy { HasNoThrowCopy(const HasNoThrowCopy&) throw(); }; +struct HasMultipleCopy { +  HasMultipleCopy(const HasMultipleCopy&) throw(); +  HasMultipleCopy(volatile HasMultipleCopy&); +}; +struct HasMultipleNoThrowCopy { +  HasMultipleNoThrowCopy(const HasMultipleNoThrowCopy&) throw(); +  HasMultipleNoThrowCopy(volatile HasMultipleNoThrowCopy&) throw(); +}; + +struct HasVirtDest { virtual ~HasVirtDest(); }; +struct DerivedVirtDest : HasVirtDest {}; +typedef HasVirtDest VirtDestAr[1]; + +class AllPrivate { +  AllPrivate() throw(); +  AllPrivate(const AllPrivate&) throw(); +  AllPrivate &operator=(const AllPrivate &) throw(); +  ~AllPrivate() throw(); +}; + +struct ThreeArgCtor { +  ThreeArgCtor(int*, char*, int); +}; + +void is_pod() +{ +  { int arr[T(__is_pod(int))]; } +  { int arr[T(__is_pod(Enum))]; } +  { int arr[T(__is_pod(POD))]; } +  { int arr[T(__is_pod(Int))]; } +  { int arr[T(__is_pod(IntAr))]; } +  { int arr[T(__is_pod(Statics))]; } +  { int arr[T(__is_pod(Empty))]; } +  { int arr[T(__is_pod(EmptyUnion))]; } +  { int arr[T(__is_pod(Union))]; } +  { int arr[T(__is_pod(HasFunc))]; } +  { int arr[T(__is_pod(HasOp))]; } +  { int arr[T(__is_pod(HasConv))]; } +  { int arr[T(__is_pod(HasAssign))]; } +  { int arr[T(__is_pod(IntArNB))]; } +  { int arr[T(__is_pod(HasAnonymousUnion))]; } +  { int arr[T(__is_pod(Vector))]; } +  { int arr[T(__is_pod(VectorExt))]; } + +  { int arr[F(__is_pod(Derives))]; } +  { int arr[F(__is_pod(DerivesAr))]; } +  { int arr[F(__is_pod(DerivesArNB))]; } +  { int arr[F(__is_pod(DerivesEmpty))]; } +  { int arr[F(__is_pod(HasCons))]; } +  { int arr[F(__is_pod(HasCopyAssign))]; } +  { int arr[F(__is_pod(HasMoveAssign))]; } +  { int arr[F(__is_pod(HasDest))]; } +  { int arr[F(__is_pod(HasPriv))]; } +  { int arr[F(__is_pod(HasProt))]; } +  { int arr[F(__is_pod(HasRef))]; } +  { int arr[F(__is_pod(HasVirt))]; } +  { int arr[F(__is_pod(DerivesHasCons))]; } +  { int arr[F(__is_pod(DerivesHasCopyAssign))]; } +  { int arr[F(__is_pod(DerivesHasMoveAssign))]; } +  { int arr[F(__is_pod(DerivesHasDest))]; } +  { int arr[F(__is_pod(DerivesHasPriv))]; } +  { int arr[F(__is_pod(DerivesHasProt))]; } +  { int arr[F(__is_pod(DerivesHasRef))]; } +  { int arr[F(__is_pod(DerivesHasVirt))]; } +  { int arr[F(__is_pod(NonPOD))]; } +  { int arr[F(__is_pod(HasNonPOD))]; } +  { int arr[F(__is_pod(NonPODAr))]; } +  { int arr[F(__is_pod(NonPODArNB))]; } +  { int arr[F(__is_pod(void))]; } +  { int arr[F(__is_pod(cvoid))]; } +// { int arr[F(__is_pod(NonPODUnion))]; } +} + +typedef Empty EmptyAr[10]; +struct Bit0 { int : 0; }; +struct Bit0Cons { int : 0; Bit0Cons(); }; +struct BitOnly { int x : 3; }; +//struct DerivesVirt : virtual POD {}; + +void is_empty() +{ +  { int arr[T(__is_empty(Empty))]; } +  { int arr[T(__is_empty(DerivesEmpty))]; } +  { int arr[T(__is_empty(HasCons))]; } +  { int arr[T(__is_empty(HasCopyAssign))]; } +  { int arr[T(__is_empty(HasMoveAssign))]; } +  { int arr[T(__is_empty(HasDest))]; } +  { int arr[T(__is_empty(HasFunc))]; } +  { int arr[T(__is_empty(HasOp))]; } +  { int arr[T(__is_empty(HasConv))]; } +  { int arr[T(__is_empty(HasAssign))]; } +  { int arr[T(__is_empty(Bit0))]; } +  { int arr[T(__is_empty(Bit0Cons))]; } + +  { int arr[F(__is_empty(Int))]; } +  { int arr[F(__is_empty(POD))]; } +  { int arr[F(__is_empty(EmptyUnion))]; } +  { int arr[F(__is_empty(EmptyAr))]; } +  { int arr[F(__is_empty(HasRef))]; } +  { int arr[F(__is_empty(HasVirt))]; } +  { int arr[F(__is_empty(BitOnly))]; } +  { int arr[F(__is_empty(void))]; } +  { int arr[F(__is_empty(IntArNB))]; } +  { int arr[F(__is_empty(HasAnonymousUnion))]; } +//  { int arr[F(__is_empty(DerivesVirt))]; } +} + +typedef Derives ClassType; + +void is_class() +{ +  { int arr[T(__is_class(Derives))]; } +  { int arr[T(__is_class(HasPriv))]; } +  { int arr[T(__is_class(ClassType))]; } +  { int arr[T(__is_class(HasAnonymousUnion))]; } + +  { int arr[F(__is_class(int))]; } +  { int arr[F(__is_class(Enum))]; } +  { int arr[F(__is_class(Int))]; } +  { int arr[F(__is_class(IntAr))]; } +  { int arr[F(__is_class(DerivesAr))]; } +  { int arr[F(__is_class(Union))]; } +  { int arr[F(__is_class(cvoid))]; } +  { int arr[F(__is_class(IntArNB))]; } +} + +typedef Union UnionAr[10]; +typedef Union UnionType; + +void is_union() +{ +  { int arr[T(__is_union(Union))]; } +  { int arr[T(__is_union(UnionType))]; } + +  { int arr[F(__is_union(int))]; } +  { int arr[F(__is_union(Enum))]; } +  { int arr[F(__is_union(Int))]; } +  { int arr[F(__is_union(IntAr))]; } +  { int arr[F(__is_union(UnionAr))]; } +  { int arr[F(__is_union(cvoid))]; } +  { int arr[F(__is_union(IntArNB))]; } +  { int arr[F(__is_union(HasAnonymousUnion))]; } +} + +typedef Enum EnumType; + +void is_enum() +{ +  { int arr[T(__is_enum(Enum))]; } +  { int arr[T(__is_enum(EnumType))]; } + +  { int arr[F(__is_enum(int))]; } +  { int arr[F(__is_enum(Union))]; } +  { int arr[F(__is_enum(Int))]; } +  { int arr[F(__is_enum(IntAr))]; } +  { int arr[F(__is_enum(UnionAr))]; } +  { int arr[F(__is_enum(Derives))]; } +  { int arr[F(__is_enum(ClassType))]; } +  { int arr[F(__is_enum(cvoid))]; } +  { int arr[F(__is_enum(IntArNB))]; } +  { int arr[F(__is_enum(HasAnonymousUnion))]; } +} + +struct FinalClass final { +}; + +template<typename T>  +struct PotentiallyFinal { }; + +template<typename T> +struct PotentiallyFinal<T*> final { }; + +template<> +struct PotentiallyFinal<int> final { }; + +void is_final() +{ +	{ int arr[T(__is_final(FinalClass))]; } +	{ int arr[T(__is_final(PotentiallyFinal<float*>))]; } +	{ int arr[T(__is_final(PotentiallyFinal<int>))]; } + +	{ int arr[F(__is_final(int))]; } +	{ int arr[F(__is_final(Union))]; } +	{ int arr[F(__is_final(Int))]; } +	{ int arr[F(__is_final(IntAr))]; } +	{ int arr[F(__is_final(UnionAr))]; } +	{ int arr[F(__is_final(Derives))]; } +	{ int arr[F(__is_final(ClassType))]; } +	{ int arr[F(__is_final(cvoid))]; } +	{ int arr[F(__is_final(IntArNB))]; } +	{ int arr[F(__is_final(HasAnonymousUnion))]; } +	{ int arr[F(__is_final(PotentiallyFinal<float>))]; } +} + +typedef HasVirt Polymorph; +struct InheritPolymorph : Polymorph {}; + +void is_polymorphic() +{ +  { int arr[T(__is_polymorphic(Polymorph))]; } +  { int arr[T(__is_polymorphic(InheritPolymorph))]; } + +  { int arr[F(__is_polymorphic(int))]; } +  { int arr[F(__is_polymorphic(Union))]; } +  { int arr[F(__is_polymorphic(Int))]; } +  { int arr[F(__is_polymorphic(IntAr))]; } +  { int arr[F(__is_polymorphic(UnionAr))]; } +  { int arr[F(__is_polymorphic(Derives))]; } +  { int arr[F(__is_polymorphic(ClassType))]; } +  { int arr[F(__is_polymorphic(Enum))]; } +  { int arr[F(__is_polymorphic(cvoid))]; } +  { int arr[F(__is_polymorphic(IntArNB))]; } +} + +void is_integral() +{ +  int t01[T(__is_integral(bool))]; +  int t02[T(__is_integral(char))]; +  int t03[T(__is_integral(signed char))]; +  int t04[T(__is_integral(unsigned char))]; +  //int t05[T(__is_integral(char16_t))]; +  //int t06[T(__is_integral(char32_t))]; +  int t07[T(__is_integral(wchar_t))]; +  int t08[T(__is_integral(short))]; +  int t09[T(__is_integral(unsigned short))]; +  int t10[T(__is_integral(int))]; +  int t11[T(__is_integral(unsigned int))]; +  int t12[T(__is_integral(long))]; +  int t13[T(__is_integral(unsigned long))]; + +  int t21[F(__is_integral(float))]; +  int t22[F(__is_integral(double))]; +  int t23[F(__is_integral(long double))]; +  int t24[F(__is_integral(Union))]; +  int t25[F(__is_integral(UnionAr))]; +  int t26[F(__is_integral(Derives))]; +  int t27[F(__is_integral(ClassType))]; +  int t28[F(__is_integral(Enum))]; +  int t29[F(__is_integral(void))]; +  int t30[F(__is_integral(cvoid))]; +  int t31[F(__is_integral(IntArNB))]; +} + +void is_floating_point() +{ +  int t01[T(__is_floating_point(float))]; +  int t02[T(__is_floating_point(double))]; +  int t03[T(__is_floating_point(long double))]; + +  int t11[F(__is_floating_point(bool))]; +  int t12[F(__is_floating_point(char))]; +  int t13[F(__is_floating_point(signed char))]; +  int t14[F(__is_floating_point(unsigned char))]; +  //int t15[F(__is_floating_point(char16_t))]; +  //int t16[F(__is_floating_point(char32_t))]; +  int t17[F(__is_floating_point(wchar_t))]; +  int t18[F(__is_floating_point(short))]; +  int t19[F(__is_floating_point(unsigned short))]; +  int t20[F(__is_floating_point(int))]; +  int t21[F(__is_floating_point(unsigned int))]; +  int t22[F(__is_floating_point(long))]; +  int t23[F(__is_floating_point(unsigned long))]; +  int t24[F(__is_floating_point(Union))]; +  int t25[F(__is_floating_point(UnionAr))]; +  int t26[F(__is_floating_point(Derives))]; +  int t27[F(__is_floating_point(ClassType))]; +  int t28[F(__is_floating_point(Enum))]; +  int t29[F(__is_floating_point(void))]; +  int t30[F(__is_floating_point(cvoid))]; +  int t31[F(__is_floating_point(IntArNB))]; +} + +void is_arithmetic() +{ +  int t01[T(__is_arithmetic(float))]; +  int t02[T(__is_arithmetic(double))]; +  int t03[T(__is_arithmetic(long double))]; +  int t11[T(__is_arithmetic(bool))]; +  int t12[T(__is_arithmetic(char))]; +  int t13[T(__is_arithmetic(signed char))]; +  int t14[T(__is_arithmetic(unsigned char))]; +  //int t15[T(__is_arithmetic(char16_t))]; +  //int t16[T(__is_arithmetic(char32_t))]; +  int t17[T(__is_arithmetic(wchar_t))]; +  int t18[T(__is_arithmetic(short))]; +  int t19[T(__is_arithmetic(unsigned short))]; +  int t20[T(__is_arithmetic(int))]; +  int t21[T(__is_arithmetic(unsigned int))]; +  int t22[T(__is_arithmetic(long))]; +  int t23[T(__is_arithmetic(unsigned long))]; + +  int t24[F(__is_arithmetic(Union))]; +  int t25[F(__is_arithmetic(UnionAr))]; +  int t26[F(__is_arithmetic(Derives))]; +  int t27[F(__is_arithmetic(ClassType))]; +  int t28[F(__is_arithmetic(Enum))]; +  int t29[F(__is_arithmetic(void))]; +  int t30[F(__is_arithmetic(cvoid))]; +  int t31[F(__is_arithmetic(IntArNB))]; +} + +struct ACompleteType {}; +struct AnIncompleteType; + +void is_complete_type() +{ +  int t01[T(__is_complete_type(float))]; +  int t02[T(__is_complete_type(double))]; +  int t03[T(__is_complete_type(long double))]; +  int t11[T(__is_complete_type(bool))]; +  int t12[T(__is_complete_type(char))]; +  int t13[T(__is_complete_type(signed char))]; +  int t14[T(__is_complete_type(unsigned char))]; +  //int t15[T(__is_complete_type(char16_t))]; +  //int t16[T(__is_complete_type(char32_t))]; +  int t17[T(__is_complete_type(wchar_t))]; +  int t18[T(__is_complete_type(short))]; +  int t19[T(__is_complete_type(unsigned short))]; +  int t20[T(__is_complete_type(int))]; +  int t21[T(__is_complete_type(unsigned int))]; +  int t22[T(__is_complete_type(long))]; +  int t23[T(__is_complete_type(unsigned long))]; +  int t24[T(__is_complete_type(ACompleteType))]; + +  int t30[F(__is_complete_type(AnIncompleteType))]; +} + +void is_void() +{ +  int t01[T(__is_void(void))]; +  int t02[T(__is_void(cvoid))]; + +  int t10[F(__is_void(float))]; +  int t11[F(__is_void(double))]; +  int t12[F(__is_void(long double))]; +  int t13[F(__is_void(bool))]; +  int t14[F(__is_void(char))]; +  int t15[F(__is_void(signed char))]; +  int t16[F(__is_void(unsigned char))]; +  int t17[F(__is_void(wchar_t))]; +  int t18[F(__is_void(short))]; +  int t19[F(__is_void(unsigned short))]; +  int t20[F(__is_void(int))]; +  int t21[F(__is_void(unsigned int))]; +  int t22[F(__is_void(long))]; +  int t23[F(__is_void(unsigned long))]; +  int t24[F(__is_void(Union))]; +  int t25[F(__is_void(UnionAr))]; +  int t26[F(__is_void(Derives))]; +  int t27[F(__is_void(ClassType))]; +  int t28[F(__is_void(Enum))]; +  int t29[F(__is_void(IntArNB))]; +  int t30[F(__is_void(void*))]; +  int t31[F(__is_void(cvoid*))]; +} + +void is_array() +{ +  int t01[T(__is_array(IntAr))]; +  int t02[T(__is_array(IntArNB))]; +  int t03[T(__is_array(UnionAr))]; + +  int t10[F(__is_array(void))]; +  int t11[F(__is_array(cvoid))]; +  int t12[F(__is_array(float))]; +  int t13[F(__is_array(double))]; +  int t14[F(__is_array(long double))]; +  int t15[F(__is_array(bool))]; +  int t16[F(__is_array(char))]; +  int t17[F(__is_array(signed char))]; +  int t18[F(__is_array(unsigned char))]; +  int t19[F(__is_array(wchar_t))]; +  int t20[F(__is_array(short))]; +  int t21[F(__is_array(unsigned short))]; +  int t22[F(__is_array(int))]; +  int t23[F(__is_array(unsigned int))]; +  int t24[F(__is_array(long))]; +  int t25[F(__is_array(unsigned long))]; +  int t26[F(__is_array(Union))]; +  int t27[F(__is_array(Derives))]; +  int t28[F(__is_array(ClassType))]; +  int t29[F(__is_array(Enum))]; +  int t30[F(__is_array(void*))]; +  int t31[F(__is_array(cvoid*))]; +} + +template <typename T> void tmpl_func(T&) {} + +template <typename T> struct type_wrapper { +  typedef T type; +  typedef T* ptrtype; +  typedef T& reftype; +}; + +void is_function() +{ +  int t01[T(__is_function(type_wrapper<void(void)>::type))]; +  int t02[T(__is_function(typeof(tmpl_func<int>)))]; + +  typedef void (*ptr_to_func_type)(void); + +  int t10[F(__is_function(void))]; +  int t11[F(__is_function(cvoid))]; +  int t12[F(__is_function(float))]; +  int t13[F(__is_function(double))]; +  int t14[F(__is_function(long double))]; +  int t15[F(__is_function(bool))]; +  int t16[F(__is_function(char))]; +  int t17[F(__is_function(signed char))]; +  int t18[F(__is_function(unsigned char))]; +  int t19[F(__is_function(wchar_t))]; +  int t20[F(__is_function(short))]; +  int t21[F(__is_function(unsigned short))]; +  int t22[F(__is_function(int))]; +  int t23[F(__is_function(unsigned int))]; +  int t24[F(__is_function(long))]; +  int t25[F(__is_function(unsigned long))]; +  int t26[F(__is_function(Union))]; +  int t27[F(__is_function(Derives))]; +  int t28[F(__is_function(ClassType))]; +  int t29[F(__is_function(Enum))]; +  int t30[F(__is_function(void*))]; +  int t31[F(__is_function(cvoid*))]; +  int t32[F(__is_function(void(*)()))]; +  int t33[F(__is_function(ptr_to_func_type))]; +  int t34[F(__is_function(type_wrapper<void(void)>::ptrtype))]; +  int t35[F(__is_function(type_wrapper<void(void)>::reftype))]; +} + +void is_reference() +{ +  int t01[T(__is_reference(int&))]; +  int t02[T(__is_reference(const int&))]; +  int t03[T(__is_reference(void *&))]; + +  int t10[F(__is_reference(int))]; +  int t11[F(__is_reference(const int))]; +  int t12[F(__is_reference(void *))]; +} + +void is_lvalue_reference() +{ +  int t01[T(__is_lvalue_reference(int&))]; +  int t02[T(__is_lvalue_reference(void *&))]; +  int t03[T(__is_lvalue_reference(const int&))]; +  int t04[T(__is_lvalue_reference(void * const &))]; + +  int t10[F(__is_lvalue_reference(int))]; +  int t11[F(__is_lvalue_reference(const int))]; +  int t12[F(__is_lvalue_reference(void *))]; +} + +#if __has_feature(cxx_rvalue_references) + +void is_rvalue_reference() +{ +  int t01[T(__is_rvalue_reference(const int&&))]; +  int t02[T(__is_rvalue_reference(void * const &&))]; + +  int t10[F(__is_rvalue_reference(int&))]; +  int t11[F(__is_rvalue_reference(void *&))]; +  int t12[F(__is_rvalue_reference(const int&))]; +  int t13[F(__is_rvalue_reference(void * const &))]; +  int t14[F(__is_rvalue_reference(int))]; +  int t15[F(__is_rvalue_reference(const int))]; +  int t16[F(__is_rvalue_reference(void *))]; +} + +#endif + +void is_fundamental() +{ +  int t01[T(__is_fundamental(float))]; +  int t02[T(__is_fundamental(double))]; +  int t03[T(__is_fundamental(long double))]; +  int t11[T(__is_fundamental(bool))]; +  int t12[T(__is_fundamental(char))]; +  int t13[T(__is_fundamental(signed char))]; +  int t14[T(__is_fundamental(unsigned char))]; +  //int t15[T(__is_fundamental(char16_t))]; +  //int t16[T(__is_fundamental(char32_t))]; +  int t17[T(__is_fundamental(wchar_t))]; +  int t18[T(__is_fundamental(short))]; +  int t19[T(__is_fundamental(unsigned short))]; +  int t20[T(__is_fundamental(int))]; +  int t21[T(__is_fundamental(unsigned int))]; +  int t22[T(__is_fundamental(long))]; +  int t23[T(__is_fundamental(unsigned long))]; +  int t24[T(__is_fundamental(void))]; +  int t25[T(__is_fundamental(cvoid))]; + +  int t30[F(__is_fundamental(Union))]; +  int t31[F(__is_fundamental(UnionAr))]; +  int t32[F(__is_fundamental(Derives))]; +  int t33[F(__is_fundamental(ClassType))]; +  int t34[F(__is_fundamental(Enum))]; +  int t35[F(__is_fundamental(IntArNB))]; +} + +void is_object() +{ +  int t01[T(__is_object(int))]; +  int t02[T(__is_object(int *))]; +  int t03[T(__is_object(void *))]; +  int t04[T(__is_object(Union))]; +  int t05[T(__is_object(UnionAr))]; +  int t06[T(__is_object(ClassType))]; +  int t07[T(__is_object(Enum))]; + +  int t10[F(__is_object(type_wrapper<void(void)>::type))]; +  int t11[F(__is_object(int&))]; +  int t12[F(__is_object(void))]; +} + +void is_scalar() +{ +  int t01[T(__is_scalar(float))]; +  int t02[T(__is_scalar(double))]; +  int t03[T(__is_scalar(long double))]; +  int t04[T(__is_scalar(bool))]; +  int t05[T(__is_scalar(char))]; +  int t06[T(__is_scalar(signed char))]; +  int t07[T(__is_scalar(unsigned char))]; +  int t08[T(__is_scalar(wchar_t))]; +  int t09[T(__is_scalar(short))]; +  int t10[T(__is_scalar(unsigned short))]; +  int t11[T(__is_scalar(int))]; +  int t12[T(__is_scalar(unsigned int))]; +  int t13[T(__is_scalar(long))]; +  int t14[T(__is_scalar(unsigned long))]; +  int t15[T(__is_scalar(Enum))]; +  int t16[T(__is_scalar(void*))]; +  int t17[T(__is_scalar(cvoid*))]; + +  int t20[F(__is_scalar(void))]; +  int t21[F(__is_scalar(cvoid))]; +  int t22[F(__is_scalar(Union))]; +  int t23[F(__is_scalar(UnionAr))]; +  int t24[F(__is_scalar(Derives))]; +  int t25[F(__is_scalar(ClassType))]; +  int t26[F(__is_scalar(IntArNB))]; +} + +struct StructWithMembers { +  int member; +  void method() {} +}; + +void is_compound() +{ +  int t01[T(__is_compound(void*))]; +  int t02[T(__is_compound(cvoid*))]; +  int t03[T(__is_compound(void (*)()))]; +  int t04[T(__is_compound(int StructWithMembers::*))]; +  int t05[T(__is_compound(void (StructWithMembers::*)()))]; +  int t06[T(__is_compound(int&))]; +  int t07[T(__is_compound(Union))]; +  int t08[T(__is_compound(UnionAr))]; +  int t09[T(__is_compound(Derives))]; +  int t10[T(__is_compound(ClassType))]; +  int t11[T(__is_compound(IntArNB))]; +  int t12[T(__is_compound(Enum))]; + +  int t20[F(__is_compound(float))]; +  int t21[F(__is_compound(double))]; +  int t22[F(__is_compound(long double))]; +  int t23[F(__is_compound(bool))]; +  int t24[F(__is_compound(char))]; +  int t25[F(__is_compound(signed char))]; +  int t26[F(__is_compound(unsigned char))]; +  int t27[F(__is_compound(wchar_t))]; +  int t28[F(__is_compound(short))]; +  int t29[F(__is_compound(unsigned short))]; +  int t30[F(__is_compound(int))]; +  int t31[F(__is_compound(unsigned int))]; +  int t32[F(__is_compound(long))]; +  int t33[F(__is_compound(unsigned long))]; +  int t34[F(__is_compound(void))]; +  int t35[F(__is_compound(cvoid))]; +} + +void is_pointer() +{ +  StructWithMembers x; + +  int t01[T(__is_pointer(void*))]; +  int t02[T(__is_pointer(cvoid*))]; +  int t03[T(__is_pointer(cvoid*))]; +  int t04[T(__is_pointer(char*))]; +  int t05[T(__is_pointer(int*))]; +  int t06[T(__is_pointer(int**))]; +  int t07[T(__is_pointer(ClassType*))]; +  int t08[T(__is_pointer(Derives*))]; +  int t09[T(__is_pointer(Enum*))]; +  int t10[T(__is_pointer(IntArNB*))]; +  int t11[T(__is_pointer(Union*))]; +  int t12[T(__is_pointer(UnionAr*))]; +  int t13[T(__is_pointer(StructWithMembers*))]; +  int t14[T(__is_pointer(void (*)()))]; + +  int t20[F(__is_pointer(void))]; +  int t21[F(__is_pointer(cvoid))]; +  int t22[F(__is_pointer(cvoid))]; +  int t23[F(__is_pointer(char))]; +  int t24[F(__is_pointer(int))]; +  int t25[F(__is_pointer(int))]; +  int t26[F(__is_pointer(ClassType))]; +  int t27[F(__is_pointer(Derives))]; +  int t28[F(__is_pointer(Enum))]; +  int t29[F(__is_pointer(IntArNB))]; +  int t30[F(__is_pointer(Union))]; +  int t31[F(__is_pointer(UnionAr))]; +  int t32[F(__is_pointer(StructWithMembers))]; +  int t33[F(__is_pointer(int StructWithMembers::*))]; +  int t34[F(__is_pointer(void (StructWithMembers::*) ()))]; +} + +void is_member_object_pointer() +{ +  StructWithMembers x; + +  int t01[T(__is_member_object_pointer(int StructWithMembers::*))]; + +  int t10[F(__is_member_object_pointer(void (StructWithMembers::*) ()))]; +  int t11[F(__is_member_object_pointer(void*))]; +  int t12[F(__is_member_object_pointer(cvoid*))]; +  int t13[F(__is_member_object_pointer(cvoid*))]; +  int t14[F(__is_member_object_pointer(char*))]; +  int t15[F(__is_member_object_pointer(int*))]; +  int t16[F(__is_member_object_pointer(int**))]; +  int t17[F(__is_member_object_pointer(ClassType*))]; +  int t18[F(__is_member_object_pointer(Derives*))]; +  int t19[F(__is_member_object_pointer(Enum*))]; +  int t20[F(__is_member_object_pointer(IntArNB*))]; +  int t21[F(__is_member_object_pointer(Union*))]; +  int t22[F(__is_member_object_pointer(UnionAr*))]; +  int t23[F(__is_member_object_pointer(StructWithMembers*))]; +  int t24[F(__is_member_object_pointer(void))]; +  int t25[F(__is_member_object_pointer(cvoid))]; +  int t26[F(__is_member_object_pointer(cvoid))]; +  int t27[F(__is_member_object_pointer(char))]; +  int t28[F(__is_member_object_pointer(int))]; +  int t29[F(__is_member_object_pointer(int))]; +  int t30[F(__is_member_object_pointer(ClassType))]; +  int t31[F(__is_member_object_pointer(Derives))]; +  int t32[F(__is_member_object_pointer(Enum))]; +  int t33[F(__is_member_object_pointer(IntArNB))]; +  int t34[F(__is_member_object_pointer(Union))]; +  int t35[F(__is_member_object_pointer(UnionAr))]; +  int t36[F(__is_member_object_pointer(StructWithMembers))]; +  int t37[F(__is_member_object_pointer(void (*)()))]; +} + +void is_member_function_pointer() +{ +  StructWithMembers x; + +  int t01[T(__is_member_function_pointer(void (StructWithMembers::*) ()))]; + +  int t10[F(__is_member_function_pointer(int StructWithMembers::*))]; +  int t11[F(__is_member_function_pointer(void*))]; +  int t12[F(__is_member_function_pointer(cvoid*))]; +  int t13[F(__is_member_function_pointer(cvoid*))]; +  int t14[F(__is_member_function_pointer(char*))]; +  int t15[F(__is_member_function_pointer(int*))]; +  int t16[F(__is_member_function_pointer(int**))]; +  int t17[F(__is_member_function_pointer(ClassType*))]; +  int t18[F(__is_member_function_pointer(Derives*))]; +  int t19[F(__is_member_function_pointer(Enum*))]; +  int t20[F(__is_member_function_pointer(IntArNB*))]; +  int t21[F(__is_member_function_pointer(Union*))]; +  int t22[F(__is_member_function_pointer(UnionAr*))]; +  int t23[F(__is_member_function_pointer(StructWithMembers*))]; +  int t24[F(__is_member_function_pointer(void))]; +  int t25[F(__is_member_function_pointer(cvoid))]; +  int t26[F(__is_member_function_pointer(cvoid))]; +  int t27[F(__is_member_function_pointer(char))]; +  int t28[F(__is_member_function_pointer(int))]; +  int t29[F(__is_member_function_pointer(int))]; +  int t30[F(__is_member_function_pointer(ClassType))]; +  int t31[F(__is_member_function_pointer(Derives))]; +  int t32[F(__is_member_function_pointer(Enum))]; +  int t33[F(__is_member_function_pointer(IntArNB))]; +  int t34[F(__is_member_function_pointer(Union))]; +  int t35[F(__is_member_function_pointer(UnionAr))]; +  int t36[F(__is_member_function_pointer(StructWithMembers))]; +  int t37[F(__is_member_function_pointer(void (*)()))]; +} + +void is_member_pointer() +{ +  StructWithMembers x; + +  int t01[T(__is_member_pointer(int StructWithMembers::*))]; +  int t02[T(__is_member_pointer(void (StructWithMembers::*) ()))]; + +  int t10[F(__is_member_pointer(void*))]; +  int t11[F(__is_member_pointer(cvoid*))]; +  int t12[F(__is_member_pointer(cvoid*))]; +  int t13[F(__is_member_pointer(char*))]; +  int t14[F(__is_member_pointer(int*))]; +  int t15[F(__is_member_pointer(int**))]; +  int t16[F(__is_member_pointer(ClassType*))]; +  int t17[F(__is_member_pointer(Derives*))]; +  int t18[F(__is_member_pointer(Enum*))]; +  int t19[F(__is_member_pointer(IntArNB*))]; +  int t20[F(__is_member_pointer(Union*))]; +  int t21[F(__is_member_pointer(UnionAr*))]; +  int t22[F(__is_member_pointer(StructWithMembers*))]; +  int t23[F(__is_member_pointer(void))]; +  int t24[F(__is_member_pointer(cvoid))]; +  int t25[F(__is_member_pointer(cvoid))]; +  int t26[F(__is_member_pointer(char))]; +  int t27[F(__is_member_pointer(int))]; +  int t28[F(__is_member_pointer(int))]; +  int t29[F(__is_member_pointer(ClassType))]; +  int t30[F(__is_member_pointer(Derives))]; +  int t31[F(__is_member_pointer(Enum))]; +  int t32[F(__is_member_pointer(IntArNB))]; +  int t33[F(__is_member_pointer(Union))]; +  int t34[F(__is_member_pointer(UnionAr))]; +  int t35[F(__is_member_pointer(StructWithMembers))]; +  int t36[F(__is_member_pointer(void (*)()))]; +} + +void is_const() +{ +  int t01[T(__is_const(cvoid))]; +  int t02[T(__is_const(const char))]; +  int t03[T(__is_const(const int))]; +  int t04[T(__is_const(const long))]; +  int t05[T(__is_const(const short))]; +  int t06[T(__is_const(const signed char))]; +  int t07[T(__is_const(const wchar_t))]; +  int t08[T(__is_const(const bool))]; +  int t09[T(__is_const(const float))]; +  int t10[T(__is_const(const double))]; +  int t11[T(__is_const(const long double))]; +  int t12[T(__is_const(const unsigned char))]; +  int t13[T(__is_const(const unsigned int))]; +  int t14[T(__is_const(const unsigned long long))]; +  int t15[T(__is_const(const unsigned long))]; +  int t16[T(__is_const(const unsigned short))]; +  int t17[T(__is_const(const void))]; +  int t18[T(__is_const(const ClassType))]; +  int t19[T(__is_const(const Derives))]; +  int t20[T(__is_const(const Enum))]; +  int t21[T(__is_const(const IntArNB))]; +  int t22[T(__is_const(const Union))]; +  int t23[T(__is_const(const UnionAr))]; + +  int t30[F(__is_const(char))]; +  int t31[F(__is_const(int))]; +  int t32[F(__is_const(long))]; +  int t33[F(__is_const(short))]; +  int t34[F(__is_const(signed char))]; +  int t35[F(__is_const(wchar_t))]; +  int t36[F(__is_const(bool))]; +  int t37[F(__is_const(float))]; +  int t38[F(__is_const(double))]; +  int t39[F(__is_const(long double))]; +  int t40[F(__is_const(unsigned char))]; +  int t41[F(__is_const(unsigned int))]; +  int t42[F(__is_const(unsigned long long))]; +  int t43[F(__is_const(unsigned long))]; +  int t44[F(__is_const(unsigned short))]; +  int t45[F(__is_const(void))]; +  int t46[F(__is_const(ClassType))]; +  int t47[F(__is_const(Derives))]; +  int t48[F(__is_const(Enum))]; +  int t49[F(__is_const(IntArNB))]; +  int t50[F(__is_const(Union))]; +  int t51[F(__is_const(UnionAr))]; +} + +void is_volatile() +{ +  int t02[T(__is_volatile(volatile char))]; +  int t03[T(__is_volatile(volatile int))]; +  int t04[T(__is_volatile(volatile long))]; +  int t05[T(__is_volatile(volatile short))]; +  int t06[T(__is_volatile(volatile signed char))]; +  int t07[T(__is_volatile(volatile wchar_t))]; +  int t08[T(__is_volatile(volatile bool))]; +  int t09[T(__is_volatile(volatile float))]; +  int t10[T(__is_volatile(volatile double))]; +  int t11[T(__is_volatile(volatile long double))]; +  int t12[T(__is_volatile(volatile unsigned char))]; +  int t13[T(__is_volatile(volatile unsigned int))]; +  int t14[T(__is_volatile(volatile unsigned long long))]; +  int t15[T(__is_volatile(volatile unsigned long))]; +  int t16[T(__is_volatile(volatile unsigned short))]; +  int t17[T(__is_volatile(volatile void))]; +  int t18[T(__is_volatile(volatile ClassType))]; +  int t19[T(__is_volatile(volatile Derives))]; +  int t20[T(__is_volatile(volatile Enum))]; +  int t21[T(__is_volatile(volatile IntArNB))]; +  int t22[T(__is_volatile(volatile Union))]; +  int t23[T(__is_volatile(volatile UnionAr))]; + +  int t30[F(__is_volatile(char))]; +  int t31[F(__is_volatile(int))]; +  int t32[F(__is_volatile(long))]; +  int t33[F(__is_volatile(short))]; +  int t34[F(__is_volatile(signed char))]; +  int t35[F(__is_volatile(wchar_t))]; +  int t36[F(__is_volatile(bool))]; +  int t37[F(__is_volatile(float))]; +  int t38[F(__is_volatile(double))]; +  int t39[F(__is_volatile(long double))]; +  int t40[F(__is_volatile(unsigned char))]; +  int t41[F(__is_volatile(unsigned int))]; +  int t42[F(__is_volatile(unsigned long long))]; +  int t43[F(__is_volatile(unsigned long))]; +  int t44[F(__is_volatile(unsigned short))]; +  int t45[F(__is_volatile(void))]; +  int t46[F(__is_volatile(ClassType))]; +  int t47[F(__is_volatile(Derives))]; +  int t48[F(__is_volatile(Enum))]; +  int t49[F(__is_volatile(IntArNB))]; +  int t50[F(__is_volatile(Union))]; +  int t51[F(__is_volatile(UnionAr))]; +} + +struct TrivialStruct { +  int member; +}; + +struct NonTrivialStruct { +  int member; +  NonTrivialStruct() { +    member = 0; +  } +}; + +struct SuperNonTrivialStruct { +  SuperNonTrivialStruct() { } +  ~SuperNonTrivialStruct() { } +}; + +struct NonTCStruct { +  NonTCStruct(const NonTCStruct&) {} +}; + +struct AllDefaulted { +  AllDefaulted() = default; +  AllDefaulted(const AllDefaulted &) = default; +  AllDefaulted(AllDefaulted &&) = default; +  AllDefaulted &operator=(const AllDefaulted &) = default; +  AllDefaulted &operator=(AllDefaulted &&) = default; +  ~AllDefaulted() = default; +}; + +struct AllDeleted { +  AllDeleted() = delete; +  AllDeleted(const AllDeleted &) = delete; +  AllDeleted(AllDeleted &&) = delete; +  AllDeleted &operator=(const AllDeleted &) = delete; +  AllDeleted &operator=(AllDeleted &&) = delete; +  ~AllDeleted() = delete; +}; + +struct ExtDefaulted { +  ExtDefaulted(); +  ExtDefaulted(const ExtDefaulted &); +  ExtDefaulted(ExtDefaulted &&); +  ExtDefaulted &operator=(const ExtDefaulted &); +  ExtDefaulted &operator=(ExtDefaulted &&); +  ~ExtDefaulted(); +}; + +// Despite being defaulted, these functions are not trivial. +ExtDefaulted::ExtDefaulted() = default; +ExtDefaulted::ExtDefaulted(const ExtDefaulted &) = default; +ExtDefaulted::ExtDefaulted(ExtDefaulted &&) = default; +ExtDefaulted &ExtDefaulted::operator=(const ExtDefaulted &) = default; +ExtDefaulted &ExtDefaulted::operator=(ExtDefaulted &&) = default; +ExtDefaulted::~ExtDefaulted() = default; + +void is_trivial2() +{ +  int t01[T(__is_trivial(char))]; +  int t02[T(__is_trivial(int))]; +  int t03[T(__is_trivial(long))]; +  int t04[T(__is_trivial(short))]; +  int t05[T(__is_trivial(signed char))]; +  int t06[T(__is_trivial(wchar_t))]; +  int t07[T(__is_trivial(bool))]; +  int t08[T(__is_trivial(float))]; +  int t09[T(__is_trivial(double))]; +  int t10[T(__is_trivial(long double))]; +  int t11[T(__is_trivial(unsigned char))]; +  int t12[T(__is_trivial(unsigned int))]; +  int t13[T(__is_trivial(unsigned long long))]; +  int t14[T(__is_trivial(unsigned long))]; +  int t15[T(__is_trivial(unsigned short))]; +  int t16[T(__is_trivial(ClassType))]; +  int t17[T(__is_trivial(Derives))]; +  int t18[T(__is_trivial(Enum))]; +  int t19[T(__is_trivial(IntAr))]; +  int t20[T(__is_trivial(Union))]; +  int t21[T(__is_trivial(UnionAr))]; +  int t22[T(__is_trivial(TrivialStruct))]; +  int t23[T(__is_trivial(AllDefaulted))]; +  int t24[T(__is_trivial(AllDeleted))]; + +  int t30[F(__is_trivial(void))]; +  int t31[F(__is_trivial(NonTrivialStruct))]; +  int t32[F(__is_trivial(SuperNonTrivialStruct))]; +  int t33[F(__is_trivial(NonTCStruct))]; +  int t34[F(__is_trivial(ExtDefaulted))]; +} + +void is_trivially_copyable2() +{ +  int t01[T(__is_trivially_copyable(char))]; +  int t02[T(__is_trivially_copyable(int))]; +  int t03[T(__is_trivially_copyable(long))]; +  int t04[T(__is_trivially_copyable(short))]; +  int t05[T(__is_trivially_copyable(signed char))]; +  int t06[T(__is_trivially_copyable(wchar_t))]; +  int t07[T(__is_trivially_copyable(bool))]; +  int t08[T(__is_trivially_copyable(float))]; +  int t09[T(__is_trivially_copyable(double))]; +  int t10[T(__is_trivially_copyable(long double))]; +  int t11[T(__is_trivially_copyable(unsigned char))]; +  int t12[T(__is_trivially_copyable(unsigned int))]; +  int t13[T(__is_trivially_copyable(unsigned long long))]; +  int t14[T(__is_trivially_copyable(unsigned long))]; +  int t15[T(__is_trivially_copyable(unsigned short))]; +  int t16[T(__is_trivially_copyable(ClassType))]; +  int t17[T(__is_trivially_copyable(Derives))]; +  int t18[T(__is_trivially_copyable(Enum))]; +  int t19[T(__is_trivially_copyable(IntAr))]; +  int t20[T(__is_trivially_copyable(Union))]; +  int t21[T(__is_trivially_copyable(UnionAr))]; +  int t22[T(__is_trivially_copyable(TrivialStruct))]; +  int t23[T(__is_trivially_copyable(NonTrivialStruct))]; +  int t24[T(__is_trivially_copyable(AllDefaulted))]; +  int t25[T(__is_trivially_copyable(AllDeleted))]; + +  int t30[F(__is_trivially_copyable(void))]; +  int t31[F(__is_trivially_copyable(SuperNonTrivialStruct))]; +  int t32[F(__is_trivially_copyable(NonTCStruct))]; +  int t33[F(__is_trivially_copyable(ExtDefaulted))]; +} + +struct CStruct { +  int one; +  int two; +}; + +struct CEmptyStruct {}; + +struct CppEmptyStruct : CStruct {}; +struct CppStructStandard : CEmptyStruct { +  int three; +  int four; +}; +struct CppStructNonStandardByBase : CStruct { +  int three; +  int four; +}; +struct CppStructNonStandardByVirt : CStruct { +  virtual void method() {} +}; +struct CppStructNonStandardByMemb : CStruct { +  CppStructNonStandardByVirt member; +}; +struct CppStructNonStandardByProt : CStruct { +  int five; +protected: +  int six; +}; +struct CppStructNonStandardByVirtBase : virtual CStruct { +}; +struct CppStructNonStandardBySameBase : CEmptyStruct { +  CEmptyStruct member; +}; +struct CppStructNonStandardBy2ndVirtBase : CEmptyStruct { +  CEmptyStruct member; +}; + +void is_standard_layout() +{ +  typedef const int ConstInt; +  typedef ConstInt ConstIntAr[4]; +  typedef CppStructStandard CppStructStandardAr[4]; + +  int t01[T(__is_standard_layout(int))]; +  int t02[T(__is_standard_layout(ConstInt))]; +  int t03[T(__is_standard_layout(ConstIntAr))]; +  int t04[T(__is_standard_layout(CStruct))]; +  int t05[T(__is_standard_layout(CppStructStandard))]; +  int t06[T(__is_standard_layout(CppStructStandardAr))]; +  int t07[T(__is_standard_layout(Vector))]; +  int t08[T(__is_standard_layout(VectorExt))]; + +  typedef CppStructNonStandardByBase CppStructNonStandardByBaseAr[4]; + +  int t10[F(__is_standard_layout(CppStructNonStandardByVirt))]; +  int t11[F(__is_standard_layout(CppStructNonStandardByMemb))]; +  int t12[F(__is_standard_layout(CppStructNonStandardByProt))]; +  int t13[F(__is_standard_layout(CppStructNonStandardByVirtBase))]; +  int t14[F(__is_standard_layout(CppStructNonStandardByBase))]; +  int t15[F(__is_standard_layout(CppStructNonStandardByBaseAr))]; +  int t16[F(__is_standard_layout(CppStructNonStandardBySameBase))]; +  int t17[F(__is_standard_layout(CppStructNonStandardBy2ndVirtBase))]; +} + +void is_signed() +{ +  //int t01[T(__is_signed(char))]; +  int t02[T(__is_signed(int))]; +  int t03[T(__is_signed(long))]; +  int t04[T(__is_signed(short))]; +  int t05[T(__is_signed(signed char))]; +  int t06[T(__is_signed(wchar_t))]; + +  int t10[F(__is_signed(bool))]; +  int t11[F(__is_signed(cvoid))]; +  int t12[F(__is_signed(float))]; +  int t13[F(__is_signed(double))]; +  int t14[F(__is_signed(long double))]; +  int t15[F(__is_signed(unsigned char))]; +  int t16[F(__is_signed(unsigned int))]; +  int t17[F(__is_signed(unsigned long long))]; +  int t18[F(__is_signed(unsigned long))]; +  int t19[F(__is_signed(unsigned short))]; +  int t20[F(__is_signed(void))]; +  int t21[F(__is_signed(ClassType))]; +  int t22[F(__is_signed(Derives))]; +  int t23[F(__is_signed(Enum))]; +  int t24[F(__is_signed(IntArNB))]; +  int t25[F(__is_signed(Union))]; +  int t26[F(__is_signed(UnionAr))]; +} + +void is_unsigned() +{ +  int t01[T(__is_unsigned(bool))]; +  int t02[T(__is_unsigned(unsigned char))]; +  int t03[T(__is_unsigned(unsigned short))]; +  int t04[T(__is_unsigned(unsigned int))]; +  int t05[T(__is_unsigned(unsigned long))]; +  int t06[T(__is_unsigned(unsigned long long))]; +  int t07[T(__is_unsigned(Enum))]; + +  int t10[F(__is_unsigned(void))]; +  int t11[F(__is_unsigned(cvoid))]; +  int t12[F(__is_unsigned(float))]; +  int t13[F(__is_unsigned(double))]; +  int t14[F(__is_unsigned(long double))]; +  int t16[F(__is_unsigned(char))]; +  int t17[F(__is_unsigned(signed char))]; +  int t18[F(__is_unsigned(wchar_t))]; +  int t19[F(__is_unsigned(short))]; +  int t20[F(__is_unsigned(int))]; +  int t21[F(__is_unsigned(long))]; +  int t22[F(__is_unsigned(Union))]; +  int t23[F(__is_unsigned(UnionAr))]; +  int t24[F(__is_unsigned(Derives))]; +  int t25[F(__is_unsigned(ClassType))]; +  int t26[F(__is_unsigned(IntArNB))]; +} + +typedef Int& IntRef; +typedef const IntAr ConstIntAr; +typedef ConstIntAr ConstIntArAr[4]; + +struct HasCopy { +  HasCopy(HasCopy& cp); +}; + +struct HasMove { +  HasMove(HasMove&& cp); +}; + +struct HasTemplateCons { +  HasVirt Annoying; + +  template <typename T> +  HasTemplateCons(const T&); +}; + +void has_trivial_default_constructor() { +  { int arr[T(__has_trivial_constructor(Int))]; } +  { int arr[T(__has_trivial_constructor(IntAr))]; } +  { int arr[T(__has_trivial_constructor(Union))]; } +  { int arr[T(__has_trivial_constructor(UnionAr))]; } +  { int arr[T(__has_trivial_constructor(POD))]; } +  { int arr[T(__has_trivial_constructor(Derives))]; } +  { int arr[T(__has_trivial_constructor(DerivesAr))]; } +  { int arr[T(__has_trivial_constructor(ConstIntAr))]; } +  { int arr[T(__has_trivial_constructor(ConstIntArAr))]; } +  { int arr[T(__has_trivial_constructor(HasDest))]; } +  { int arr[T(__has_trivial_constructor(HasPriv))]; } +  { int arr[T(__has_trivial_constructor(HasCopyAssign))]; } +  { int arr[T(__has_trivial_constructor(HasMoveAssign))]; } +  { int arr[T(__has_trivial_constructor(const Int))]; } +  { int arr[T(__has_trivial_constructor(AllDefaulted))]; } +  { int arr[T(__has_trivial_constructor(AllDeleted))]; } + +  { int arr[F(__has_trivial_constructor(HasCons))]; } +  { int arr[F(__has_trivial_constructor(HasRef))]; } +  { int arr[F(__has_trivial_constructor(HasCopy))]; } +  { int arr[F(__has_trivial_constructor(IntRef))]; } +  { int arr[F(__has_trivial_constructor(VirtAr))]; } +  { int arr[F(__has_trivial_constructor(void))]; } +  { int arr[F(__has_trivial_constructor(cvoid))]; } +  { int arr[F(__has_trivial_constructor(HasTemplateCons))]; } +  { int arr[F(__has_trivial_constructor(AllPrivate))]; } +  { int arr[F(__has_trivial_constructor(ExtDefaulted))]; } +} + +void has_trivial_copy_constructor() { +  { int arr[T(__has_trivial_copy(Int))]; } +  { int arr[T(__has_trivial_copy(IntAr))]; } +  { int arr[T(__has_trivial_copy(Union))]; } +  { int arr[T(__has_trivial_copy(UnionAr))]; } +  { int arr[T(__has_trivial_copy(POD))]; } +  { int arr[T(__has_trivial_copy(Derives))]; } +  { int arr[T(__has_trivial_copy(ConstIntAr))]; } +  { int arr[T(__has_trivial_copy(ConstIntArAr))]; } +  { int arr[T(__has_trivial_copy(HasDest))]; } +  { int arr[T(__has_trivial_copy(HasPriv))]; } +  { int arr[T(__has_trivial_copy(HasCons))]; } +  { int arr[T(__has_trivial_copy(HasRef))]; } +  { int arr[T(__has_trivial_copy(HasMove))]; } +  { int arr[T(__has_trivial_copy(IntRef))]; } +  { int arr[T(__has_trivial_copy(HasCopyAssign))]; } +  { int arr[T(__has_trivial_copy(HasMoveAssign))]; } +  { int arr[T(__has_trivial_copy(const Int))]; } +  { int arr[T(__has_trivial_copy(AllDefaulted))]; } +  { int arr[T(__has_trivial_copy(AllDeleted))]; } + +  { int arr[F(__has_trivial_copy(HasCopy))]; } +  { int arr[F(__has_trivial_copy(HasTemplateCons))]; } +  { int arr[F(__has_trivial_copy(DerivesAr))]; } +  { int arr[F(__has_trivial_copy(VirtAr))]; } +  { int arr[F(__has_trivial_copy(void))]; } +  { int arr[F(__has_trivial_copy(cvoid))]; } +  { int arr[F(__has_trivial_copy(AllPrivate))]; } +  { int arr[F(__has_trivial_copy(ExtDefaulted))]; } +} + +void has_trivial_copy_assignment() { +  { int arr[T(__has_trivial_assign(Int))]; } +  { int arr[T(__has_trivial_assign(IntAr))]; } +  { int arr[T(__has_trivial_assign(Union))]; } +  { int arr[T(__has_trivial_assign(UnionAr))]; } +  { int arr[T(__has_trivial_assign(POD))]; } +  { int arr[T(__has_trivial_assign(Derives))]; } +  { int arr[T(__has_trivial_assign(HasDest))]; } +  { int arr[T(__has_trivial_assign(HasPriv))]; } +  { int arr[T(__has_trivial_assign(HasCons))]; } +  { int arr[T(__has_trivial_assign(HasRef))]; } +  { int arr[T(__has_trivial_assign(HasCopy))]; } +  { int arr[T(__has_trivial_assign(HasMove))]; } +  { int arr[T(__has_trivial_assign(HasMoveAssign))]; } +  { int arr[T(__has_trivial_assign(AllDefaulted))]; } +  { int arr[T(__has_trivial_assign(AllDeleted))]; } + +  { int arr[F(__has_trivial_assign(IntRef))]; } +  { int arr[F(__has_trivial_assign(HasCopyAssign))]; } +  { int arr[F(__has_trivial_assign(const Int))]; } +  { int arr[F(__has_trivial_assign(ConstIntAr))]; } +  { int arr[F(__has_trivial_assign(ConstIntArAr))]; } +  { int arr[F(__has_trivial_assign(DerivesAr))]; } +  { int arr[F(__has_trivial_assign(VirtAr))]; } +  { int arr[F(__has_trivial_assign(void))]; } +  { int arr[F(__has_trivial_assign(cvoid))]; } +  { int arr[F(__has_trivial_assign(AllPrivate))]; } +  { int arr[F(__has_trivial_assign(ExtDefaulted))]; } +} + +void has_trivial_destructor() { +  { int arr[T(__has_trivial_destructor(Int))]; } +  { int arr[T(__has_trivial_destructor(IntAr))]; } +  { int arr[T(__has_trivial_destructor(Union))]; } +  { int arr[T(__has_trivial_destructor(UnionAr))]; } +  { int arr[T(__has_trivial_destructor(POD))]; } +  { int arr[T(__has_trivial_destructor(Derives))]; } +  { int arr[T(__has_trivial_destructor(ConstIntAr))]; } +  { int arr[T(__has_trivial_destructor(ConstIntArAr))]; } +  { int arr[T(__has_trivial_destructor(HasPriv))]; } +  { int arr[T(__has_trivial_destructor(HasCons))]; } +  { int arr[T(__has_trivial_destructor(HasRef))]; } +  { int arr[T(__has_trivial_destructor(HasCopy))]; } +  { int arr[T(__has_trivial_destructor(HasMove))]; } +  { int arr[T(__has_trivial_destructor(IntRef))]; } +  { int arr[T(__has_trivial_destructor(HasCopyAssign))]; } +  { int arr[T(__has_trivial_destructor(HasMoveAssign))]; } +  { int arr[T(__has_trivial_destructor(const Int))]; } +  { int arr[T(__has_trivial_destructor(DerivesAr))]; } +  { int arr[T(__has_trivial_destructor(VirtAr))]; } +  { int arr[T(__has_trivial_destructor(AllDefaulted))]; } +  { int arr[T(__has_trivial_destructor(AllDeleted))]; } + +  { int arr[F(__has_trivial_destructor(HasDest))]; } +  { int arr[F(__has_trivial_destructor(void))]; } +  { int arr[F(__has_trivial_destructor(cvoid))]; } +  { int arr[F(__has_trivial_destructor(AllPrivate))]; } +  { int arr[F(__has_trivial_destructor(ExtDefaulted))]; } +} + +struct A { ~A() {} }; +template<typename> struct B : A { }; + +void f() { +  { int arr[F(__has_trivial_destructor(A))]; } +  { int arr[F(__has_trivial_destructor(B<int>))]; } +} + +class PR11110 { +  template <int> int operator=( int ); +  int operator=(PR11110); +}; + +class UsingAssign; + +class UsingAssignBase { +protected: +  UsingAssign &operator=(const UsingAssign&) throw(); +}; + +class UsingAssign : public UsingAssignBase { +public: +  using UsingAssignBase::operator=; +}; + +void has_nothrow_assign() { +  { int arr[T(__has_nothrow_assign(Int))]; } +  { int arr[T(__has_nothrow_assign(IntAr))]; } +  { int arr[T(__has_nothrow_assign(Union))]; } +  { int arr[T(__has_nothrow_assign(UnionAr))]; } +  { int arr[T(__has_nothrow_assign(POD))]; } +  { int arr[T(__has_nothrow_assign(Derives))]; } +  { int arr[T(__has_nothrow_assign(HasDest))]; } +  { int arr[T(__has_nothrow_assign(HasPriv))]; } +  { int arr[T(__has_nothrow_assign(HasCons))]; } +  { int arr[T(__has_nothrow_assign(HasRef))]; } +  { int arr[T(__has_nothrow_assign(HasCopy))]; } +  { int arr[T(__has_nothrow_assign(HasMove))]; } +  { int arr[T(__has_nothrow_assign(HasMoveAssign))]; } +  { int arr[T(__has_nothrow_assign(HasNoThrowCopyAssign))]; } +  { int arr[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))]; } +  { int arr[T(__has_nothrow_assign(HasVirtDest))]; } +  { int arr[T(__has_nothrow_assign(AllPrivate))]; } +  { int arr[T(__has_nothrow_assign(UsingAssign))]; } + +  { int arr[F(__has_nothrow_assign(IntRef))]; } +  { int arr[F(__has_nothrow_assign(HasCopyAssign))]; } +  { int arr[F(__has_nothrow_assign(HasMultipleCopyAssign))]; } +  { int arr[F(__has_nothrow_assign(const Int))]; } +  { int arr[F(__has_nothrow_assign(ConstIntAr))]; } +  { int arr[F(__has_nothrow_assign(ConstIntArAr))]; } +  { int arr[F(__has_nothrow_assign(DerivesAr))]; } +  { int arr[F(__has_nothrow_assign(VirtAr))]; } +  { int arr[F(__has_nothrow_assign(void))]; } +  { int arr[F(__has_nothrow_assign(cvoid))]; } +  { int arr[F(__has_nothrow_assign(PR11110))]; } +} + +void has_nothrow_copy() { +  { int arr[T(__has_nothrow_copy(Int))]; } +  { int arr[T(__has_nothrow_copy(IntAr))]; } +  { int arr[T(__has_nothrow_copy(Union))]; } +  { int arr[T(__has_nothrow_copy(UnionAr))]; } +  { int arr[T(__has_nothrow_copy(POD))]; } +  { int arr[T(__has_nothrow_copy(const Int))]; } +  { int arr[T(__has_nothrow_copy(ConstIntAr))]; } +  { int arr[T(__has_nothrow_copy(ConstIntArAr))]; } +  { int arr[T(__has_nothrow_copy(Derives))]; } +  { int arr[T(__has_nothrow_copy(IntRef))]; } +  { int arr[T(__has_nothrow_copy(HasDest))]; } +  { int arr[T(__has_nothrow_copy(HasPriv))]; } +  { int arr[T(__has_nothrow_copy(HasCons))]; } +  { int arr[T(__has_nothrow_copy(HasRef))]; } +  { int arr[T(__has_nothrow_copy(HasMove))]; } +  { int arr[T(__has_nothrow_copy(HasCopyAssign))]; } +  { int arr[T(__has_nothrow_copy(HasMoveAssign))]; } +  { int arr[T(__has_nothrow_copy(HasNoThrowCopy))]; } +  { int arr[T(__has_nothrow_copy(HasMultipleNoThrowCopy))]; } +  { int arr[T(__has_nothrow_copy(HasVirtDest))]; } +  { int arr[T(__has_nothrow_copy(HasTemplateCons))]; } +  { int arr[T(__has_nothrow_copy(AllPrivate))]; } + +  { int arr[F(__has_nothrow_copy(HasCopy))]; } +  { int arr[F(__has_nothrow_copy(HasMultipleCopy))]; } +  { int arr[F(__has_nothrow_copy(DerivesAr))]; } +  { int arr[F(__has_nothrow_copy(VirtAr))]; } +  { int arr[F(__has_nothrow_copy(void))]; } +  { int arr[F(__has_nothrow_copy(cvoid))]; } +} + +template<bool b> struct assert_expr; +template<> struct assert_expr<true> {}; + +void has_nothrow_constructor() { +  { int arr[T(__has_nothrow_constructor(Int))]; } +  { int arr[T(__has_nothrow_constructor(IntAr))]; } +  { int arr[T(__has_nothrow_constructor(Union))]; } +  { int arr[T(__has_nothrow_constructor(UnionAr))]; } +  { int arr[T(__has_nothrow_constructor(POD))]; } +  { int arr[T(__has_nothrow_constructor(Derives))]; } +  { int arr[T(__has_nothrow_constructor(DerivesAr))]; } +  { int arr[T(__has_nothrow_constructor(ConstIntAr))]; } +  { int arr[T(__has_nothrow_constructor(ConstIntArAr))]; } +  { int arr[T(__has_nothrow_constructor(HasDest))]; } +  { int arr[T(__has_nothrow_constructor(HasPriv))]; } +  { int arr[T(__has_nothrow_constructor(HasCopyAssign))]; } +  { int arr[T(__has_nothrow_constructor(const Int))]; } +  { int arr[T(__has_nothrow_constructor(HasNoThrowConstructor))]; } +  { int arr[T(__has_nothrow_constructor(HasVirtDest))]; } +  // { int arr[T(__has_nothrow_constructor(VirtAr))]; } // not implemented +  { int arr[T(__has_nothrow_constructor(AllPrivate))]; } + +  { int arr[F(__has_nothrow_constructor(HasCons))]; } +  { int arr[F(__has_nothrow_constructor(HasRef))]; } +  { int arr[F(__has_nothrow_constructor(HasCopy))]; } +  { int arr[F(__has_nothrow_constructor(HasMove))]; } +  { int arr[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))]; } +  { int arr[F(__has_nothrow_constructor(IntRef))]; } +  { int arr[F(__has_nothrow_constructor(void))]; } +  { int arr[F(__has_nothrow_constructor(cvoid))]; } +  { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; } + +  // While parsing an in-class initializer, the constructor is not known to be +  // non-throwing yet. +  struct HasInClassInit { int n = (assert_expr<!__has_nothrow_constructor(HasInClassInit)>(), 0); }; +  { int arr[T(__has_nothrow_constructor(HasInClassInit))]; } +} + +void has_virtual_destructor() { +  { int arr[F(__has_virtual_destructor(Int))]; } +  { int arr[F(__has_virtual_destructor(IntAr))]; } +  { int arr[F(__has_virtual_destructor(Union))]; } +  { int arr[F(__has_virtual_destructor(UnionAr))]; } +  { int arr[F(__has_virtual_destructor(POD))]; } +  { int arr[F(__has_virtual_destructor(Derives))]; } +  { int arr[F(__has_virtual_destructor(DerivesAr))]; } +  { int arr[F(__has_virtual_destructor(const Int))]; } +  { int arr[F(__has_virtual_destructor(ConstIntAr))]; } +  { int arr[F(__has_virtual_destructor(ConstIntArAr))]; } +  { int arr[F(__has_virtual_destructor(HasDest))]; } +  { int arr[F(__has_virtual_destructor(HasPriv))]; } +  { int arr[F(__has_virtual_destructor(HasCons))]; } +  { int arr[F(__has_virtual_destructor(HasRef))]; } +  { int arr[F(__has_virtual_destructor(HasCopy))]; } +  { int arr[F(__has_virtual_destructor(HasMove))]; } +  { int arr[F(__has_virtual_destructor(HasCopyAssign))]; } +  { int arr[F(__has_virtual_destructor(HasMoveAssign))]; } +  { int arr[F(__has_virtual_destructor(IntRef))]; } +  { int arr[F(__has_virtual_destructor(VirtAr))]; } + +  { int arr[T(__has_virtual_destructor(HasVirtDest))]; } +  { int arr[T(__has_virtual_destructor(DerivedVirtDest))]; } +  { int arr[F(__has_virtual_destructor(VirtDestAr))]; } +  { int arr[F(__has_virtual_destructor(void))]; } +  { int arr[F(__has_virtual_destructor(cvoid))]; } +  { int arr[F(__has_virtual_destructor(AllPrivate))]; } +} + + +class Base {}; +class Derived : Base {}; +class Derived2a : Derived {}; +class Derived2b : Derived {}; +class Derived3 : virtual Derived2a, virtual Derived2b {}; +template<typename T> struct BaseA { T a;  }; +template<typename T> struct DerivedB : BaseA<T> { }; +template<typename T> struct CrazyDerived : T { }; + + +class class_forward; // expected-note {{forward declaration of 'class_forward'}} + +template <typename Base, typename Derived> +void isBaseOfT() { +  int t[T(__is_base_of(Base, Derived))]; +}; +template <typename Base, typename Derived> +void isBaseOfF() { +  int t[F(__is_base_of(Base, Derived))]; +}; + +template <class T> class DerivedTemp : Base {}; +template <class T> class NonderivedTemp {}; +template <class T> class UndefinedTemp; // expected-note {{declared here}} + +void is_base_of() { +  { int arr[T(__is_base_of(Base, Derived))]; } +  { int arr[T(__is_base_of(const Base, Derived))]; } +  { int arr[F(__is_base_of(Derived, Base))]; } +  { int arr[F(__is_base_of(Derived, int))]; } +  { int arr[T(__is_base_of(Base, Base))]; } +  { int arr[T(__is_base_of(Base, Derived3))]; } +  { int arr[T(__is_base_of(Derived, Derived3))]; } +  { int arr[T(__is_base_of(Derived2b, Derived3))]; } +  { int arr[T(__is_base_of(Derived2a, Derived3))]; } +  { int arr[T(__is_base_of(BaseA<int>, DerivedB<int>))]; } +  { int arr[F(__is_base_of(DerivedB<int>, BaseA<int>))]; } +  { int arr[T(__is_base_of(Base, CrazyDerived<Base>))]; } +  { int arr[F(__is_base_of(Union, Union))]; } +  { int arr[T(__is_base_of(Empty, Empty))]; } +  { int arr[T(__is_base_of(class_forward, class_forward))]; } +  { int arr[F(__is_base_of(Empty, class_forward))]; } // expected-error {{incomplete type 'class_forward' used in type trait expression}} +  { int arr[F(__is_base_of(Base&, Derived&))]; } +  int t18[F(__is_base_of(Base[10], Derived[10]))]; +  { int arr[F(__is_base_of(int, int))]; } +  { int arr[F(__is_base_of(long, int))]; } +  { int arr[T(__is_base_of(Base, DerivedTemp<int>))]; } +  { int arr[F(__is_base_of(Base, NonderivedTemp<int>))]; } +  { int arr[F(__is_base_of(Base, UndefinedTemp<int>))]; } // expected-error {{implicit instantiation of undefined template 'UndefinedTemp<int>'}} + +  isBaseOfT<Base, Derived>(); +  isBaseOfF<Derived, Base>(); + +  isBaseOfT<Base, CrazyDerived<Base> >(); +  isBaseOfF<CrazyDerived<Base>, Base>(); + +  isBaseOfT<BaseA<int>, DerivedB<int> >(); +  isBaseOfF<DerivedB<int>, BaseA<int> >(); +} + +template<class T, class U> +class TemplateClass {}; + +template<class T> +using TemplateAlias = TemplateClass<T, int>; + +typedef class Base BaseTypedef; + +void is_same() +{ +  int t01[T(__is_same(Base, Base))]; +  int t02[T(__is_same(Base, BaseTypedef))]; +  int t03[T(__is_same(TemplateClass<int, int>, TemplateAlias<int>))]; + +  int t10[F(__is_same(Base, const Base))]; +  int t11[F(__is_same(Base, Base&))]; +  int t12[F(__is_same(Base, Derived))]; +} + +struct IntWrapper +{ +  int value; +  IntWrapper(int _value) : value(_value) {} +  operator int() const { +    return value; +  } +}; + +struct FloatWrapper +{ +  float value; +  FloatWrapper(float _value) : value(_value) {} +  FloatWrapper(const IntWrapper& obj) +    : value(static_cast<float>(obj.value)) {} +  operator float() const { +    return value; +  } +  operator IntWrapper() const { +    return IntWrapper(static_cast<int>(value)); +  } +}; + +void is_convertible() +{ +  int t01[T(__is_convertible(IntWrapper, IntWrapper))]; +  int t02[T(__is_convertible(IntWrapper, const IntWrapper))]; +  int t03[T(__is_convertible(IntWrapper, int))]; +  int t04[T(__is_convertible(int, IntWrapper))]; +  int t05[T(__is_convertible(IntWrapper, FloatWrapper))]; +  int t06[T(__is_convertible(FloatWrapper, IntWrapper))]; +  int t07[T(__is_convertible(FloatWrapper, float))]; +  int t08[T(__is_convertible(float, FloatWrapper))]; +} + +struct FromInt { FromInt(int); }; +struct ToInt { operator int(); }; +typedef void Function(); + +void is_convertible_to(); +class PrivateCopy { +  PrivateCopy(const PrivateCopy&); +  friend void is_convertible_to(); +}; + +template<typename T> +struct X0 {  +  template<typename U> X0(const X0<U>&); +}; + +void is_convertible_to() { +  { int arr[T(__is_convertible_to(Int, Int))]; } +  { int arr[F(__is_convertible_to(Int, IntAr))]; } +  { int arr[F(__is_convertible_to(IntAr, IntAr))]; } +  { int arr[T(__is_convertible_to(void, void))]; } +  { int arr[T(__is_convertible_to(cvoid, void))]; } +  { int arr[T(__is_convertible_to(void, cvoid))]; } +  { int arr[T(__is_convertible_to(cvoid, cvoid))]; } +  { int arr[T(__is_convertible_to(int, FromInt))]; } +  { int arr[T(__is_convertible_to(long, FromInt))]; } +  { int arr[T(__is_convertible_to(double, FromInt))]; } +  { int arr[T(__is_convertible_to(const int, FromInt))]; } +  { int arr[T(__is_convertible_to(const int&, FromInt))]; } +  { int arr[T(__is_convertible_to(ToInt, int))]; } +  { int arr[T(__is_convertible_to(ToInt, const int&))]; } +  { int arr[T(__is_convertible_to(ToInt, long))]; } +  { int arr[F(__is_convertible_to(ToInt, int&))]; } +  { int arr[F(__is_convertible_to(ToInt, FromInt))]; } +  { int arr[T(__is_convertible_to(IntAr&, IntAr&))]; } +  { int arr[T(__is_convertible_to(IntAr&, const IntAr&))]; } +  { int arr[F(__is_convertible_to(const IntAr&, IntAr&))]; } +  { int arr[F(__is_convertible_to(Function, Function))]; } +  { int arr[F(__is_convertible_to(PrivateCopy, PrivateCopy))]; } +  { int arr[T(__is_convertible_to(X0<int>, X0<float>))]; } +} + +namespace is_convertible_to_instantiate { +  // Make sure we don't try to instantiate the constructor. +  template<int x> class A { A(int) { int a[x]; } }; +  int x = __is_convertible_to(int, A<-1>); +} + +void is_trivial() +{ +  { int arr[T(__is_trivial(int))]; } +  { int arr[T(__is_trivial(Enum))]; } +  { int arr[T(__is_trivial(POD))]; } +  { int arr[T(__is_trivial(Int))]; } +  { int arr[T(__is_trivial(IntAr))]; } +  { int arr[T(__is_trivial(IntArNB))]; } +  { int arr[T(__is_trivial(Statics))]; } +  { int arr[T(__is_trivial(Empty))]; } +  { int arr[T(__is_trivial(EmptyUnion))]; } +  { int arr[T(__is_trivial(Union))]; } +  { int arr[T(__is_trivial(Derives))]; } +  { int arr[T(__is_trivial(DerivesAr))]; } +  { int arr[T(__is_trivial(DerivesArNB))]; } +  { int arr[T(__is_trivial(DerivesEmpty))]; } +  { int arr[T(__is_trivial(HasFunc))]; } +  { int arr[T(__is_trivial(HasOp))]; } +  { int arr[T(__is_trivial(HasConv))]; } +  { int arr[T(__is_trivial(HasAssign))]; } +  { int arr[T(__is_trivial(HasAnonymousUnion))]; } +  { int arr[T(__is_trivial(HasPriv))]; } +  { int arr[T(__is_trivial(HasProt))]; } +  { int arr[T(__is_trivial(DerivesHasPriv))]; } +  { int arr[T(__is_trivial(DerivesHasProt))]; } +  { int arr[T(__is_trivial(Vector))]; } +  { int arr[T(__is_trivial(VectorExt))]; } + +  { int arr[F(__is_trivial(HasCons))]; } +  { int arr[F(__is_trivial(HasCopyAssign))]; } +  { int arr[F(__is_trivial(HasMoveAssign))]; } +  { int arr[F(__is_trivial(HasDest))]; } +  { int arr[F(__is_trivial(HasRef))]; } +  { int arr[F(__is_trivial(HasNonPOD))]; } +  { int arr[F(__is_trivial(HasVirt))]; } +  { int arr[F(__is_trivial(DerivesHasCons))]; } +  { int arr[F(__is_trivial(DerivesHasCopyAssign))]; } +  { int arr[F(__is_trivial(DerivesHasMoveAssign))]; } +  { int arr[F(__is_trivial(DerivesHasDest))]; } +  { int arr[F(__is_trivial(DerivesHasRef))]; } +  { int arr[F(__is_trivial(DerivesHasVirt))]; } +  { int arr[F(__is_trivial(void))]; } +  { int arr[F(__is_trivial(cvoid))]; } +} + +void trivial_checks() +{ +  { int arr[T(__is_trivially_copyable(int))]; } +  { int arr[T(__is_trivially_copyable(Enum))]; } +  { int arr[T(__is_trivially_copyable(POD))]; } +  { int arr[T(__is_trivially_copyable(Int))]; } +  { int arr[T(__is_trivially_copyable(IntAr))]; } +  { int arr[T(__is_trivially_copyable(IntArNB))]; } +  { int arr[T(__is_trivially_copyable(Statics))]; } +  { int arr[T(__is_trivially_copyable(Empty))]; } +  { int arr[T(__is_trivially_copyable(EmptyUnion))]; } +  { int arr[T(__is_trivially_copyable(Union))]; } +  { int arr[T(__is_trivially_copyable(Derives))]; } +  { int arr[T(__is_trivially_copyable(DerivesAr))]; } +  { int arr[T(__is_trivially_copyable(DerivesArNB))]; } +  { int arr[T(__is_trivially_copyable(DerivesEmpty))]; } +  { int arr[T(__is_trivially_copyable(HasFunc))]; } +  { int arr[T(__is_trivially_copyable(HasOp))]; } +  { int arr[T(__is_trivially_copyable(HasConv))]; } +  { int arr[T(__is_trivially_copyable(HasAssign))]; } +  { int arr[T(__is_trivially_copyable(HasAnonymousUnion))]; } +  { int arr[T(__is_trivially_copyable(HasPriv))]; } +  { int arr[T(__is_trivially_copyable(HasProt))]; } +  { int arr[T(__is_trivially_copyable(DerivesHasPriv))]; } +  { int arr[T(__is_trivially_copyable(DerivesHasProt))]; } +  { int arr[T(__is_trivially_copyable(Vector))]; } +  { int arr[T(__is_trivially_copyable(VectorExt))]; } +  { int arr[T(__is_trivially_copyable(HasCons))]; } +  { int arr[T(__is_trivially_copyable(HasRef))]; } +  { int arr[T(__is_trivially_copyable(HasNonPOD))]; } +  { int arr[T(__is_trivially_copyable(DerivesHasCons))]; } +  { int arr[T(__is_trivially_copyable(DerivesHasRef))]; } + +  { int arr[F(__is_trivially_copyable(HasCopyAssign))]; } +  { int arr[F(__is_trivially_copyable(HasMoveAssign))]; } +  { int arr[F(__is_trivially_copyable(HasDest))]; } +  { int arr[F(__is_trivially_copyable(HasVirt))]; } +  { int arr[F(__is_trivially_copyable(DerivesHasCopyAssign))]; } +  { int arr[F(__is_trivially_copyable(DerivesHasMoveAssign))]; } +  { int arr[F(__is_trivially_copyable(DerivesHasDest))]; } +  { int arr[F(__is_trivially_copyable(DerivesHasVirt))]; } +  { int arr[F(__is_trivially_copyable(void))]; } +  { int arr[F(__is_trivially_copyable(cvoid))]; } + +  { int arr[T((__is_trivially_constructible(int)))]; } +  { int arr[T((__is_trivially_constructible(int, int)))]; } +  { int arr[T((__is_trivially_constructible(int, float)))]; } +  { int arr[T((__is_trivially_constructible(int, int&)))]; } +  { int arr[T((__is_trivially_constructible(int, const int&)))]; } +  { int arr[T((__is_trivially_constructible(int, int)))]; } +  { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; } +  { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; } +  { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; } +  { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; } +  { int arr[T((__is_trivially_constructible(NonTrivialDefault, +                                            const NonTrivialDefault&)))]; } +  { int arr[T((__is_trivially_constructible(NonTrivialDefault, +                                            NonTrivialDefault&&)))]; } +  { int arr[T((__is_trivially_constructible(AllDefaulted)))]; } +  { int arr[T((__is_trivially_constructible(AllDefaulted, +                                            const AllDefaulted &)))]; } +  { int arr[T((__is_trivially_constructible(AllDefaulted, +                                            AllDefaulted &&)))]; } + +  { int arr[F((__is_trivially_constructible(int, int*)))]; } +  { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; } +  { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; } +  { int arr[F((__is_trivially_constructible(AllDeleted)))]; } +  { int arr[F((__is_trivially_constructible(AllDeleted, +                                            const AllDeleted &)))]; } +  { int arr[F((__is_trivially_constructible(AllDeleted, +                                            AllDeleted &&)))]; } +  { int arr[F((__is_trivially_constructible(ExtDefaulted)))]; } +  { int arr[F((__is_trivially_constructible(ExtDefaulted, +                                            const ExtDefaulted &)))]; } +  { int arr[F((__is_trivially_constructible(ExtDefaulted, +                                            ExtDefaulted &&)))]; } + +  { int arr[T((__is_trivially_assignable(int&, int)))]; } +  { int arr[T((__is_trivially_assignable(int&, int&)))]; } +  { int arr[T((__is_trivially_assignable(int&, int&&)))]; } +  { int arr[T((__is_trivially_assignable(int&, const int&)))]; } +  { int arr[T((__is_trivially_assignable(POD&, POD)))]; } +  { int arr[T((__is_trivially_assignable(POD&, POD&)))]; } +  { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; } +  { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; } +  { int arr[T((__is_trivially_assignable(int*&, int*)))]; } +  { int arr[T((__is_trivially_assignable(AllDefaulted, +                                         const AllDefaulted &)))]; } +  { int arr[T((__is_trivially_assignable(AllDefaulted, +                                         AllDefaulted &&)))]; } + +  { int arr[F((__is_trivially_assignable(int*&, float*)))]; } +  { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)))]; } +  { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&)))]; } +  { int arr[F((__is_trivially_assignable(HasCopyAssign&, const HasCopyAssign&)))]; } +  { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&&)))]; } +  { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, +                                        TrivialMoveButNotCopy&)))]; } +  { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, +                                        const TrivialMoveButNotCopy&)))]; } +  { int arr[F((__is_trivially_assignable(AllDeleted, +                                         const AllDeleted &)))]; } +  { int arr[F((__is_trivially_assignable(AllDeleted, +                                         AllDeleted &&)))]; } +  { int arr[F((__is_trivially_assignable(ExtDefaulted, +                                         const ExtDefaulted &)))]; } +  { int arr[F((__is_trivially_assignable(ExtDefaulted, +                                         ExtDefaulted &&)))]; } + +  { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&, +                                         HasDefaultTrivialCopyAssign&)))]; } +  { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&, +                                       const HasDefaultTrivialCopyAssign&)))]; } +  { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&, +                                         TrivialMoveButNotCopy)))]; } +  { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&, +                                         TrivialMoveButNotCopy&&)))]; } +} + +// Instantiation of __is_trivially_constructible +template<typename T, typename ...Args> +struct is_trivially_constructible { +  static const bool value = __is_trivially_constructible(T, Args...); +}; + +void is_trivially_constructible_test() { +  { int arr[T((is_trivially_constructible<int>::value))]; } +  { int arr[T((is_trivially_constructible<int, int>::value))]; } +  { int arr[T((is_trivially_constructible<int, float>::value))]; } +  { int arr[T((is_trivially_constructible<int, int&>::value))]; } +  { int arr[T((is_trivially_constructible<int, const int&>::value))]; } +  { int arr[T((is_trivially_constructible<int, int>::value))]; } +  { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign>::value))]; } +  { int arr[T((is_trivially_constructible<HasCopyAssign, const HasCopyAssign&>::value))]; } +  { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign&&>::value))]; } +  { int arr[T((is_trivially_constructible<HasCopyAssign>::value))]; } +  { int arr[T((is_trivially_constructible<NonTrivialDefault, +                                            const NonTrivialDefault&>::value))]; } +  { int arr[T((is_trivially_constructible<NonTrivialDefault, +                                            NonTrivialDefault&&>::value))]; } + +  { int arr[F((is_trivially_constructible<int, int*>::value))]; } +  { int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; } +  { int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, int&>::value))]; } +} + +void array_rank() { +  int t01[T(__array_rank(IntAr) == 1)]; +  int t02[T(__array_rank(ConstIntArAr) == 2)]; +} + +void array_extent() { +  int t01[T(__array_extent(IntAr, 0) == 10)]; +  int t02[T(__array_extent(ConstIntArAr, 0) == 4)]; +  int t03[T(__array_extent(ConstIntArAr, 1) == 10)]; +} diff --git a/clang/test/SemaCXX/typedef-redecl.cpp b/clang/test/SemaCXX/typedef-redecl.cpp new file mode 100644 index 0000000..b53bcd2 --- /dev/null +++ b/clang/test/SemaCXX/typedef-redecl.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +typedef int INT; +typedef INT REALLY_INT; // expected-note {{previous definition is here}} +typedef REALLY_INT REALLY_REALLY_INT; +typedef REALLY_INT BOB; +typedef float REALLY_INT; // expected-error{{typedef redefinition with different types ('float' vs 'INT' (aka 'int'))}} + +struct X { +  typedef int result_type; // expected-note {{previous definition is here}} +  typedef INT result_type; // expected-error {{redefinition of 'result_type'}} +}; + +struct Y; // expected-note{{previous definition is here}} +typedef int Y;  // expected-error{{typedef redefinition with different types ('int' vs 'Y')}} + +typedef int Y2; // expected-note{{declared here}} +struct Y2; // expected-error{{definition of type 'Y2' conflicts with typedef of the same name}} + +void f(); // expected-note{{previous definition is here}} +typedef int f; // expected-error{{redefinition of 'f' as different kind of symbol}} + +typedef int f2; // expected-note{{previous definition is here}} +void f2(); // expected-error{{redefinition of 'f2' as different kind of symbol}} + +typedef struct s s;  +typedef int I;  +typedef int I;  +typedef I I;  + +struct s { }; + +// PR5874 +namespace test1 { +  typedef int foo; +  namespace a { using test1::foo; }; +  typedef int foo; +  using namespace a;  +  foo x; +} + +namespace PR6923 { +  struct A; + +  extern "C" { +    struct A; +    typedef struct A A; +  } + +  struct A; +} + +namespace PR7462 { +  struct A {}; +  typedef int operator! (A); // expected-error{{typedef name must be an identifier}} +  int i = !A(); // expected-error{{invalid argument type}} +} + +template<typename T> +typedef T f(T t) { return t; } // expected-error {{function definition declared 'typedef'}} +int k = f(0); +int k2 = k; + +namespace PR11630 { +  template <class T> +  struct S +  { +    static const unsigned C = 1; +    static void f() +    { +      typedef int q[C == 1 ? 1 : -1]; // expected-note{{previous definition is here}} +      typedef int q[C >= 1 ? 2 : -2]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}} +      typedef int n[C == 1 ? 1 : -1]; +      typedef int n[C >= 1 ? 1 : -1]; +    } +  }; + +  template <int T> +  struct S2 +  { +    static void f() +    { +      typedef int q[1];  // expected-note{{previous definition is here}} +      typedef int q[T];  // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}} +    } +  }; + +  void f() { +    S<int> a; +    a.f(); // expected-note{{in instantiation of member function 'PR11630::S<int>::f' requested here}} +    S2<1> b; +    b.f(); +    S2<2> b2; +    b2.f(); // expected-note{{in instantiation of member function 'PR11630::S2<2>::f' requested here}} +  } +} diff --git a/clang/test/SemaCXX/typeid-ref.cpp b/clang/test/SemaCXX/typeid-ref.cpp new file mode 100644 index 0000000..d01fd31 --- /dev/null +++ b/clang/test/SemaCXX/typeid-ref.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +namespace std { +  class type_info; +} + +struct X { }; + +void f() { +  // CHECK: @_ZTS1X = linkonce_odr constant +  // CHECK: @_ZTI1X = linkonce_odr unnamed_addr constant  +  (void)typeid(X&); +} diff --git a/clang/test/SemaCXX/typeid.cpp b/clang/test/SemaCXX/typeid.cpp new file mode 100644 index 0000000..d3a2a28 --- /dev/null +++ b/clang/test/SemaCXX/typeid.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() +{ +  (void)typeid(int); // expected-error {{you need to include <typeinfo> before using the 'typeid' operator}} +} + +namespace std { +  class type_info; +} + +void g() +{ +  (void)typeid(int); +} + +struct X; // expected-note 3{{forward declaration}} + +void g1(X &x) { +  (void)typeid(X); // expected-error{{'typeid' of incomplete type 'X'}} +  (void)typeid(X&); // expected-error{{'typeid' of incomplete type 'X'}} +  (void)typeid(x); // expected-error{{'typeid' of incomplete type 'X'}} +} diff --git a/clang/test/SemaCXX/types_compatible_p.cpp b/clang/test/SemaCXX/types_compatible_p.cpp new file mode 100644 index 0000000..4aa9a1c --- /dev/null +++ b/clang/test/SemaCXX/types_compatible_p.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +bool f() { +  return __builtin_types_compatible_p(int, const int); // expected-error{{C++}} +} diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp new file mode 100644 index 0000000..b1e8d91 --- /dev/null +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -0,0 +1,192 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s + +struct errc { +  int v_; +  operator int() const {return v_;} +}; + +class error_condition +{ +  int _val_; +public: +  error_condition() : _val_(0) {} + +  error_condition(int _val) +    : _val_(_val) {} + +  template <class E> +  error_condition(E _e) { +    // make_error_condition must not be typo corrected to error_condition +    // even though the first declaration of make_error_condition has not +    // yet been encountered. This was a bug in the first version of the type +    // name typo correction patch that wasn't noticed until building LLVM with +    // Clang failed. +    *this = make_error_condition(_e); +  } + +}; + +inline error_condition make_error_condition(errc _e) { +  return error_condition(static_cast<int>(_e)); +} + + +// Prior to the introduction of a callback object to further filter possible +// typo corrections, this example would not trigger a suggestion as "base_type" +// is a closer match to "basetype" than is "BaseType" but "base_type" does not +// refer to a base class or non-static data member. +struct BaseType { }; +struct Derived : public BaseType { // expected-note {{base class 'BaseType' specified here}} +  static int base_type; // expected-note {{'base_type' declared here}} +  Derived() : basetype() {} // expected-error{{initializer 'basetype' does not name a non-static data member or base class; did you mean the base class 'BaseType'?}} +}; + +// Test the improvement from passing a callback object to CorrectTypo in +// the helper function LookupMemberExprInRecord. +int get_type(struct Derived *st) { +  return st->Base_Type; // expected-error{{no member named 'Base_Type' in 'Derived'; did you mean 'base_type'?}} +} + +// In this example, somename should not be corrected to the cached correction +// "some_name" since "some_name" is a class and a namespace name is needed. +class some_name {}; // expected-note {{'some_name' declared here}} +somename Foo; // expected-error {{unknown type name 'somename'; did you mean 'some_name'?}} +namespace SomeName {} // expected-note {{namespace 'SomeName' defined here}} +using namespace somename; // expected-error {{no namespace named 'somename'; did you mean 'SomeName'?}} + + +// Without the callback object, CorrectTypo would choose "field1" as the +// correction for "fielda" as it is closer than "FieldA", but that correction +// would be later discarded by the caller and no suggestion would be given. +struct st { +  struct { +    int field1; +  }; +  double FieldA; // expected-note{{'FieldA' declared here}} +}; +st var = { .fielda = 0.0 }; // expected-error{{field designator 'fielda' does not refer to any field in type 'st'; did you mean 'FieldA'?}} + +// Test the improvement from passing a callback object to CorrectTypo in +// Sema::BuildCXXNestedNameSpecifier. And also for the improvement by doing +// so in Sema::getTypeName. +typedef char* another_str; // expected-note{{'another_str' declared here}} +namespace AnotherStd { // expected-note{{'AnotherStd' declared here}} +  class string {}; +} +another_std::string str; // expected-error{{use of undeclared identifier 'another_std'; did you mean 'AnotherStd'?}} +another_str *cstr = new AnotherStr; // expected-error{{unknown type name 'AnotherStr'; did you mean 'another_str'?}} + +// Test the improvement from passing a callback object to CorrectTypo in +// Sema::ActOnSizeofParameterPackExpr. +char* TireNames; +template<typename ...TypeNames> struct count { // expected-note{{parameter pack 'TypeNames' declared here}} +  static const unsigned value = sizeof...(TyreNames); // expected-error{{'TyreNames' does not refer to the name of a parameter pack; did you mean 'TypeNames'?}} +}; + +// Test the typo-correction callback in Sema::DiagnoseUnknownTypeName. +namespace unknown_type_test { +  class StreamOut {}; // expected-note 2 {{'StreamOut' declared here}} +  long stream_count; // expected-note 2 {{'stream_count' declared here}} +}; +unknown_type_test::stream_out out; // expected-error{{no type named 'stream_out' in namespace 'unknown_type_test'; did you mean 'StreamOut'?}} + +// Demonstrate a case where using only the cached value returns the wrong thing +// when the cached value was the result of a previous callback object that only +// accepts a subset of the current callback object. +namespace { +using namespace unknown_type_test; +void bar(long i); +void before_caching_classname() { +  bar((stream_out)); // expected-error{{use of undeclared identifier 'stream_out'; did you mean 'stream_count'?}} +} +stream_out out; // expected-error{{unknown type name 'stream_out'; did you mean 'StreamOut'?}} +void after_caching_classname() { +  bar((stream_out)); // expected-error{{use of undeclared identifier 'stream_out'; did you mean 'stream_count'?}} +} +} + +// Test the typo-correction callback in Sema::DiagnoseInvalidRedeclaration. +struct BaseDecl { +  void add_in(int i); +}; +struct TestRedecl : public BaseDecl { +  void add_it(int i); // expected-note{{'add_it' declared here}} +}; +void TestRedecl::add_in(int i) {} // expected-error{{out-of-line definition of 'add_in' does not match any declaration in 'TestRedecl'; did you mean 'add_it'?}} + +// Test the improved typo correction for the Parser::ParseCastExpr => +// Sema::ActOnIdExpression => Sema::DiagnoseEmptyLookup call path. +class SomeNetMessage; +class Message {}; +void foo(Message&); +void foo(SomeNetMessage&); +void doit(void *data) { +  Message somenetmsg; // expected-note{{'somenetmsg' declared here}} +  foo(somenetmessage); // expected-error{{use of undeclared identifier 'somenetmessage'; did you mean 'somenetmsg'?}} +  foo((somenetmessage)data); // expected-error{{use of undeclared identifier 'somenetmessage'; did you mean 'SomeNetMessage'?}} +} + +// Test the typo-correction callback in BuildRecoveryCallExpr. +// Solves the main issue in PR 9320 of suggesting corrections that take the +// wrong number of arguments. +void revoke(const char*); // expected-note 2{{'revoke' declared here}} +void Test() { +  Invoke(); // expected-error{{use of undeclared identifier 'Invoke'}} +  Invoke("foo"); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'revoke'?}} +  Invoke("foo", "bar"); // expected-error{{use of undeclared identifier 'Invoke'}} +} +void Test2(void (*invoke)(const char *, int)) { // expected-note{{'invoke' declared here}} +  Invoke(); // expected-error{{use of undeclared identifier 'Invoke'}} +  Invoke("foo"); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'revoke'?}} +  Invoke("foo", 7); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'invoke'?}} +  Invoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Invoke'}} +} + +void provoke(const char *x, bool y=false) {} // expected-note 2{{'provoke' declared here}} +void Test3() { +  Provoke(); // expected-error{{use of undeclared identifier 'Provoke'}} +  Provoke("foo"); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}} +  Provoke("foo", true); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}} +  Provoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Provoke'}} +} + +// PR 11737 - Don't try to typo-correct the implicit 'begin' and 'end' in a +// C++11 for-range statement. +struct R {}; +bool begun(R); +void RangeTest() { +  for (auto b : R()) {} // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type}} +} + +// PR 12019 - Avoid infinite mutual recursion in DiagnoseInvalidRedeclaration +// by not trying to typo-correct a method redeclaration to declarations not +// in the current record. +class Parent { + void set_types(int index, int value); + void add_types(int value); +}; +class Child: public Parent {}; +void Child::add_types(int value) {} // expected-error{{out-of-line definition of 'add_types' does not match any declaration in 'Child'}} + +// Fix the callback based filtering of typo corrections within +// Sema::ActOnIdExpression by Parser::ParseCastExpression to allow type names as +// potential corrections for template arguments. +namespace clash { +class ConstructExpr {}; // expected-note{{'clash::ConstructExpr' declared here}} +} +class ClashTool { +  bool HaveConstructExpr(); +  template <class T> T* getExprAs(); + +  void test() { +    ConstructExpr *expr = // expected-error{{unknown type name 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}} +        getExprAs<ConstructExpr>(); // expected-error{{use of undeclared identifier 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}} +  } +}; + +namespace test1 { +  struct S { +    struct Foobar *f;  // expected-note{{'Foobar' declared here}} +  }; +  test1::FooBar *b;  // expected-error{{no type named 'FooBar' in namespace 'test1'; did you mean 'Foobar'?}} +} diff --git a/clang/test/SemaCXX/unary-real-imag.cpp b/clang/test/SemaCXX/unary-real-imag.cpp new file mode 100644 index 0000000..91b63e3 --- /dev/null +++ b/clang/test/SemaCXX/unary-real-imag.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A {}; +int i = __real__ A(); // expected-error {{invalid type 'A' to __real operator}} +int j = __imag__ A(); // expected-error {{invalid type 'A' to __imag operator}} + diff --git a/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp new file mode 100644 index 0000000..1541720 --- /dev/null +++ b/clang/test/SemaCXX/undefined-internal.cpp @@ -0,0 +1,183 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Make sure we don't produce invalid IR. +// RUN: %clang_cc1 -emit-llvm-only %s + +namespace test1 { +  static void foo(); // expected-warning {{function 'test1::foo' has internal linkage but is not defined}} +  template <class T> static void bar(); // expected-warning {{function 'test1::bar<int>' has internal linkage but is not defined}} + +  void test() { +    foo(); // expected-note {{used here}} +    bar<int>(); // expected-note {{used here}} +  } +} + +namespace test2 { +  namespace { +    void foo(); // expected-warning {{function 'test2::<anonymous namespace>::foo' has internal linkage but is not defined}} +    extern int var; // expected-warning {{variable 'test2::<anonymous namespace>::var' has internal linkage but is not defined}} +    template <class T> void bar(); // expected-warning {{function 'test2::<anonymous namespace>::bar<int>' has internal linkage but is not defined}} +  } +  void test() { +    foo(); // expected-note {{used here}} +    var = 0; // expected-note {{used here}} +    bar<int>(); // expected-note {{used here}} +  } +} + +namespace test3 { +  namespace { +    void foo(); +    extern int var; +    template <class T> void bar(); +  } + +  void test() { +    foo(); +    var = 0; +    bar<int>(); +  } + +  namespace { +    void foo() {} +    int var = 0; +    template <class T> void bar() {} +  } +} + +namespace test4 { +  namespace { +    struct A { +      A(); // expected-warning {{function 'test4::<anonymous namespace>::A::A' has internal linkage but is not defined}} +      ~A();// expected-warning {{function 'test4::<anonymous namespace>::A::~A' has internal linkage but is not defined}} +      virtual void foo(); // expected-warning {{function 'test4::<anonymous namespace>::A::foo' has internal linkage but is not defined}} +      virtual void bar() = 0; +      virtual void baz(); // expected-warning {{function 'test4::<anonymous namespace>::A::baz' has internal linkage but is not defined}} +    }; +  } + +  void test(A &a) { +    a.foo(); // expected-note {{used here}} +    a.bar(); +    a.baz(); // expected-note {{used here}} +  } + +  struct Test : A { +    Test() {} // expected-note 2 {{used here}} +  }; +} + +// rdar://problem/9014651 +namespace test5 { +  namespace { +    struct A {}; +  } + +  template <class N> struct B { +    static int var; // expected-warning {{variable 'test5::B<test5::<anonymous>::A>::var' has internal linkage but is not defined}} +    static void foo(); // expected-warning {{function 'test5::B<test5::<anonymous>::A>::foo' has internal linkage but is not defined}} +  }; + +  void test() { +    B<A>::var = 0; // expected-note {{used here}} +    B<A>::foo(); // expected-note {{used here}} +  } +} + +namespace test6 { +  template <class T> struct A { +    static const int zero = 0; +    static const int one = 1; +    static const int two = 2; + +    int value; + +    A() : value(zero) { +      value = one; +    } +  }; + +  namespace { struct Internal; } + +  void test() { +    A<Internal> a; +    a.value = A<Internal>::two; +  } +} + +// We support (as an extension) private, undefined copy constructors when +// a temporary is bound to a reference even in C++98. Similarly, we shouldn't +// warn about this copy constructor being used without a definition. +namespace PR9323 { +  namespace { +    struct Uncopyable { +      Uncopyable() {} +    private: +      Uncopyable(const Uncopyable&); // expected-note {{declared private here}} +    }; +  } +  void f(const Uncopyable&) {} +  void test() { +    f(Uncopyable()); // expected-warning {{C++98 requires an accessible copy constructor}} +  }; +} + + +namespace std { class type_info; }; +namespace cxx11_odr_rules { +  // Note: the way this test is written isn't really ideal, but there really +  // isn't any other way to check that the odr-used logic for constants +  // is working without working implicit capture in lambda-expressions. +  // (The more accurate used-but-not-defined warning is the only other visible +  // effect of accurate odr-used computation.) +  // +  // Note that the warning in question can trigger in cases some people would +  // consider false positives; hopefully that happens rarely in practice. +  // +  // FIXME: Suppressing this test while I figure out how to fix a bug in the +  // odr-use marking code. + +  namespace { +    struct A { +      static const int unused = 10; +      static const int used1 = 20; // xpected-warning {{internal linkage}} +      static const int used2 = 20; // xpected-warning {{internal linkage}} +      virtual ~A() {} +    }; +  } + +  void a(int,int); +  A& p(const int&) { static A a; return a; } + +  // Check handling of default arguments +  void b(int = A::unused); + +  void tests() { +    // Basic test +    a(A::unused, A::unused); + +    // Check that nesting an unevaluated or constant-evaluated context does +    // the right thing. +    a(A::unused, sizeof(int[10])); + +    // Check that the checks work with unevaluated contexts +    (void)sizeof(p(A::used1)); +    (void)typeid(p(A::used1)); // xpected-note {{used here}} + +    // Misc other testing +    a(A::unused, 1 ? A::used2 : A::used2); // xpected-note {{used here}} +    b(); +  } +} + + +namespace OverloadUse { +  namespace { +    void f(); +    void f(int); // expected-warning {{function 'OverloadUse::<anonymous namespace>::f' has internal linkage but is not defined}} +  } +  template<void x()> void t(int*) { x(); } +  template<void x(int)> void t(long*) { x(10); } // expected-note {{used here}} +  void g() { long a; t<f>(&a); } +} diff --git a/clang/test/SemaCXX/underlying_type.cpp b/clang/test/SemaCXX/underlying_type.cpp new file mode 100644 index 0000000..7bca06b --- /dev/null +++ b/clang/test/SemaCXX/underlying_type.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -std=c++11 %s + +#include "limits.h" + +template<typename T, typename U> +struct is_same_type { +  static const bool value = false; +}; +template <typename T> +struct is_same_type<T, T> { +  static const bool value = true; +}; + +__underlying_type(int) a; // expected-error {{only enumeration types}} +__underlying_type(struct b) c; // expected-error {{only enumeration types}} + +enum class f : char; +static_assert(is_same_type<char, __underlying_type(f)>::value, +              "f has the wrong underlying type"); + +enum g {d = INT_MIN }; +static_assert(is_same_type<int, __underlying_type(g)>::value, +              "g has the wrong underlying type"); + +__underlying_type(f) h; +static_assert(is_same_type<char, decltype(h)>::value, +              "h has the wrong type"); + +template <typename T> +struct underlying_type { +  typedef __underlying_type(T) type; // expected-error {{only enumeration types}} +}; + +static_assert(is_same_type<underlying_type<f>::type, char>::value, +              "f has the wrong underlying type in the template"); + +underlying_type<int>::type e; // expected-note {{requested here}} + +using uint = unsigned; +enum class foo : uint { bar }; +  +static_assert(is_same_type<underlying_type<foo>::type, unsigned>::value, +              "foo has the wrong underlying type"); diff --git a/clang/test/SemaCXX/uninit-variables-conditional.cpp b/clang/test/SemaCXX/uninit-variables-conditional.cpp new file mode 100644 index 0000000..3c44c72 --- /dev/null +++ b/clang/test/SemaCXX/uninit-variables-conditional.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -Wconditional-uninitialized -fsyntax-only %s -verify + +class Foo { +public: +  Foo(); +  ~Foo(); +  operator bool(); +}; + +int bar(); +int baz(); +int init(double *); + +// This case flags a false positive under -Wconditional-uninitialized because +// the destructor in Foo fouls about the minor bit of path-sensitivity in +// -Wuninitialized. +double test() { +  double x; // expected-note{{initialize the variable 'x' to silence this warning}} +  if (bar() || baz() || Foo() || init(&x)) +    return 1.0; + +  return x; // expected-warning {{variable 'x' may be uninitialized when used here}} +} diff --git a/clang/test/SemaCXX/uninit-variables.cpp b/clang/test/SemaCXX/uninit-variables.cpp new file mode 100644 index 0000000..eb6428d --- /dev/null +++ b/clang/test/SemaCXX/uninit-variables.cpp @@ -0,0 +1,143 @@ +// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fcxx-exceptions %s -verify + +// Stub out types for 'typeid' to work. +namespace std { class type_info {}; } + +int test1_aux(int &x); +int test1() { +  int x; +  test1_aux(x); +  return x; // no-warning +} + +int test2_aux() { +  int x; +  int &y = x; +  return x; // no-warning +} + +// Don't warn on unevaluated contexts. +void unevaluated_tests() { +  int x; +  (void)sizeof(x); +  (void)typeid(x); +} + +// Warn for glvalue arguments to typeid whose type is polymorphic. +struct A { virtual ~A() {} }; +void polymorphic_test() { +  A *a; // expected-note{{initialize the variable 'a' to silence this warning}} +  (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here}} +} + +// Handle cases where the CFG may constant fold some branches, thus +// mitigating the need for some path-sensitivity in the analysis. +unsigned test3_aux(); +unsigned test3() { +  unsigned x = 0; +  const bool flag = true; +  if (flag && (x = test3_aux()) == 0) { +    return x; +  } +  return x; +} +unsigned test3_b() { +  unsigned x ; +  const bool flag = true; +  if (flag && (x = test3_aux()) == 0) { +    x = 1; +  } +  return x; // no-warning +} +unsigned test3_c() { +  unsigned x; // expected-note{{initialize the variable 'x' to silence this warning}} +  const bool flag = false; +  if (flag && (x = test3_aux()) == 0) { +    x = 1; +  } +  return x; // expected-warning{{variable 'x' is uninitialized when used here}} +} + +enum test4_A { + test4_A_a, test_4_A_b +}; +test4_A test4() { + test4_A a; // expected-note{{variable 'a' is declared here}} + return a; // expected-warning{{variable 'a' is uninitialized when used here}} +} + +// Test variables getting invalidated by function calls with reference arguments +// *AND* there are multiple invalidated arguments. +void test5_aux(int &, int &); + +int test5() { +  int x, y; +  test5_aux(x, y); +  return x + y; // no-warning +} + +// This test previously crashed Sema. +class Rdar9188004A { +public:  +  virtual ~Rdar9188004A(); +}; + +template< typename T > class Rdar9188004B : public Rdar9188004A { +virtual double *foo(Rdar9188004B *next) const  { +    double *values = next->foo(0); +    try { +    } +    catch(double e) { +      values[0] = e; +    } +    return 0; +  } +}; +class Rdar9188004C : public Rdar9188004B<Rdar9188004A> { +  virtual void bar(void) const; +}; +void Rdar9188004C::bar(void) const {} + +// Don't warn about uninitialized variables in unreachable code. +void PR9625() { +  if (false) { +    int x; +    (void)static_cast<float>(x); // no-warning +  } +} + +// Don't warn about variables declared in "catch" +void RDar9251392_bar(const char *msg); + +void RDar9251392() { +  try { +    throw "hi"; +  } +  catch (const char* msg) { +    RDar9251392_bar(msg); // no-warning +  } +} + +// Test handling of "no-op" casts. +void test_noop_cast() +{ +    int x = 1; +    int y = (int&)x; // no-warning +} + +void test_noop_cast2() { +    int x; // expected-note {{initialize the variable 'x' to silence this warning}} +    int y = (int&)x; // expected-warning {{uninitialized when used here}} +} + +// Test handling of bit casts. +void test_bitcasts() { +  int x = 1; +  int y = (float &)x; // no-warning +} + +void test_bitcasts_2() { +  int x;  // expected-note {{initialize the variable 'x' to silence this warning}} +  int y = (float &)x; // expected-warning {{uninitialized when used here}} +} + diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp new file mode 100644 index 0000000..7879e7c --- /dev/null +++ b/clang/test/SemaCXX/uninitialized.cpp @@ -0,0 +1,169 @@ +// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -std=c++11 -verify %s + +int foo(int x); +int bar(int* x); +int boo(int& x); +int far(const int& x); + +// Test self-references within initializers which are guaranteed to be +// uninitialized. +int a = a; // no-warning: used to signal intended lack of initialization. +int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}} +int c = (c + c); // expected-warning 2 {{variable 'c' is uninitialized when used within its own initialization}} +void test() { +  int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}} +} +int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}} +int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}} + +// Thes don't warn as they don't require the value. +int g = sizeof(g); +void* ptr = &ptr; +int h = bar(&h); +int i = boo(i); +int j = far(j); +int k = __alignof__(k); + + +// Test self-references with record types. +class A { +  // Non-POD class. +  public: +    enum count { ONE, TWO, THREE }; +    int num; +    static int count; +    int get() const { return num; } +    int get2() { return num; } +    void set(int x) { num = x; } +    static int zero() { return 0; } + +    A() {} +    A(A const &a) {} +    A(int x) {} +    A(int *x) {} +    A(A *a) {} +    ~A(); +}; + +A getA() { return A(); } +A getA(int x) { return A(); } +A getA(A* a) { return A(); } + +void setupA() { +  A a1; +  a1.set(a1.get()); +  A a2(a1.get()); +  A a3(a1); +  A a4(&a4); +  A a5(a5.zero()); +  A a6(a6.ONE); +  A a7 = getA(); +  A a8 = getA(a8.TWO); +  A a9 = getA(&a9); +  A a10(a10.count); + +  A a11(a11);  // expected-warning {{variable 'a11' is uninitialized when used within its own initialization}} +  A a12(a12.get());  // expected-warning {{variable 'a12' is uninitialized when used within its own initialization}} +  A a13(a13.num);  // expected-warning {{variable 'a13' is uninitialized when used within its own initialization}} +  A a14 = A(a14);  // expected-warning {{variable 'a14' is uninitialized when used within its own initialization}} +  A a15 = getA(a15.num);  // expected-warning {{variable 'a15' is uninitialized when used within its own initialization}} +  A a16(&a16.num);  // expected-warning {{variable 'a16' is uninitialized when used within its own initialization}} +  A a17(a17.get2());  // expected-warning {{variable 'a17' is uninitialized when used within its own initialization}} +} + +struct B { +  // POD struct. +  int x; +  int *y; +}; + +B getB() { return B(); }; +B getB(int x) { return B(); }; +B getB(int *x) { return B(); }; +B getB(B *b) { return B(); }; + +void setupB() { +  B b1; +  B b2(b1); +  B b3 = { 5, &b3.x }; +  B b4 = getB(); +  B b5 = getB(&b5); +  B b6 = getB(&b6.x); + +  // Silence unused warning +  (void) b2; +  (void) b4; + +  B b7(b7);  // expected-warning {{variable 'b7' is uninitialized when used within its own initialization}} +  B b8 = getB(b8.x);  // expected-warning {{variable 'b8' is uninitialized when used within its own initialization}} +  B b9 = getB(b9.y);  // expected-warning {{variable 'b9' is uninitialized when used within its own initialization}} +} + +// Also test similar constructs in a field's initializer. +struct S { +  int x; +  void *ptr; + +  S(bool (*)[1]) : x(x) {} // expected-warning {{field is uninitialized when used here}} +  S(bool (*)[2]) : x(x + 1) {} // expected-warning {{field is uninitialized when used here}} +  S(bool (*)[3]) : x(x + x) {} // expected-warning {{field is uninitialized when used here}} +  S(bool (*)[4]) : x(static_cast<long>(x) + 1) {} // expected-warning {{field is uninitialized when used here}} +  S(bool (*)[5]) : x(foo(x)) {} // FIXME: This should warn! + +  // These don't actually require the value of x and so shouldn't warn. +  S(char (*)[1]) : x(sizeof(x)) {} // rdar://8610363 +  S(char (*)[2]) : ptr(&ptr) {} +  S(char (*)[3]) : x(__alignof__(x)) {} +  S(char (*)[4]) : x(bar(&x)) {} +  S(char (*)[5]) : x(boo(x)) {} +  S(char (*)[6]) : x(far(x)) {} +}; + +struct C { char a[100], *e; } car = { .e = car.a }; + +// <rdar://problem/10398199> +namespace rdar10398199 { +  class FooBase { protected: ~FooBase() {} }; +  class Foo : public FooBase { +  public: +    operator int&() const; +  }; +  void stuff(); +  template <typename T> class FooImpl : public Foo { +    T val; +  public: +    FooImpl(const T &x) : val(x) {} +    ~FooImpl() { stuff(); } +  }; + +  template <typename T> FooImpl<T> makeFoo(const T& x) { +    return FooImpl<T>(x); +  } + +  void test() { +    const Foo &x = makeFoo(42); +    const int&y = makeFoo(42u); +    (void)x; +    (void)y; +  }; +} + +// PR 12325 - this was a false uninitialized value warning due to +// a broken CFG. +int pr12325(int params) { +  int x = ({ +    while (false) +      ; +    int _v = params; +    if (false) +      ; +    _v; // no-warning +  }); +  return x; +} + +// Test lambda expressions with -Wuninitialized +int test_lambda() { +  auto f1 = [] (int x, int y) { int z; return x + y + z; }; // expected-warning {{C++11 requires lambda with omitted result type to consist of a single return statement}} expected-warning{{variable 'z' is uninitialized when used here}} expected-note {{initialize the variable 'z' to silence this warning}} +  return f1(1, 2); +} diff --git a/clang/test/SemaCXX/unknown-anytype-blocks.cpp b/clang/test/SemaCXX/unknown-anytype-blocks.cpp new file mode 100644 index 0000000..86ce7e1 --- /dev/null +++ b/clang/test/SemaCXX/unknown-anytype-blocks.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -funknown-anytype -fblocks -fsyntax-only -verify -std=c++11 %s + +namespace test1 { +  __unknown_anytype (^foo)(); +  __unknown_anytype (^bar)(); +  int test() { +    auto ret1 = (int)foo(); +    auto ret2 = bar(); // expected-error {{'bar' has unknown return type; cast the call to its declared return type}} +    return ret1; +  } +} diff --git a/clang/test/SemaCXX/unknown-anytype.cpp b/clang/test/SemaCXX/unknown-anytype.cpp new file mode 100644 index 0000000..a07ec83 --- /dev/null +++ b/clang/test/SemaCXX/unknown-anytype.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -funknown-anytype -fsyntax-only -verify %s + +namespace test0 { +  extern __unknown_anytype test0; +  extern __unknown_anytype test1(); +  extern __unknown_anytype test2(int); +} + +namespace test1 { +  extern __unknown_anytype foo; +  int test() { +    // TODO: it would be great if the 'cannot initialize' errors +    // turned into something more interesting.  It's just a matter of +    // making sure that these locations check for placeholder types +    // properly. + +    int x = foo; // expected-error {{'foo' has unknown type}} +    int y = 0 + foo; // expected-error {{'foo' has unknown type}} +    return foo; // expected-error {{'foo' has unknown type}} +  } +} + +namespace test2 { +  extern __unknown_anytype foo(); +  void test() { +    foo(); // expected-error {{'foo' has unknown return type}} +  } +} + +namespace test3 { +  extern __unknown_anytype foo; +  void test() { +    foo(); // expected-error {{call to unsupported expression with unknown type}} +    ((void(void)) foo)(); // expected-error {{variable 'foo' with unknown type cannot be given a function type}} +  } +} + +// rdar://problem/9899447 +namespace test4 { +  extern __unknown_anytype test0(...); +  extern __unknown_anytype test1(...); + +  void test() { +    void (*fn)(int) = (void(*)(int)) test0; +    int x = (int) test1; // expected-error {{function 'test1' with unknown type must be given a function type}} +  } +} diff --git a/clang/test/SemaCXX/unknown-type-name.cpp b/clang/test/SemaCXX/unknown-type-name.cpp new file mode 100644 index 0000000..5f8d8ca --- /dev/null +++ b/clang/test/SemaCXX/unknown-type-name.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR3990 +namespace N { +  struct Wibble { +  }; + +  typedef Wibble foo; +} +using namespace N; + +foo::bar x; // expected-error{{no type named 'bar' in 'N::Wibble'}} + +void f() { +  foo::bar  = 4; // expected-error{{no member named 'bar' in 'N::Wibble'}} +} + +template<typename T> +struct A { +  typedef T type; +   +  type f(); +}; + +template<typename T> +A<T>::type g(T t) { return t; } // expected-error{{missing 'typename'}} + +template<typename T> +A<T>::type A<T>::f() { return type(); } // expected-error{{missing 'typename'}} diff --git a/clang/test/SemaCXX/unreachable-catch-clauses.cpp b/clang/test/SemaCXX/unreachable-catch-clauses.cpp new file mode 100644 index 0000000..c75067f --- /dev/null +++ b/clang/test/SemaCXX/unreachable-catch-clauses.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s + +class BaseEx {}; +class Ex1: public BaseEx {}; +typedef Ex1 Ex2; + +void f(); + +void test() +try {} +catch (BaseEx &e) { f(); } +catch (Ex1 &e) { f(); } // expected-note {{for type class Ex1 &}} +catch (Ex2 &e) { f(); } // expected-warning {{exception of type Ex2 & will be caught by earlier handler}} + diff --git a/clang/test/SemaCXX/unreachable-code.cpp b/clang/test/SemaCXX/unreachable-code.cpp new file mode 100644 index 0000000..743290e --- /dev/null +++ b/clang/test/SemaCXX/unreachable-code.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -Wunreachable-code -fblocks -verify %s + +int j; +void bar() { } +int test1() { +  for (int i = 0; +       i != 10; +       ++i) {  // expected-warning {{will never be executed}} +    if (j == 23) // missing {}'s +      bar(); +      return 1; +  } +  return 0; +  return 1;    // expected-warning {{will never be executed}} +} + +void test2(int i) { +  switch (i) { +  case 0: +    break; +    bar();     // expected-warning {{will never be executed}} +  case 2: +    switch (i) { +    default: +    a: goto a; +    } +    bar();     // expected-warning {{will never be executed}} +  } +  b: goto b; +  bar();       // expected-warning {{will never be executed}} +} + +void test3() { +  ^{ return; +     bar();    // expected-warning {{will never be executed}} +  }(); +  while (++j) { +    continue; +    bar();     // expected-warning {{will never be executed}} +  } +} + +// PR 6130 - Don't warn about bogus unreachable code with throw's and +// temporary objects. +class PR6130 { +public: +  PR6130(); +  ~PR6130(); +}; + +int pr6130(unsigned i) { +  switch(i) { +    case 0: return 1; +    case 1: return 2; +    default: +      throw PR6130(); // no-warning +  } +} diff --git a/clang/test/SemaCXX/unused-functions.cpp b/clang/test/SemaCXX/unused-functions.cpp new file mode 100644 index 0000000..3598082 --- /dev/null +++ b/clang/test/SemaCXX/unused-functions.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused -verify %s + +static int foo(int x) { return x; } + +template<typename T> +T get_from_foo(T y) { return foo(y); } + +int g(int z) { return get_from_foo(z); } + +namespace { void f() = delete; } diff --git a/clang/test/SemaCXX/unused-with-error.cpp b/clang/test/SemaCXX/unused-with-error.cpp new file mode 100644 index 0000000..5660007 --- /dev/null +++ b/clang/test/SemaCXX/unused-with-error.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused -verify %s + +// Make sure 'unused' warnings are disabled when errors occurred. +static void foo(int *X) { // expected-note {{candidate}} +} +void bar(const int *Y) { +  foo(Y); // expected-error {{no matching function for call}} +} diff --git a/clang/test/SemaCXX/unused.cpp b/clang/test/SemaCXX/unused.cpp new file mode 100644 index 0000000..88783ce --- /dev/null +++ b/clang/test/SemaCXX/unused.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR4103 : Make sure we don't get a bogus unused expression warning +class APInt { +  char foo; +}; +class APSInt : public APInt { +  char bar; +public: +  APSInt &operator=(const APSInt &RHS); +}; + +APSInt& APSInt::operator=(const APSInt &RHS) { +  APInt::operator=(RHS); +  return *this; +} + +template<typename T> +struct X { +  X(); +}; + +void test() { +  X<int>(); +} diff --git a/clang/test/SemaCXX/user-defined-conversions.cpp b/clang/test/SemaCXX/user-defined-conversions.cpp new file mode 100644 index 0000000..43ec5a3 --- /dev/null +++ b/clang/test/SemaCXX/user-defined-conversions.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s  +struct X { +  operator bool(); +}; + +int& f(bool); +float& f(int); + +void f_test(X x) { +  int& i1 = f(x); +} + +struct Y { +  operator short(); +  operator float(); +}; + +void g(int); + +void g_test(Y y) { +  g(y); +  short s; +  s = y; +} + +struct A { }; +struct B : A { }; + +struct C { +  operator B&(); +}; + +// Test reference binding via an lvalue conversion function. +void h(volatile A&); +void h_test(C c) { +  h(c); +} + +// Test conversion followed by copy-construction +struct FunkyDerived; + +struct Base {  +  Base(const FunkyDerived&); +}; + +struct Derived : Base { }; + +struct FunkyDerived : Base { }; + +struct ConvertibleToBase { +  operator Base(); +}; + +struct ConvertibleToDerived { +  operator Derived(); +}; + +struct ConvertibleToFunkyDerived { +  operator FunkyDerived(); +}; + +void test_conversion(ConvertibleToBase ctb, ConvertibleToDerived ctd, +                     ConvertibleToFunkyDerived ctfd) { +  Base b1 = ctb; +  Base b2(ctb); +  Base b3 = ctd; +  Base b4(ctd); +  Base b5 = ctfd; +} + +struct X1 { +  X1(X1&); // expected-note{{candidate constructor not viable: no known conversion from 'X1' to 'X1 &' for 1st argument}} +}; + +struct X2 { +  operator X1(); +}; + +int &f(X1); +float &f(...); + +void g(X2 b) { +  int &ir = f(b); // expected-error{{no viable constructor copying parameter of type 'X1'}} +} + +namespace rdar10202900 { +  class A { +  public: +    A(); + +  private: +    A(int i); // expected-note{{declared private here}} +  }; + +  void testA(A a) { +    int b = 10; +    a = b; // expected-error{{calling a private constructor of class 'rdar10202900::A'}} +  } +} diff --git a/clang/test/SemaCXX/using-decl-1.cpp b/clang/test/SemaCXX/using-decl-1.cpp new file mode 100644 index 0000000..ebe97f6 --- /dev/null +++ b/clang/test/SemaCXX/using-decl-1.cpp @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern "C" { void f(bool); } + +namespace std { +  using ::f; +  inline void f() { return f(true); } +} + +namespace M { +  void f(float); +} + +namespace N { +  using M::f; +  void f(int) { } // expected-note{{previous}} +   +  void f(int) { } // expected-error{{redefinition}} +} + +namespace N { +  void f(double); +  void f(long); +} + +struct X0 { +  void operator()(int); +  void operator()(long); +}; + +struct X1 : X0 { +  // FIXME: give this operator() a 'float' parameter to test overloading +  // behavior. It currently fails. +  void operator()(); +  using X0::operator(); +   +  void test() { +    (*this)(1); +  } +}; + +struct A { void f(); }; +struct B : A { }; +class C : B { using B::f; }; + +// PR5751: Resolve overloaded functions through using decls. +namespace O { +  void f(int i); +  void f(double d); +} +namespace P { +  void f(); +  void g(void (*ptr)(int)); +  using O::f; +  void test() { +    f(); +    f(1); +    void (*f_ptr1)(double) = f; +    void (*f_ptr2)() = f; +    g(f); +  } +} + +// Make sure that ADL can find names brought in by using decls. +namespace test0 { +  namespace ns { +    class Foo {}; +     +    namespace inner { +      void foo(char *); // expected-note {{no known conversion}}  +    } + +    using inner::foo; +  } + +  void test(ns::Foo *p) { +    foo(*p); // expected-error {{no matching function for call to 'foo'}} +  } +} + +// Redeclarations! +namespace test1 { +  namespace ns0 { struct Foo {}; } +  namespace A { void foo(ns0::Foo *p, int y, int z); } +  namespace ns2 { using A::foo; } +  namespace ns1 { struct Bar : ns0::Foo {}; } +  namespace A { void foo(ns0::Foo *p, int y, int z = 0); } // expected-note {{candidate}} +  namespace ns1 { using A::foo; } +  namespace ns2 { struct Baz : ns1::Bar {}; } +  namespace A { void foo(ns0::Foo *p, int y = 0, int z); } + +  void test(ns2::Baz *p) { +    foo(p, 0, 0); // okay! +    foo(p, 0); // should be fine! +    foo(p); // expected-error {{no matching function}} +  } +} + +namespace test2 { +  namespace ns { int foo; } +  template <class T> using ns::foo; // expected-error {{cannot template a using declaration}} + +  // PR8022 +  struct A { +    template <typename T> void f(T); +  }; +  class B : A { +    template <typename T> using A::f<T>; // expected-error {{cannot template a using declaration}} +  }; +} + +// PR8756 +namespace foo +{ +  class Class1; // expected-note{{forward declaration}} +  class Class2 +  { +    using ::foo::Class1::Function; // expected-error{{incomplete type 'foo::Class1' named in nested name specifier}} +  }; +} diff --git a/clang/test/SemaCXX/using-decl-pr4441.cpp b/clang/test/SemaCXX/using-decl-pr4441.cpp new file mode 100644 index 0000000..39a446f --- /dev/null +++ b/clang/test/SemaCXX/using-decl-pr4441.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { +    struct B { }; +    void operator+(B,B); +} + +using A::operator+; diff --git a/clang/test/SemaCXX/using-decl-pr4450.cpp b/clang/test/SemaCXX/using-decl-pr4450.cpp new file mode 100644 index 0000000..4f929ad --- /dev/null +++ b/clang/test/SemaCXX/using-decl-pr4450.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { +  void g(); +} + +namespace X { +  using A::g;  +} + +void h() +{ +  A::g(); +  X::g(); +} diff --git a/clang/test/SemaCXX/using-decl-templates.cpp b/clang/test/SemaCXX/using-decl-templates.cpp new file mode 100644 index 0000000..2f8abca --- /dev/null +++ b/clang/test/SemaCXX/using-decl-templates.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { +  void f() { } +  struct N { }; // expected-note{{target of using declaration}} +}; + +template<typename T> struct B : A<T> { +  using A<T>::f; +  using A<T>::N; // expected-error{{dependent using declaration resolved to type without 'typename'}} +   +  using A<T>::foo; // expected-error{{no member named 'foo'}} +  using A<double>::f; // expected-error{{using declaration refers into 'A<double>::', which is not a base class of 'B<int>'}} +}; + +B<int> a; // expected-note{{in instantiation of template class 'B<int>' requested here}} + +template<typename T> struct C : A<T> { +  using A<T>::f; +   +  void f() { }; +}; + +template <typename T> struct D : A<T> { +  using A<T>::f; +   +  void f(); +}; + +template<typename T> void D<T>::f() { } + +template<typename T> struct E : A<T> { +  using A<T>::f; + +  void g() { f(); } +}; + +namespace test0 { +  struct Base { +    int foo; +  }; +  template<typename T> struct E : Base { +    using Base::foo; +  }; + +  template struct E<int>; +} + +// PR7896 +namespace PR7896 { +template <class T> struct Foo { +  int k (float); +}; +struct Baz { +  int k (int); +}; +template <class T> struct Bar : public Foo<T>, Baz { +  using Foo<T>::k; +  using Baz::k; +  int foo() { +    return k (1.0f); +  } +}; +template int Bar<int>::foo(); +} + +// PR10883 +namespace PR10883 { +  template <typename T> +  class Base { +   public: +    typedef long Container; +  }; + +  template <typename T> +  class Derived : public Base<T> { +   public: +    using Base<T>::Container; + +    void foo(const Container& current); // expected-error {{unknown type name 'Container'}} +  }; +} diff --git a/clang/test/SemaCXX/using-directive.cpp b/clang/test/SemaCXX/using-directive.cpp new file mode 100644 index 0000000..22c6e14 --- /dev/null +++ b/clang/test/SemaCXX/using-directive.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { +  short i; // expected-note 2{{candidate found by name lookup is 'A::i'}} +  namespace B { +    long i; // expected-note{{candidate found by name lookup is 'A::B::i'}} +    void f() {} // expected-note{{candidate function}} +    int k; +    namespace E {} // \ +      expected-note{{candidate found by name lookup is 'A::B::E'}} +  } + +  namespace E {} // expected-note{{candidate found by name lookup is 'A::E'}} + +  namespace C { +    using namespace B; +    namespace E {} // \ +      expected-note{{candidate found by name lookup is 'A::C::E'}} +  } + +  void f() {} // expected-note{{candidate function}} + +  class K1 { +    void foo(); +  }; + +  void local_i() { +    char i; +    using namespace A; +    using namespace B; +    int a[sizeof(i) == sizeof(char)? 1 : -1]; // okay +  } +  namespace B { +    int j; +  } + +  void ambig_i() { +    using namespace A; +    using namespace A::B; +    (void) i; // expected-error{{reference to 'i' is ambiguous}} +    f(); // expected-error{{call to 'f' is ambiguous}} +    (void) j; // okay +    using namespace C; +    (void) k; // okay +    using namespace E; // expected-error{{reference to 'E' is ambiguous}} +  } + +  struct K2 {}; // expected-note 2{{candidate found by name lookup is 'A::K2'}} +} + +struct K2 {}; // expected-note 2{{candidate found by name lookup is 'K2'}} + +using namespace A; + +void K1::foo() {} // okay + +struct K2 *k2; // expected-error{{reference to 'K2' is ambiguous}} + +K2 *k3; // expected-error{{reference to 'K2' is ambiguous}} + +class X { // expected-note{{candidate found by name lookup is 'X'}} +  // FIXME: produce a suitable error message for this +  using namespace A; // expected-error{{not allowed}} +}; + +namespace N { +  struct K2; +  struct K2 { }; +} + +namespace Ni { + int i(); // expected-note{{candidate found by name lookup is 'Ni::i'}} +} + +namespace NiTest { + using namespace A; + using namespace Ni; + + int test() { +   return i; // expected-error{{reference to 'i' is ambiguous}} + } +} + +namespace OneTag { +  struct X; // expected-note{{candidate found by name lookup is 'OneTag::X'}} +} + +namespace OneFunction { +  void X(); // expected-note{{candidate found by name lookup is 'OneFunction::X'}} +} + +namespace TwoTag { +  struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} +} + +namespace FuncHidesTagAmbiguity { +  using namespace OneTag; +  using namespace OneFunction; +  using namespace TwoTag; + +  void test() { +    (void)X(); // expected-error{{reference to 'X' is ambiguous}} +  } +} + +// PR5479 +namespace Aliased { +  void inAliased(); +} +namespace Alias = Aliased; +using namespace Alias; +void testAlias() { +  inAliased(); +} + +namespace N { void f2(int); } + +extern "C++" { +  using namespace N; +  void f3() { f2(1); } +} + +void f4() { f2(1); } + +// PR7517 +using namespace std; // expected-warning{{using directive refers to implicitly-defined namespace 'std'}} +using namespace ::std; // expected-warning{{using directive refers to implicitly-defined namespace 'std'}} + +namespace test1 { +  namespace ns { typedef int test1; } +  template <class T> using namespace ns; // expected-error {{cannot template a using directive}} + +  // Test that we recovered okay. +  test1 x; +} diff --git a/clang/test/SemaCXX/value-dependent-exprs.cpp b/clang/test/SemaCXX/value-dependent-exprs.cpp new file mode 100644 index 0000000..2017ffa --- /dev/null +++ b/clang/test/SemaCXX/value-dependent-exprs.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -verify %s + +template <unsigned I> +class C0 { +  static const int iv0 = 1 << I; + +  enum { +    A = I, +    B = I + 1 +  }; + +  struct s0 { +    int a : I; +    int b[I]; +  }; + +  // FIXME: I'm unclear where the right place to handle this is. +#if 0 +  void f0(int *p) { +    if (p == I) { +    } +  } +#endif + +#if 0 +  // FIXME: Not sure whether we care about these. +  void f1(int *a) +    __attribute__((nonnull(1 + I))) +    __attribute__((constructor(1 + I))) +    __attribute__((destructor(1 + I))) +    __attribute__((sentinel(1 + I, 2 + I))), +    __attribute__((reqd_work_group_size(1 + I, 2 + I, 3 + I))), +    __attribute__((format_arg(1 + I))), +    __attribute__((aligned(1 + I))), +    __attribute__((regparm(1 + I))); + +  typedef int int_a0 __attribute__((address_space(1 + B))); +#endif + +#if 0 +  // FIXME: This doesn't work. PR4996. +  int f2() { +    return __builtin_choose_expr(I, 1, 2); +  } +#endif + +}; diff --git a/clang/test/SemaCXX/value-initialization.cpp b/clang/test/SemaCXX/value-initialization.cpp new file mode 100644 index 0000000..4e3acbb --- /dev/null +++ b/clang/test/SemaCXX/value-initialization.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct A { // expected-warning {{does not declare any constructor to initialize}} +     const int i; // expected-note{{const member 'i' will never be initialized}} expected-note {{implicitly deleted}} +     virtual void f() { }  +}; + +int main () { +      (void)A(); // expected-error {{call to implicitly-deleted default constructor}} +} diff --git a/clang/test/SemaCXX/vararg-default-arg.cpp b/clang/test/SemaCXX/vararg-default-arg.cpp new file mode 100644 index 0000000..3c8e41c --- /dev/null +++ b/clang/test/SemaCXX/vararg-default-arg.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only +// PR5462 + +void f1(void); +void f2(const char * = __null, ...); + +void f1(void) +{ +        f2(); +} diff --git a/clang/test/SemaCXX/vararg-non-pod.cpp b/clang/test/SemaCXX/vararg-non-pod.cpp new file mode 100644 index 0000000..86b560e --- /dev/null +++ b/clang/test/SemaCXX/vararg-non-pod.cpp @@ -0,0 +1,125 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs + +extern char version[]; + +class C { +public: +  C(int); +  void g(int a, ...); +  static void h(int a, ...); +}; + +void g(int a, ...); + +void t1() +{ +  C c(10); +   +  g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} +  g(10, version); +} + +void t2() +{ +  C c(10); + +  c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} +  c.g(10, version); +   +  C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} +  C::h(10, version); +} + +int (^block)(int, ...); + +void t3() +{ +  C c(10); +   +  block(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}} +  block(10, version); +} + +class D { +public: +  void operator() (int a, ...); +}; + +void t4() +{ +  C c(10); + +  D d; +   +  d(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} +  d(10, version); +} + +class E { +  E(int, ...); // expected-note 2{{implicitly declared private here}} +}; + +void t5() +{ +  C c(10); +   +  E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \ +    // expected-error{{calling a private constructor of class 'E'}} +  (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \ +    // expected-error{{calling a private constructor of class 'E'}} + +} + +// PR5761: unevaluated operands and the non-POD warning +class Foo { + public: +  Foo() {} +}; + +int Helper(...); +const int size = sizeof(Helper(Foo())); + +namespace std { +  class type_info { }; +} + +struct Base { virtual ~Base(); }; +Base &get_base(...); +int eat_base(...); + +void test_typeid(Base &base) { +  (void)typeid(get_base(base)); // expected-warning{{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}} +  (void)typeid(eat_base(base)); // okay +} + + +// rdar://7985267 - Shouldn't warn, doesn't actually use __builtin_va_start is +// magic. + +void t6(Foo somearg, ... ) { +  __builtin_va_list list; +  __builtin_va_start(list, somearg); +} + +void t7(int n, ...) { +  __builtin_va_list list; +  __builtin_va_start(list, n); +  (void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}} +  __builtin_va_end(list); +} + +struct Abstract { +  virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}} +}; + +void t8(int n, ...) { +  __builtin_va_list list; +  __builtin_va_start(list, n); +  (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}} +  __builtin_va_end(list); +} + +int t9(int n) { +  // Make sure the error works in potentially-evaluated sizeof +  return (int)sizeof(*(Helper(Foo()), (int (*)[n])0)); // expected-warning{{cannot pass object of non-POD type}} +} diff --git a/clang/test/SemaCXX/vector-casts.cpp b/clang/test/SemaCXX/vector-casts.cpp new file mode 100644 index 0000000..681a07e --- /dev/null +++ b/clang/test/SemaCXX/vector-casts.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +typedef int __v2si __attribute__((__vector_size__(8))); +typedef short __v4hi __attribute__((__vector_size__(8))); +typedef short __v8hi __attribute__((__vector_size__(16))); + +struct S { }; // expected-note 2 {{candidate constructor}} + +void f() { +  __v2si v2si; +  __v4hi v4hi; +  __v8hi v8hi; +  unsigned long long ll; +  unsigned char c; +  S s; +   +  (void)reinterpret_cast<__v2si>(v4hi); +  (void)(__v2si)v4hi; +  (void)reinterpret_cast<__v4hi>(v2si); +  (void)(__v4hi)v2si; +  (void)reinterpret_cast<unsigned long long>(v2si); +  (void)(unsigned long long)v2si; +  (void)reinterpret_cast<__v2si>(ll); +  (void)(__v2si)(ll); + +  (void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' to 'S' is not allowed}} +  (void)(S)v2si; // expected-error {{no matching conversion for C-style cast from '__v2si' to 'S'}} +  (void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'S' to '__v2si' is not allowed}} +  (void)(__v2si)s; // expected-error {{cannot convert 'S' to '__v2si' without a conversion operator}} +   +  (void)reinterpret_cast<unsigned char>(v2si); // expected-error {{reinterpret_cast from vector '__v2si' to scalar 'unsigned char' of different size}} +  (void)(unsigned char)v2si; // expected-error {{C-style cast from vector '__v2si' to scalar 'unsigned char' of different size}} +  (void)reinterpret_cast<__v2si>(c); // expected-error {{reinterpret_cast from scalar 'unsigned char' to vector '__v2si' of different size}} + +  (void)reinterpret_cast<__v8hi>(v4hi); // expected-error {{reinterpret_cast from vector '__v4hi' to vector '__v8hi' of different size}} +  (void)(__v8hi)v4hi; // expected-error {{C-style cast from vector '__v4hi' to vector '__v8hi' of different size}} +  (void)reinterpret_cast<__v4hi>(v8hi); // expected-error {{reinterpret_cast from vector '__v8hi' to vector '__v4hi' of different size}} +  (void)(__v4hi)v8hi; // expected-error {{C-style cast from vector '__v8hi' to vector '__v4hi' of different size}} +} + + diff --git a/clang/test/SemaCXX/vector-no-lax.cpp b/clang/test/SemaCXX/vector-no-lax.cpp new file mode 100644 index 0000000..32dcacf --- /dev/null +++ b/clang/test/SemaCXX/vector-no-lax.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -fno-lax-vector-conversions -verify %s +typedef unsigned int __attribute__((vector_size (16))) vUInt32; +typedef int __attribute__((vector_size (16))) vSInt32; + +vSInt32 foo (vUInt32 a) { +  vSInt32 b = { 0, 0, 0, 0 }; +  b += a; // expected-error{{can't convert between vector values}} +  return b; +} diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp new file mode 100644 index 0000000..82245ac --- /dev/null +++ b/clang/test/SemaCXX/vector.cpp @@ -0,0 +1,269 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s +typedef char char16 __attribute__ ((__vector_size__ (16))); +typedef long long longlong16 __attribute__ ((__vector_size__ (16))); +typedef char char16_e __attribute__ ((__ext_vector_type__ (16))); +typedef long long longlong16_e __attribute__ ((__ext_vector_type__ (2))); + +// Test overloading and function calls with vector types. +void f0(char16); + +void f0_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { +  f0(c16); +  f0(ll16); +  f0(c16e); +  f0(ll16e); +} + +int &f1(char16); // expected-note 2{{candidate function}} +float &f1(longlong16); // expected-note 2{{candidate function}} + +void f1_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { +  int &ir1 = f1(c16); +  float &fr1 = f1(ll16); +  f1(c16e); // expected-error{{call to 'f1' is ambiguous}} +  f1(ll16e); // expected-error{{call to 'f1' is ambiguous}} +} + +void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' to 'char16_e' for 1st argument}} \ +       // expected-note{{candidate function not viable: no known conversion from 'convertible_to<longlong16_e>' to 'char16_e' for 1st argument}} + +void f2_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { +  f2(c16); +  f2(ll16); +  f2(c16e); +  f2(ll16e); // expected-error{{no matching function}} +  f2('a'); +  f2(17); +} + +// Test the conditional operator with vector types. +void conditional(bool Cond, char16 c16, longlong16 ll16, char16_e c16e,  +                 longlong16_e ll16e) { +  // Conditional operators with the same type. +  __typeof__(Cond? c16 : c16) *c16p1 = &c16; +  __typeof__(Cond? ll16 : ll16) *ll16p1 = &ll16; +  __typeof__(Cond? c16e : c16e) *c16ep1 = &c16e; +  __typeof__(Cond? ll16e : ll16e) *ll16ep1 = &ll16e; + +  // Conditional operators with similar types. +  __typeof__(Cond? c16 : c16e) *c16ep2 = &c16e; +  __typeof__(Cond? c16e : c16) *c16ep3 = &c16e; +  __typeof__(Cond? ll16 : ll16e) *ll16ep2 = &ll16e; +  __typeof__(Cond? ll16e : ll16) *ll16ep3 = &ll16e; + +  // Conditional operators with compatible types under -flax-vector-conversions (default) +  (void)(Cond? c16 : ll16); +  (void)(Cond? ll16e : c16e); +  (void)(Cond? ll16e : c16); +} + +// Test C++ cast'ing of vector types. +void casts(longlong16 ll16, longlong16_e ll16e) { +  // C-style casts. +  (void)(char16)ll16; +  (void)(char16_e)ll16; +  (void)(longlong16)ll16; +  (void)(longlong16_e)ll16; +  (void)(char16)ll16e; +  (void)(char16_e)ll16e; +  (void)(longlong16)ll16e; +  (void)(longlong16_e)ll16e; + +  // Function-style casts. +  (void)char16(ll16); +  (void)char16_e(ll16); +  (void)longlong16(ll16); +  (void)longlong16_e(ll16); +  (void)char16(ll16e); +  (void)char16_e(ll16e); +  (void)longlong16(ll16e); +  (void)longlong16_e(ll16e); + +  // static_cast +  (void)static_cast<char16>(ll16); +  (void)static_cast<char16_e>(ll16); +  (void)static_cast<longlong16>(ll16); +  (void)static_cast<longlong16_e>(ll16); +  (void)static_cast<char16>(ll16e); +  (void)static_cast<char16_e>(ll16e); // expected-error{{static_cast from 'longlong16_e' to 'char16_e' is not allowed}} +  (void)static_cast<longlong16>(ll16e); +  (void)static_cast<longlong16_e>(ll16e); + +  // reinterpret_cast +  (void)reinterpret_cast<char16>(ll16); +  (void)reinterpret_cast<char16_e>(ll16); +  (void)reinterpret_cast<longlong16>(ll16); +  (void)reinterpret_cast<longlong16_e>(ll16); +  (void)reinterpret_cast<char16>(ll16e); +  (void)reinterpret_cast<char16_e>(ll16e); +  (void)reinterpret_cast<longlong16>(ll16e); +  (void)reinterpret_cast<longlong16_e>(ll16e); +} + +template<typename T> +struct convertible_to { // expected-note 3 {{candidate function (the implicit copy assignment operator)}} +  operator T() const; +}; + +void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16,  +                               char16_e c16e, longlong16_e ll16e, +                               convertible_to<char16> to_c16,  +                               convertible_to<longlong16> to_ll16,  +                               convertible_to<char16_e> to_c16e,  +                               convertible_to<longlong16_e> to_ll16e, +                               convertible_to<char16&> rto_c16, +                               convertible_to<char16_e&> rto_c16e) { +  f0(to_c16); +  f0(to_ll16); +  f0(to_c16e); +  f0(to_ll16e); +  f2(to_c16); +  f2(to_ll16); +  f2(to_c16e); +  f2(to_ll16e); // expected-error{{no matching function}} + +  (void)(c16 == c16e); +  (void)(c16 == to_c16); +  (void)+to_c16; +  (void)-to_c16; +  (void)~to_c16; +  (void)(to_c16 == to_c16e); +  (void)(to_c16 != to_c16e); +  (void)(to_c16 <  to_c16e); +  (void)(to_c16 <= to_c16e); +  (void)(to_c16 >  to_c16e); +  (void)(to_c16 >= to_c16e); +  (void)(to_c16 + to_c16); +  (void)(to_c16 - to_c16); +  (void)(to_c16 * to_c16); +  (void)(to_c16 / to_c16); +  (void)(rto_c16 = to_c16); // expected-error{{no viable overloaded '='}} +  (void)(rto_c16 += to_c16); +  (void)(rto_c16 -= to_c16); +  (void)(rto_c16 *= to_c16); +  (void)(rto_c16 /= to_c16); + +  (void)+to_c16e; +  (void)-to_c16e; +  (void)~to_c16e; +  (void)(to_c16e == to_c16e); +  (void)(to_c16e != to_c16e); +  (void)(to_c16e <  to_c16e); +  (void)(to_c16e <= to_c16e); +  (void)(to_c16e >  to_c16e); +  (void)(to_c16e >= to_c16e); +  (void)(to_c16e + to_c16); +  (void)(to_c16e - to_c16); +  (void)(to_c16e * to_c16); +  (void)(to_c16e / to_c16); +  (void)(rto_c16e = to_c16); // expected-error{{no viable overloaded '='}} +  (void)(rto_c16e += to_c16); +  (void)(rto_c16e -= to_c16); +  (void)(rto_c16e *= to_c16); +  (void)(rto_c16e /= to_c16); + +  (void)+to_c16; +  (void)-to_c16; +  (void)~to_c16; +  (void)(to_c16 == to_c16e); +  (void)(to_c16 != to_c16e); +  (void)(to_c16 <  to_c16e); +  (void)(to_c16 <= to_c16e); +  (void)(to_c16 >  to_c16e); +  (void)(to_c16 >= to_c16e); +  (void)(to_c16 + to_c16e); +  (void)(to_c16 - to_c16e); +  (void)(to_c16 * to_c16e); +  (void)(to_c16 / to_c16e); +  (void)(rto_c16 = c16e); // expected-error{{no viable overloaded '='}} +  (void)(rto_c16 += to_c16e); +  (void)(rto_c16 -= to_c16e); +  (void)(rto_c16 *= to_c16e); +  (void)(rto_c16 /= to_c16e); + +  (void)(Cond? to_c16 : to_c16e); +  (void)(Cond? to_ll16e : to_ll16); +   +  // These 2 are convertable with -flax-vector-conversions (default) +  (void)(Cond? to_c16 : to_ll16); +  (void)(Cond? to_c16e : to_ll16e); +} + +typedef float fltx2 __attribute__((__vector_size__(8))); +typedef float fltx4 __attribute__((__vector_size__(16))); +typedef double dblx2 __attribute__((__vector_size__(16))); +typedef double dblx4 __attribute__((__vector_size__(32))); + +void accept_fltx2(fltx2); // expected-note{{candidate function not viable: no known conversion from 'double' to 'fltx2' for 1st argument}} +void accept_fltx4(fltx4); +void accept_dblx2(dblx2); +void accept_dblx4(dblx4); +void accept_bool(bool); // expected-note{{candidate function not viable: no known conversion from 'fltx2' to 'bool' for 1st argument}} + +void test(fltx2 fltx2_val, fltx4 fltx4_val, dblx2 dblx2_val, dblx4 dblx4_val) { +  // Exact matches +  accept_fltx2(fltx2_val); +  accept_fltx4(fltx4_val); +  accept_dblx2(dblx2_val); +  accept_dblx4(dblx4_val); + +  // Same-size conversions +  // FIXME: G++ rejects these conversions, we accept them. Revisit this! +  accept_fltx4(dblx2_val); +  accept_dblx2(fltx4_val); + +  // Conversion to bool. +  accept_bool(fltx2_val); // expected-error{{no matching function for call to 'accept_bool'}} + +  // Scalar-to-vector conversions. +  accept_fltx2(1.0); // expected-error{{no matching function for call to 'accept_fltx2'}} +} + +typedef int intx4 __attribute__((__vector_size__(16))); +typedef int inte4 __attribute__((__ext_vector_type__(4))); +typedef int flte4 __attribute__((__ext_vector_type__(4))); + +void test_mixed_vector_types(fltx4 f, intx4 n, flte4 g, flte4 m) { +  (void)(f == g); +  (void)(g != f); +  (void)(f <= g); +  (void)(g >= f); +  (void)(f < g); +  (void)(g > f); + +  (void)(+g); +  (void)(-g); + +  (void)(f + g); +  (void)(f - g); +  (void)(f * g); +  (void)(f / g); +  (void)(f = g); +  (void)(f += g); +  (void)(f -= g); +  (void)(f *= g); +  (void)(f /= g); + + +  (void)(n == m); +  (void)(m != n); +  (void)(n <= m); +  (void)(m >= n); +  (void)(n < m); +  (void)(m > n); + +  (void)(+m); +  (void)(-m); +  (void)(~m); + +  (void)(n + m); +  (void)(n - m); +  (void)(n * m); +  (void)(n / m); +  (void)(n % m); +  (void)(n = m); +  (void)(n += m); +  (void)(n -= m); +  (void)(n *= m); +  (void)(n /= m); +} diff --git a/clang/test/SemaCXX/virtual-base-used.cpp b/clang/test/SemaCXX/virtual-base-used.cpp new file mode 100644 index 0000000..d147b13 --- /dev/null +++ b/clang/test/SemaCXX/virtual-base-used.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// PR7800 + +class NoDestroy { ~NoDestroy(); }; // expected-note 3 {{declared private here}} +struct A { +  virtual ~A(); +}; + +struct B : public virtual A { +  NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} +}; +struct D : public virtual B { +  virtual void foo(); +  ~D(); +}; +void D::foo() { // expected-note {{implicit default destructor for 'B' first required here}} +} + +struct E : public virtual A { +  NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} +}; +struct F : public E { // expected-note {{implicit default destructor for 'E' first required here}} +}; +struct G : public virtual F { +  virtual void foo(); +  ~G(); +}; +void G::foo() { // expected-note {{implicit default destructor for 'F' first required here}} +} + +struct H : public virtual A { +  NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} +}; +struct I : public virtual H { +  ~I(); +}; +struct J : public I { +  virtual void foo(); +  ~J(); +}; +void J::foo() { // expected-note {{implicit default destructor for 'H' first required here}} +} diff --git a/clang/test/SemaCXX/virtual-member-functions-key-function.cpp b/clang/test/SemaCXX/virtual-member-functions-key-function.cpp new file mode 100644 index 0000000..09a30b9 --- /dev/null +++ b/clang/test/SemaCXX/virtual-member-functions-key-function.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { +  virtual ~A(); +}; + +struct B : A {  // expected-error {{no suitable member 'operator delete' in 'B'}} +  B() { } // expected-note {{implicit default destructor for 'B' first required here}} +  void operator delete(void *, int); // expected-note {{'operator delete' declared here}} +};  + +struct C : A {  // expected-error {{no suitable member 'operator delete' in 'C'}} +  void operator delete(void *, int); // expected-note {{'operator delete' declared here}} +};  + +void f() { +  (void)new B;  +  (void)new C; // expected-note {{implicit default destructor for 'C' first required here}} +} + +// Make sure that the key-function computation is consistent when the +// first virtual member function of a nested class has an inline body. +struct Outer { +  struct Inner { +    virtual void f() { } +    void g(); +  }; +}; + +void Outer::Inner::g() { } diff --git a/clang/test/SemaCXX/virtual-override.cpp b/clang/test/SemaCXX/virtual-override.cpp new file mode 100644 index 0000000..b477438 --- /dev/null +++ b/clang/test/SemaCXX/virtual-override.cpp @@ -0,0 +1,290 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +namespace T1 { + +class A { +  virtual int f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { +  virtual void f(); // expected-error{{virtual function 'f' has a different return type ('void') than the function it overrides (which has return type 'int')}} +}; + +} + +namespace T2 { + +struct a { }; +struct b { }; +   +class A { +  virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { +  virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('T2::b *' is not derived from 'T2::a *')}} +}; + +} + +namespace T3 { + +struct a { }; +struct b : private a { }; // expected-note{{declared private here}} +   +class A { +  virtual a* f(); // FIXME: desired-note{{overridden virtual function is here}} +}; + +class B : A { +  virtual b* f(); // expected-error{{invalid covariant return for virtual function: 'T3::a' is a private base class of 'T3::b'}} +}; + +} + +namespace T4 { + +struct a { }; +struct a1 : a { }; +struct b : a, a1 { }; +   +class A { +  virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { +  virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (ambiguous conversion from derived class 'T4::b' to base class 'T4::a':\n\ +    struct T4::b -> struct T4::a\n\ +    struct T4::b -> struct T4::a1 -> struct T4::a)}} +}; + +} + +namespace T5 { +   +struct a { }; + +class A { +  virtual a* const f();  +  virtual a* const g(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { +  virtual a* const f();  +  virtual a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides ('T5::a *' has different qualifiers than 'T5::a *const')}} +}; + +} + +namespace T6 { +   +struct a { }; + +class A { +  virtual const a* f();  +  virtual a* g(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { +  virtual a* f();  +  virtual const a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides (class type 'const T6::a *' is more qualified than class type 'T6::a *'}} +}; + +} + +namespace T7 { +  struct a { }; +  struct b { }; + +  class A { +    a* f(); +  }; + +  class B : A { +    virtual b* f(); +  }; +} + +namespace T8 { +  struct a { }; +  struct b; // expected-note {{forward declaration of 'T8::b'}} +   +  class A { +    virtual a *f(); +  }; +   +  class B : A { +    b* f(); // expected-error {{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('T8::b' is incomplete)}} +  }; +} + +namespace T9 { +  struct a { }; +   +  template<typename T> struct b : a { +    int a[sizeof(T) ? -1 : -1]; // expected-error {{array with a negative size}} +  }; +   +  class A { +    virtual a *f(); +  }; +   +  class B : A { +    virtual b<int> *f(); // expected-note {{in instantiation of template class 'T9::b<int>' requested here}} +  }; +} + +// PR5656 +class X0 { +  virtual void f0(); +}; +class X1 : public X0 { +  void f0() = 0; +}; + +template <typename Base> +struct Foo : Base {  +  void f(int) = 0; // expected-error{{not virtual and cannot be declared pure}} +}; + +struct Base1 { virtual void f(int); }; +struct Base2 { }; + +void test() { +  (void)sizeof(Foo<Base1>); +  (void)sizeof(Foo<Base2>); // expected-note{{instantiation}} +} + +template<typename Base> +struct Foo2 : Base { +  template<typename T> int f(T); +}; + +void test2() { +  Foo2<Base1> f1; +  Foo2<Base2> f2; +  f1.f(17); +  f2.f(17); +}; + +struct Foo3 { +  virtual void f(int) = 0; // expected-note{{unimplemented pure virtual method}} +}; + +template<typename T> +struct Bar3 : Foo3 { +  void f(T); +}; + +void test3() { +  Bar3<int> b3i; // okay +  Bar3<float> b3f; // expected-error{{is an abstract class}} +} + +// 5920 +namespace PR5920 { +  class Base {}; + +  template <typename T> +  class Derived : public Base {}; + +  class Foo { +   public: +    virtual Base* Method(); +  }; + +  class Bar : public Foo { +   public: +    virtual Derived<int>* Method(); +  }; +} + +// Look through template types and typedefs to see whether return types are +// pointers or references. +namespace PR6110 { +  class Base {}; +  class Derived : public Base {}; + +  typedef Base* BaseP; +  typedef Derived* DerivedP; + +  class X { virtual BaseP f(); }; +  class X1 : public X { virtual DerivedP f(); }; + +  template <typename T> class Y { virtual T f(); }; +  template <typename T1, typename T> class Y1 : public Y<T> { virtual T1 f(); }; +  Y1<Derived*, Base*> y; +} + +// Defer checking for covariance if either return type is dependent. +namespace type_dependent_covariance { +  struct B {}; +  template <int N> struct TD : public B {}; +  template <> struct TD<1> {}; + +  template <int N> struct TB {}; +  struct D : public TB<0> {}; + +  template <int N> struct X { +    virtual B* f1(); // expected-note{{overridden virtual function is here}} +    virtual TB<N>* f2(); // expected-note{{overridden virtual function is here}} +  }; +  template <int N, int M> struct X1 : X<N> { +    virtual TD<M>* f1(); // expected-error{{return type of virtual function 'f1' is not covariant with the return type of the function it overrides ('TD<1> *'}} +    virtual D* f2(); // expected-error{{return type of virtual function 'f2' is not covariant with the return type of the function it overrides ('type_dependent_covariance::D *' is not derived from 'TB<1> *')}} +  }; + +  X1<0, 0> good; +  X1<0, 1> bad_derived; // expected-note{{instantiation}} +  X1<1, 0> bad_base; // expected-note{{instantiation}} +} + +namespace T10 { +  struct A { }; +  struct B : A { }; + +  struct C {  +    virtual A&& f(); +  }; + +  struct D : C { +    virtual B&& f(); +  }; +}; + +namespace T11 { +  struct A { }; +  struct B : A { }; + +  struct C {  +    virtual A& f(); // expected-note {{overridden virtual function is here}} +  }; + +  struct D : C { +    virtual B&& f(); // expected-error {{virtual function 'f' has a different return type ('T11::B &&') than the function it overrides (which has return type 'T11::A &')}} +  }; +}; + +namespace T12 { +  struct A { }; +  struct B : A { }; + +  struct C {  +    virtual A&& f(); // expected-note {{overridden virtual function is here}} +  }; + +  struct D : C { +    virtual B& f(); // expected-error {{virtual function 'f' has a different return type ('T12::B &') than the function it overrides (which has return type 'T12::A &&')}} +  }; +}; + +namespace PR8168 { +  class A { +  public: +    virtual void foo() {} // expected-note{{overridden virtual function is here}} +  }; + +  class B : public A { +  public: +    static void foo() {} // expected-error{{'static' member function 'foo' overrides a virtual function}} +  }; +} diff --git a/clang/test/SemaCXX/virtuals.cpp b/clang/test/SemaCXX/virtuals.cpp new file mode 100644 index 0000000..ea7d203 --- /dev/null +++ b/clang/test/SemaCXX/virtuals.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 %s + +class A { +  virtual void f(); +  virtual void g() = 0; // expected-note{{unimplemented pure virtual method 'g' in 'A'}} + +  void h() = 0; // expected-error {{'h' is not virtual and cannot be declared pure}} +  void i() = 1; // expected-error {{initializer on function does not look like a pure-specifier}} +  void j() = 0u; // expected-error {{initializer on function does not look like a pure-specifier}} + + +  void k(); + +public: +  A(int); +}; + +virtual void A::k() { } // expected-error{{'virtual' can only be specified inside the class definition}} + +class B : public A { +  // Needs to recognize that overridden function is virtual. +  void g() = 0; + +  // Needs to recognize that function does not override. +  void g(int) = 0; // expected-error{{'g' is not virtual and cannot be declared pure}} +}; + +// Needs to recognize invalid uses of abstract classes. +A fn(A) // expected-error{{parameter type 'A' is an abstract class}} \ +        // expected-error{{return type 'A' is an abstract class}} +{ +  A a; // expected-error{{variable type 'A' is an abstract class}} +  (void)static_cast<A>(0); +  try { +  } catch(A) { // expected-error{{variable type 'A' is an abstract class}} +  } +} + +namespace rdar9670557 { +  typedef int func(int); +  func *a(); +  struct X { +    virtual func f = 0; +    virtual func (g) = 0; +    func *h = 0; +  }; +} diff --git a/clang/test/SemaCXX/vla.cpp b/clang/test/SemaCXX/vla.cpp new file mode 100644 index 0000000..d63b633 --- /dev/null +++ b/clang/test/SemaCXX/vla.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -verify %s + +// PR11925 +int n; +int (&f())[n]; // expected-error {{function declaration cannot have variably modified type}} diff --git a/clang/test/SemaCXX/vtable-instantiation.cc b/clang/test/SemaCXX/vtable-instantiation.cc new file mode 100644 index 0000000..2a1b989 --- /dev/null +++ b/clang/test/SemaCXX/vtable-instantiation.cc @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8640 { +  template<class T1> struct C1 { +    virtual void c1() { +      T1 t1 = 3;  // expected-error {{cannot initialize a variable}} +    } +  }; + +  template<class T2> struct C2 { +    void c2() { +      new C1<T2>();  // expected-note {{in instantiation of member function}} +    } +  }; + +  void f() { +    C2<int*> c2; +    c2.c2();  // expected-note {{in instantiation of member function}} +  } +} + +namespace PR9325 { +  template<typename T> +  class Target +  { +  public: +    virtual T Value() const +    { +      return 1; // expected-error{{cannot initialize return object of type 'int *' with an rvalue of type 'int'}} +    } +  }; + +  template<typename T> +  struct Provider +  { +    static Target<T> Instance; +  }; + +  template<typename T> +  Target<T> Provider<T>::Instance; // expected-note{{in instantiation of}} + +  void f() +  { +    Target<int*>* traits = &Provider<int*>::Instance; +  } +} + +namespace PR10020 { +  struct MG { +    virtual void Accept(int) = 0; +  }; + +  template <typename Type> +  struct GMG : MG { +    void Accept(int i) { +      static_cast<Type *>(0)->Accept(i); // expected-error{{member reference base}} +    } +    static GMG* Method() { return &singleton; } // expected-note{{in instantiation of}} +    static GMG singleton; +  }; + +  template <typename Type> +  GMG<Type> GMG<Type>::singleton; + +  void test(void) { +    GMG<int>::Method(); // expected-note{{in instantiation of}} +  } +} diff --git a/clang/test/SemaCXX/warn-assignment-condition.cpp b/clang/test/SemaCXX/warn-assignment-condition.cpp new file mode 100644 index 0000000..04f2e79 --- /dev/null +++ b/clang/test/SemaCXX/warn-assignment-condition.cpp @@ -0,0 +1,146 @@ +// RUN: %clang_cc1 -fsyntax-only -Wparentheses -verify %s + +struct A { +  int foo(); +  friend A operator+(const A&, const A&); +  A operator|=(const A&); +  operator bool(); +}; + +void test() { +  int x, *p; +  A a, b; + +  // With scalars. +  if (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  if ((x = 7)) {} +  do { +  } while (x = 7); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  do { +  } while ((x = 7)); +  while (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} + +  while ((x = 7)) {} +  for (; x = 7; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  for (; (x = 7); ) {} + +  if (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  if ((p = p)) {} +  do { +  } while (p = p); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  do { +  } while ((p = p)); +  while (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  while ((p = p)) {} +  for (; p = p; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  for (; (p = p); ) {} + +  // Initializing variables (shouldn't warn). +  if (int y = x) {} +  while (int y = x) {} +  if (A y = a) {} +  while (A y = a) {} + +  // With temporaries. +  if (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  if ((x = (b+b).foo())) {} +  do { +  } while (x = (b+b).foo()); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  do { +  } while ((x = (b+b).foo())); +  while (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  while ((x = (b+b).foo())) {} +  for (; x = (b+b).foo(); ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  for (; (x = (b+b).foo()); ) {} + +  // With a user-defined operator. +  if (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  if ((a = b + b)) {} +  do { +  } while (a = b + b); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  do { +  } while ((a = b + b)); +  while (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  while ((a = b + b)) {} +  for (; a = b + b; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '==' to turn this assignment into an equality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} +  for (; (a = b + b); ) {} + +  // Compound assignments. +  if (x |= 2) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '!=' to turn this compound assignment into an inequality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} + +  if (a |= b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ +                // expected-note{{use '!=' to turn this compound assignment into an inequality comparison}} \ +  // expected-note{{place parentheses around the assignment to silence this warning}} + +  if ((x == 5)) {} // expected-warning {{equality comparison with extraneous parentheses}} \ +                   // expected-note {{use '=' to turn this equality comparison into an assignment}} \ +                   // expected-note {{remove extraneous parentheses around the comparison to silence this warning}} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wparentheses-equality" +  if ((x == 5)) {} // no-warning +#pragma clang diagnostic pop + +  if ((5 == x)) {} + +#define EQ(x,y) ((x) == (y)) +  if (EQ(x, 5)) {} +#undef EQ +} + +void (*fn)(); + +void test2() { +    if ((fn == test2)) {} // expected-warning {{equality comparison with extraneous parentheses}} \ +                          // expected-note {{use '=' to turn this equality comparison into an assignment}} \ +                          // expected-note {{remove extraneous parentheses around the comparison to silence this warning}} +    if ((test2 == fn)) {} +} + +namespace rdar9027658 { +template <typename T> +void f() { +    if ((T::g == 3)) { } // expected-warning {{equality comparison with extraneous parentheses}} \ +                         // expected-note {{use '=' to turn this equality comparison into an assignment}} \ +                         // expected-note {{remove extraneous parentheses around the comparison to silence this warning}} +} + +struct S { int g; }; +void test() { +  f<S>(); // expected-note {{in instantiation}} +} +} diff --git a/clang/test/SemaCXX/warn-bad-memaccess.cpp b/clang/test/SemaCXX/warn-bad-memaccess.cpp new file mode 100644 index 0000000..3a02c84 --- /dev/null +++ b/clang/test/SemaCXX/warn-bad-memaccess.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -fsyntax-only -Wdynamic-class-memaccess -verify %s + +extern "C" void *memset(void *, int, unsigned); +extern "C" void *memmove(void *s1, const void *s2, unsigned n); +extern "C" void *memcpy(void *s1, const void *s2, unsigned n); +extern "C" void *memcmp(void *s1, const void *s2, unsigned n); + +// Several types that should not warn. +struct S1 {} s1; +struct S2 { int x; } s2; +struct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3; + +class C1 { +  int x, y, z; +public: +  void foo() {} +} c1; + +struct X1 { virtual void f(); } x1; +struct X2 : virtual S1 {} x2; + +void test_warn() { +  memset(&x1, 0, sizeof x1); // \ +      // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  memset(&x2, 0, sizeof x2); // \ +      // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} + +  memmove(&x1, 0, sizeof x1); // \ +      // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  memmove(0, &x1, sizeof x1); // \ +      // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be moved}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  memcpy(&x1, 0, sizeof x1); // \ +      // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  memcpy(0, &x1, sizeof x1); // \ +      // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be copied}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  memcmp(&x1, 0, sizeof x1); // \ +      // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  memcmp(0, &x1, sizeof x1); // \ +      // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} + +  __builtin_memset(&x1, 0, sizeof x1); // \ +      // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin_memset(&x2, 0, sizeof x2); // \ +      // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} + +  __builtin_memmove(&x1, 0, sizeof x1); // \ +      // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin_memmove(0, &x1, sizeof x1); // \ +      // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin_memcpy(&x1, 0, sizeof x1); // \ +      // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin_memcpy(0, &x1, sizeof x1); // \ +      // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} + +  __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); //                    \ +      // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); //                    \ +      // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} + +  __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); //                   \ +      // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); //                   \ +      // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); //                    \ +      // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +  __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); //                    \ +      // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ +      // expected-note {{explicitly cast the pointer to silence this warning}} +} + +void test_nowarn(void *void_ptr) { +  int i, *iptr; +  float y; +  char c; + +  memset(&i, 0, sizeof i); +  memset(&iptr, 0, sizeof iptr); +  memset(&y, 0, sizeof y); +  memset(&c, 0, sizeof c); +  memset(void_ptr, 0, 42); +  memset(&s1, 0, sizeof s1); +  memset(&s2, 0, sizeof s2); +  memset(&s3, 0, sizeof s3); +  memset(&c1, 0, sizeof c1); + +  // Unevaluated code shouldn't warn. +  (void)sizeof memset(&x1, 0, sizeof x1); + +  // Dead code shouldn't warn. +  if (false) memset(&x1, 0, sizeof x1); +} + +namespace N { +  void *memset(void *, int, unsigned); +  void test_nowarn() { +    N::memset(&x1, 0, sizeof x1); +  } +} diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp new file mode 100644 index 0000000..b3d136e --- /dev/null +++ b/clang/test/SemaCXX/warn-bool-conversion.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int* j = false; // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} + +void foo(int* i, int *j=(false)) // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} +{ +  foo(false); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} +  foo((int*)false); // no-warning: explicit cast +  foo(0); // no-warning: not a bool, even though its convertible to bool + +  foo(false == true); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} +  foo((42 + 24) < 32); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} + +  const bool kFlag = false; +  foo(kFlag); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} +} + +char f(struct Undefined*); +double f(...); + +// Ensure that when using false in metaprogramming machinery its conversion +// isn't flagged. +template <int N> struct S {}; +S<sizeof(f(false))> s; diff --git a/clang/test/SemaCXX/warn-cast-align.cpp b/clang/test/SemaCXX/warn-cast-align.cpp new file mode 100644 index 0000000..68acbdd --- /dev/null +++ b/clang/test/SemaCXX/warn-cast-align.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -Wcast-align -verify %s + +// Simple casts. +void test0(char *P) { +  char *a; short *b; int *c; + +  a = (char*) P; +  a = static_cast<char*>(P); +  a = reinterpret_cast<char*>(P); +  typedef char *CharPtr; +  a = CharPtr(P); + +  b = (short*) P; // expected-warning {{cast from 'char *' to 'short *' increases required alignment from 1 to 2}} +  b = reinterpret_cast<short*>(P); +  typedef short *ShortPtr; +  b = ShortPtr(P); // expected-warning {{cast from 'char *' to 'ShortPtr' (aka 'short *') increases required alignment from 1 to 2}} + +  c = (int*) P; // expected-warning {{cast from 'char *' to 'int *' increases required alignment from 1 to 4}} +  c = reinterpret_cast<int*>(P); +  typedef int *IntPtr; +  c = IntPtr(P); // expected-warning {{cast from 'char *' to 'IntPtr' (aka 'int *') increases required alignment from 1 to 4}} +} + +// Casts from void* are a special case. +void test1(void *P) { +  char *a; short *b; int *c; + +  a = (char*) P; +  a = static_cast<char*>(P); +  a = reinterpret_cast<char*>(P); +  typedef char *CharPtr; +  a = CharPtr(P); + +  b = (short*) P; +  b = static_cast<short*>(P); +  b = reinterpret_cast<short*>(P); +  typedef short *ShortPtr; +  b = ShortPtr(P); + +  c = (int*) P; +  c = static_cast<int*>(P); +  c = reinterpret_cast<int*>(P); +  typedef int *IntPtr; +  c = IntPtr(P); +} diff --git a/clang/test/SemaCXX/warn-char-subscripts.cpp b/clang/test/SemaCXX/warn-char-subscripts.cpp new file mode 100644 index 0000000..84ea536 --- /dev/null +++ b/clang/test/SemaCXX/warn-char-subscripts.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -Wchar-subscripts -fsyntax-only -verify %s + +template<typename T> +void t1() { +  int array[1] = { 0 }; +  T subscript = 0; +  int val = array[subscript]; // expected-warning{{array subscript is of type 'char'}} +} + +template<typename T> +void t2() { +  int array[1] = { 0 }; +  T subscript = 0; +  int val = subscript[array]; // expected-warning{{array subscript is of type 'char'}} +} + +void test() { +  t1<char>(); // expected-note {{in instantiation of function template specialization 't1<char>' requested here}} +  t2<char>(); // expected-note {{in instantiation of function template specialization 't2<char>' requested here}} +} + diff --git a/clang/test/SemaCXX/warn-dangling-field.cpp b/clang/test/SemaCXX/warn-dangling-field.cpp new file mode 100644 index 0000000..95f8c61 --- /dev/null +++ b/clang/test/SemaCXX/warn-dangling-field.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -Wdangling-field -verify %s + +struct X { +  X(int); +}; +struct Y { +  operator X*(); +  operator X&(); +}; + +struct S { +  int &x, *y;  // expected-note {{reference member declared here}} \ +               // expected-note {{pointer member declared here}} +  S(int i) +    : x(i),    // expected-warning {{binding reference member 'x' to stack allocated parameter 'i'}} +      y(&i) {} // expected-warning {{initializing pointer member 'y' with the stack address of parameter 'i'}} +  S(int &i) : x(i), y(&i) {} // no-warning: reference parameter +  S(int *i) : x(*i), y(i) {} // no-warning: pointer parameter +}; + +struct S2 { +  const X &x; // expected-note {{reference member declared here}} +  S2(int i) : x(i) {} // expected-warning {{binding reference member 'x' to a temporary}} +}; + +struct S3 { +  X &x1, *x2; +  S3(Y y) : x1(y), x2(y) {} // no-warning: conversion operator +}; + +template <typename T> struct S4 { +  T x; // expected-note {{reference member declared here}} +  S4(int i) : x(i) {} // expected-warning {{binding reference member 'x' to stack allocated parameter 'i'}} +}; + +template struct S4<int>; // no warning from this instantiation +template struct S4<int&>; // expected-note {{in instantiation}} diff --git a/clang/test/SemaCXX/warn-deprecated-header.cpp b/clang/test/SemaCXX/warn-deprecated-header.cpp new file mode 100644 index 0000000..f6ac2cb --- /dev/null +++ b/clang/test/SemaCXX/warn-deprecated-header.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -fdeprecated-macro -verify %s +// RUN: %clang_cc1 -fsyntax-only -Werror %s + +#ifdef __DEPRECATED +#warning This file is deprecated. // expected-warning {{This file is deprecated.}} +#endif diff --git a/clang/test/SemaCXX/warn-empty-body.cpp b/clang/test/SemaCXX/warn-empty-body.cpp new file mode 100644 index 0000000..d643ced --- /dev/null +++ b/clang/test/SemaCXX/warn-empty-body.cpp @@ -0,0 +1,271 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void a(int i); +int b(); +int c(); + +void test1(int x, int y) { +  while(true) { +    if (x); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + +    int i; +    // PR11329 +    for (i = 0; i < x; i++); { // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      a(i); +      b(); +    } + +    for (i = 0; i < x; i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    { +      a(i); +    } + +    for (i = 0; +         i < x; +         i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    { +      a(i); +    } + +    int arr[3] = { 1, 2, 3 }; +    for (int j : arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      a(i); + +    for (int j : +         arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      a(i); + +    while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      a(i); + +    while (b() == 0); { // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      a(i); +    } + +    while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    { +      a(i); +    } + +    while (b() == 0 || +           c() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    { +      a(i); +    } + +    do;          // expected-note{{to match this 'do'}} +      b();       // expected-error{{expected 'while' in do/while loop}} +    while (b()); // no-warning +    c(); + +    do;          // expected-note{{to match this 'do'}} +      b();       // expected-error{{expected 'while' in do/while loop}} +    while (b()); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      c(); + +    switch(x) // no-warning +    { +      switch(y); // expected-warning{{switch statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +      { +        case 0: +          a(10); +          break; +        default: +          a(20); +          break; +      } +    } +  } +} + +/// There should be no warning  when null statement is placed on its own line. +void test2(int x, int y) { +  if (x) // no-warning +    ; // no-warning + +  int i; +  for (i = 0; i < x; i++) // no-warning +    ; // no-warning + +  for (i = 0; +       i < x; +       i++) // no-warning +    ; // no-warning + +  int arr[3] = { 1, 2, 3 }; +  for (int j : arr) // no-warning +    ; // no-warning + +  while (b() == 0) // no-warning +    ; // no-warning + +  while (b() == 0 || +         c() == 0) // no-warning +    ; // no-warning + +  switch(x) +  { +    switch(y) // no-warning +      ; // no-warning +  } + +  // Last `for' or `while' statement in compound statement shouldn't warn. +  while(b() == 0); // no-warning +} + +/// There should be no warning for a null statement resulting from an empty macro. +#define EMPTY(a) +void test3(int x, int y) { +  if (x) EMPTY(x); // no-warning + +  int i; +  for (i = 0; i < x; i++) EMPTY(i); // no-warning + +  for (i = 0; +       i < x; +       i++) EMPTY(i); // no-warning + +  int arr[3] = { 1, 2, 3 }; +  for (int j : arr) EMPTY(j); // no-warning + +  for (int j : +       arr) EMPTY(j); // no-warning + +  while (b() == 0) EMPTY(i); // no-warning + +  while (b() == 0 || +         c() == 0) EMPTY(i); // no-warning + +  switch (x) { +    switch (y) +      EMPTY(i); // no-warning +  } +} + +void test4(int x) +{ +  // Idiom used in some metaprogramming constructs. +  switch (x) default:; // no-warning + +  // Frequent idiom used in macros. +  do {} while (false); // no-warning +} + +/// There should be no warning for a common for/while idiom when it is obvious +/// from indentation that next statement wasn't meant to be a body. +void test5(int x, int y) { +  int i; +  for (i = 0; i < x; i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    a(i); + +  for (i = 0; i < x; i++); // no-warning +  a(i); + +  for (i = 0; +       i < x; +       i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    a(i); + +  for (i = 0; +       i < x; +       i++); // no-warning +  a(i); + +  while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    a(i); + +  while (b() == 0); // no-warning +  a(i); + +  while (b() == 0 || +         c() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    a(i); + +  while (b() == 0 || +         c() == 0); // no-warning +  a(i); +} + +/// There should be no warning for a statement with a non-null body. +void test6(int x, int y) { +  if (x) {} // no-warning + +  if (x) +    a(x); // no-warning + +  int i; +  for (i = 0; i < x; i++) // no-warning +    a(i); // no-warning + +  for (i = 0; i < x; i++) { // no-warning +    a(i); // no-warning +  } + +  for (i = 0; +       i < x; +       i++) // no-warning +    a(i); // no-warning + +  int arr[3] = { 1, 2, 3 }; +  for (int j : arr) // no-warning +    a(j); + +  for (int j : arr) {} // no-warning + +  while (b() == 0) // no-warning +    a(i); // no-warning + +  while (b() == 0) {} // no-warning + +  switch(x) // no-warning +  { +    switch(y) // no-warning +    { +      case 0: +        a(10); +        break; +      default: +        a(20); +        break; +    } +  } +} + +void test_errors(int x) { +  if (1) +    aa; // expected-error{{use of undeclared identifier}} +        // no empty body warning. + +  int i; +  for (i = 0; i < x; i++) +    bb; // expected-error{{use of undeclared identifier}} + +  int arr[3] = { 1, 2, 3 }; +  for (int j : arr) +    cc; // expected-error{{use of undeclared identifier}} + +  while (b() == 0) +    dd; // expected-error{{use of undeclared identifier}} +} + +// Warnings for statements in templates shouldn't be duplicated for all +// instantiations. +template <typename T> +void test_template(int x) { +  if (x); // expected-warning{{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + +  if (x) +    EMPTY(x); // no-warning + +  int arr[3] = { 1, 2, 3 }; +  for (int j : arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + +  while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} +    a(x); +} + +void test_template_inst(int x) { +  test_template<int>(x); +  test_template<double>(x); +} + diff --git a/clang/test/SemaCXX/warn-enum-compare.cpp b/clang/test/SemaCXX/warn-enum-compare.cpp new file mode 100644 index 0000000..52639e7 --- /dev/null +++ b/clang/test/SemaCXX/warn-enum-compare.cpp @@ -0,0 +1,212 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify + +enum Foo { FooA, FooB, FooC }; +enum Bar { BarD, BarE, BarF }; +enum { AnonAA = 42, AnonAB = 43 }; +enum { AnonBA = 44, AnonBB = 45 }; + +namespace name1 { +  enum Foo {F1, F2, F3}; +  enum Baz {B1, B2, B3}; +} + +namespace name2 { +  enum Baz {B1, B2, B3}; +} + +using name1::Baz; +using name1::B1; +using name2::B2; +typedef name1::Foo oneFoo; +typedef name1::Foo twoFoo; +Foo getFoo(); +Bar getBar(); + +void test () { +  Foo x = FooA; +  Bar y = BarD; +  Baz z = name1::B3; +  name1::Foo a; +  oneFoo b; +  twoFoo c; + +  while (x == FooA); +  while (y == BarD); +  while (a == name1::F1); +  while (z == name1::B2); +  while (a == b); +  while (a == c); +  while (b == c); +  while (B1 == name1::B2); +  while (B2 == name2::B1); +  while (x == AnonAA); +  while (AnonBB == y); +  while (AnonAA == AnonAB); +  while (AnonAB == AnonBA); +  while (AnonBB == AnonAA); + +  while ((x) == FooA); +  while ((y) == BarD); +  while ((a) == name1::F1); +  while (z == (name1::B2)); +  while (a == (b)); +  while (a == (c)); +  while ((b) == (c)); +  while ((B1) == (name1::B2)); +  while ((B2) == (name2::B1)); + +  while (((x)) == FooA); +  while ((y) == (BarD)); +  while ((a) == (name1::F1)); +  while (z == (name1::B2)); +  while ((a) == ((((b))))); +  while (((a)) == (c)); +  while ((b) == (((c)))); +  while ((((((B1))))) == (((name1::B2)))); +  while (B2 == ((((((name2::B1))))))); + +  while (B1 == B2); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} +  while (name1::B2 == name2::B3); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} +  while (z == name2::B2); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} + +  while (((((B1)))) == B2); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} +  while (name1::B2 == (name2::B3)); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} +  while (z == ((((name2::B2))))); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} + +  while ((((B1))) == (((B2)))); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} +  while ((name1::B2) == (((name2::B3)))); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} +  while ((((z))) == (name2::B2)); // expected-warning  {{comparison of two values with different enumeration types ('name1::Baz' and 'name2::Baz')}} + +  while (x == a); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'name1::Foo')}} +  while (x == b); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'oneFoo' (aka 'name1::Foo'))}} +  while (x == c); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'twoFoo' (aka 'name1::Foo'))}} + +  while (x == y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x != y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x >= y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x <= y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x > y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x < y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (FooB == y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB != y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB >= y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB <= y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB > y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB < y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (FooB == BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB != BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB >= BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB <= BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB > BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB < BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (x == BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x != BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x >= BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x <= BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x > BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x < BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (getFoo() == y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() != y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() >= y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() <= y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() > y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() < y); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (getFoo() == BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() != BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() >= BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() <= BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() > BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() < BarD); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (getFoo() == getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() != getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() >= getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() <= getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() > getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (getFoo() < getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (FooB == getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB != getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB >= getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB <= getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB > getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (FooB < getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + +  while (x == getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x != getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x >= getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x <= getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x > getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} +  while (x < getBar()); // expected-warning  {{comparison of two values with different enumeration types ('Foo' and 'Bar')}} + + + +  while (y == x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y != x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y >= x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y <= x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y > x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y < x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (y == FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y != FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y >= FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y <= FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y > FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y < FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (BarD == FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD != FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD >= FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD <= FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD > FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD <FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (BarD == x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD != x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD >= x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD <= x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD < x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD > x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (y == getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y != getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y >= getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y <= getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y > getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (y < getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (BarD == getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD != getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD >= getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD <= getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD > getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (BarD < getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (getBar() == getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() != getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() >= getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() <= getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() > getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() < getFoo()); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (getBar() == FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() != FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() >= FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() <= FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() > FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() < FooB); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +  while (getBar() == x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() != x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() >= x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() <= x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() > x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} +  while (getBar() < x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}} + +} diff --git a/clang/test/SemaCXX/warn-everthing.cpp b/clang/test/SemaCXX/warn-everthing.cpp new file mode 100644 index 0000000..ad3dd8a --- /dev/null +++ b/clang/test/SemaCXX/warn-everthing.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -Weverything -fsyntax-only %s -verify + +// This previously crashed due to a bug in the CFG.  Exercising all +// warnings helps check CFG construction. +class PR12271 { +public: +  PR12271(); +  ~PR12271(); +}; + +void testPR12271() { // expected-warning {{no previous prototype for function 'testPR12271'}} +  PR12271 a[1][1]; // expected-warning {{unused variable 'a'}} +} diff --git a/clang/test/SemaCXX/warn-exit-time-destructors.cpp b/clang/test/SemaCXX/warn-exit-time-destructors.cpp new file mode 100644 index 0000000..f49134b --- /dev/null +++ b/clang/test/SemaCXX/warn-exit-time-destructors.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -Wexit-time-destructors %s -verify + +namespace test1 { +  struct A { ~A(); }; +  A a; // expected-warning {{declaration requires an exit-time destructor}} +  A b[10]; // expected-warning {{declaration requires an exit-time destructor}} +  A c[10][10]; // expected-warning {{declaration requires an exit-time destructor}} + +  A &d = a; +  A &e = b[5]; +  A &f = c[5][7]; +} + +namespace test2 { +void f() { +  struct A { ~A() { } }; +   +  static A a; // expected-warning {{declaration requires an exit-time destructor}} +  static A b[10]; // expected-warning {{declaration requires an exit-time destructor}} +  static A c[10][10]; // expected-warning {{declaration requires an exit-time destructor}} + +  static A &d = a; +  static A &e = b[5]; +  static A &f = c[5][7]; +} + +} diff --git a/clang/test/SemaCXX/warn-func-as-bool.cpp b/clang/test/SemaCXX/warn-func-as-bool.cpp new file mode 100644 index 0000000..b5df744 --- /dev/null +++ b/clang/test/SemaCXX/warn-func-as-bool.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -x c++ -verify -fsyntax-only %s + +void f1(); + +struct S { +  static void f2(); +}; + +extern void f3() __attribute__((weak_import)); + +struct S2 { +  static void f4() __attribute__((weak_import)); +}; + +bool f5(); +bool f6(int); + +void bar() { +  bool b; + +  b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ +             expected-note {{prefix with the address-of operator to silence this warning}} +  if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ +                expected-note {{prefix with the address-of operator to silence this warning}} +  b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ +                expected-note {{prefix with the address-of operator to silence this warning}} +  if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ +                   expected-note {{prefix with the address-of operator to silence this warning}} +  b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \ +             expected-note {{prefix with the address-of operator to silence this warning}} \ +             expected-note {{suffix with parentheses to turn this into a function call}} +  b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \ +             expected-note {{prefix with the address-of operator to silence this warning}} + +  // implicit casts of weakly imported symbols are ok: +  b = f3; +  if (f3) {} +  b = S2::f4; +  if (S2::f4) {} +} diff --git a/clang/test/SemaCXX/warn-global-constructors.cpp b/clang/test/SemaCXX/warn-global-constructors.cpp new file mode 100644 index 0000000..6330958 --- /dev/null +++ b/clang/test/SemaCXX/warn-global-constructors.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -fsyntax-only -Wglobal-constructors %s -verify + +int opaque_int(); + +namespace test0 { +  // These should never require global constructors. +  int a; +  int b = 20; +  float c = 5.0f; + +  // This global constructor is avoidable based on initialization order. +  int d = b; // expected-warning {{global constructor}} + +  // These global constructors are unavoidable. +  int e = opaque_int(); // expected-warning {{global constructor}} +  int f = b; // expected-warning {{global constructor}} +} + +namespace test1 { +  struct A { int x; }; +  A a; +  A b = A(); +  A c = { 10 }; +  A d = { opaque_int() }; // expected-warning {{global constructor}} +  A e = A(A()); +  A f = A(a); // expected-warning {{global constructor}} +  A g(a); // expected-warning {{global constructor}} +  A h((A()));  // elided +  A i((A(A()))); // elided +} + +namespace test2 { +  struct A { A(); }; +  A a; // expected-warning {{global constructor}} +  A b[10]; // expected-warning {{global constructor}} +  A c[10][10]; // expected-warning {{global constructor}} + +  A &d = a; +  A &e = b[5]; +  A &f = c[5][7]; +} + +namespace test3 { +  struct A { ~A(); }; +  A a; // expected-warning {{global destructor}} +  A b[10]; // expected-warning {{global destructor}} +  A c[10][10]; // expected-warning {{global destructor}} + +  A &d = a; +  A &e = b[5]; +  A &f = c[5][7]; +} + +namespace test4 { +  char a[] = "hello"; +  char b[6] = "hello"; +  char c[][6] = { "hello" }; +} + +namespace test5 { +  struct A { A(); }; + +  void f1() { +    static A a; +  } +  void f2() { +    static A& a = *new A; +  } +} + +namespace test6 { +  struct A { ~A(); }; + +  void f1() { +    static A a; +  } +  void f2() { +    static A& a = *new A; +  } +} + +namespace pr8095 { +  struct Foo { +    int x; +    Foo(int x1) : x(x1) {} +  }; +  void foo() { +    static Foo a(0); +  } + +  struct Bar { +    ~Bar(); +  }; +  void bar() { +    static Bar b; +  } +} diff --git a/clang/test/SemaCXX/warn-large-by-value-copy.cpp b/clang/test/SemaCXX/warn-large-by-value-copy.cpp new file mode 100644 index 0000000..3e419ec --- /dev/null +++ b/clang/test/SemaCXX/warn-large-by-value-copy.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wlarge-by-value-copy=100 %s + +// rdar://8548050 +namespace rdar8548050 { + +struct S100 { +    char x[100]; +}; + +struct S101 { +    char x[101]; +}; + +S100 f100(S100 s) { return s; } + +S101 f101(S101 s) { return s; } // expected-warning {{return value of 'f101' is a large (101 bytes) pass-by-value object}} \ +                                // expected-warning {{'s' is a large (101 bytes) pass-by-value argument}} + +typedef int Arr[200]; +void farr(Arr a) { } + +struct NonPOD { +  char x[200]; +  virtual void m(); +}; + +NonPOD fNonPOD(NonPOD s) { return s; } + +template <unsigned size> +struct TS { +    char x[size]; +}; + +template <unsigned size> +void tf(TS<size> ts) {} // expected-warning {{ts' is a large (300 bytes) pass-by-value argument}} + +void g() { +    TS<300> ts; +    tf<300>(ts); // expected-note {{instantiation}} +} + +} + +template<typename T> class DependentPOD { +  enum b { x }; +  b foo() { return x; } +}; diff --git a/clang/test/SemaCXX/warn-literal-conversion.cpp b/clang/test/SemaCXX/warn-literal-conversion.cpp new file mode 100644 index 0000000..5fcae5d --- /dev/null +++ b/clang/test/SemaCXX/warn-literal-conversion.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -Wliteral-conversion -verify %s + +void foo(int y); + +// Warn when a literal float or double is assigned or bound to an integer. +void test0() { +  // Float +  int y0 = 1.2222F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y1 = (1.2222F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y3 = 12E-1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y4 = 1.23E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  // Double +  int y5 = 1.2222; // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y6 = 12E-1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y7 = 1.23E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} +  int y8 = (1.23E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + +  // Test assignment to an existing variable. +  y8 = 2.22F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + +  // Test direct initialization. +  int y9(1.23F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + +  // Test passing a literal floating-point value to a function that takes an integer. +  foo(1.2F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + +  int y10 = -1.2F;  // expected-warning {{implicit conversion turns literal floating-point number into integer}} + +  // -Wconversion-literal does NOT catch const values. +  // (-Wconversion DOES catch them.) +  static const float sales_tax_rate = .095F; +  int z = sales_tax_rate; +  foo(sales_tax_rate); + +  // Expressions, such as those that indicate rounding-down, should NOT produce warnings. +  int x = 24 * 0.5; +  int y = (24*60*60) * 0.25; +  int pennies = 123.45 * 100; +} diff --git a/clang/test/SemaCXX/warn-memset-bad-sizeof.cpp b/clang/test/SemaCXX/warn-memset-bad-sizeof.cpp new file mode 100644 index 0000000..e0d28da --- /dev/null +++ b/clang/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -0,0 +1,145 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-sizeof-array-argument %s +// +extern "C" void *memset(void *, int, unsigned); +extern "C" void *memmove(void *s1, const void *s2, unsigned n); +extern "C" void *memcpy(void *s1, const void *s2, unsigned n); +extern "C" void *memcmp(void *s1, const void *s2, unsigned n); + +struct S {int a, b, c, d;}; +typedef S* PS; + +struct Foo {}; +typedef const Foo& CFooRef; +typedef const Foo CFoo; +typedef volatile Foo VFoo; +typedef const volatile Foo CVFoo; + +typedef double Mat[4][4]; + +template <class Dest, class Source> +inline Dest bit_cast(const Source& source) { +  Dest dest; +  memcpy(&dest, &source, sizeof(dest)); +  return dest; +} + +// http://www.lysator.liu.se/c/c-faq/c-2.html#2-6 +void f(Mat m, const Foo& const_foo, char *buffer) { +  S s; +  S* ps = &s; +  PS ps2 = &s; +  char arr[5]; +  char* parr[5]; +  Foo foo; +  char* heap_buffer = new char[42]; + +  /* Should warn */ +  memset(&s, 0, sizeof(&s));  // \ +      // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} +  memset(ps, 0, sizeof(ps));  // \ +      // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} +  memset(ps2, 0, sizeof(ps2));  // \ +      // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} +  memset(ps2, 0, sizeof(typeof(ps2)));  // \ +      // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} +  memset(ps2, 0, sizeof(PS));  // \ +      // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} +  memset(heap_buffer, 0, sizeof(heap_buffer));  // \ +      // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + +  memcpy(&s, 0, sizeof(&s));  // \ +      // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the destination}} +  memcpy(0, &s, sizeof(&s));  // \ +      // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the source}} + +  memmove(ps, 0, sizeof(ps));  // \ +      // expected-warning {{argument to 'sizeof' in 'memmove' call is the same expression as the destination}} +  memcmp(ps, 0, sizeof(ps));  // \ +      // expected-warning {{argument to 'sizeof' in 'memcmp' call is the same expression as the destination}} + +  /* Shouldn't warn */ +  memset((void*)&s, 0, sizeof(&s)); +  memset(&s, 0, sizeof(s)); +  memset(&s, 0, sizeof(S)); +  memset(&s, 0, sizeof(const S)); +  memset(&s, 0, sizeof(volatile S)); +  memset(&s, 0, sizeof(volatile const S)); +  memset(&foo, 0, sizeof(CFoo)); +  memset(&foo, 0, sizeof(VFoo)); +  memset(&foo, 0, sizeof(CVFoo)); +  memset(ps, 0, sizeof(*ps)); +  memset(ps2, 0, sizeof(*ps2)); +  memset(ps2, 0, sizeof(typeof(*ps2))); +  memset(arr, 0, sizeof(arr)); +  memset(parr, 0, sizeof(parr)); + +  memcpy(&foo, &const_foo, sizeof(Foo)); +  memcpy((void*)&s, 0, sizeof(&s)); +  memcpy(0, (void*)&s, sizeof(&s)); +  char *cptr; +  memcpy(&cptr, buffer, sizeof(cptr)); +  memcpy((char*)&cptr, buffer, sizeof(cptr)); + +  CFooRef cfoo = foo; +  memcpy(&foo, &cfoo, sizeof(Foo)); + +  memcpy(0, &arr, sizeof(arr)); +  typedef char Buff[8]; +  memcpy(0, &arr, sizeof(Buff)); + +  unsigned char* puc; +  bit_cast<char*>(puc); + +  float* pf; +  bit_cast<int*>(pf); + +  int iarr[14]; +  memset(&iarr[0], 0, sizeof iarr); + +  int* iparr[14]; +  memset(&iparr[0], 0, sizeof iparr); + +  memset(m, 0, sizeof(Mat)); + +  // Copy to raw buffer shouldn't warn either +  memcpy(&foo, &arr, sizeof(Foo)); +  memcpy(&arr, &foo, sizeof(Foo)); + +  // Shouldn't warn, and shouldn't crash either. +  memset(({ +    if (0) {} +    while (0) {} +    for (;;) {} +    &s; +  }), 0, sizeof(s)); +} + +namespace ns { +void memset(void* s, char c, int n); +void f(int* i) { +  memset(i, 0, sizeof(i)); +} +} + +extern "C" int strncmp(const char *s1, const char *s2, unsigned n); +extern "C" int strncasecmp(const char *s1, const char *s2, unsigned n); +extern "C" char *strncpy(char *det, const char *src, unsigned n); +extern "C" char *strncat(char *dst, const char *src, unsigned n); +extern "C" char *strndup(const  char *src, unsigned n); + +void strcpy_and_friends() { +  const char* FOO = "<- should be an array instead"; +  const char* BAR = "<- this, too"; + +  strncmp(FOO, BAR, sizeof(FOO)); // \ +      // expected-warning {{argument to 'sizeof' in 'strncmp' call is the same expression as the destination}} +  strncasecmp(FOO, BAR, sizeof(FOO));  // \ +      // expected-warning {{argument to 'sizeof' in 'strncasecmp' call is the same expression as the destination}} + +  char buff[80]; + +  strncpy(buff, BAR, sizeof(BAR)); // \ +      // expected-warning {{argument to 'sizeof' in 'strncpy' call is the same expression as the source}} +  strndup(FOO, sizeof(FOO)); // \ +      // expected-warning {{argument to 'sizeof' in 'strndup' call is the same expression as the source}} +} diff --git a/clang/test/SemaCXX/warn-missing-noreturn.cpp b/clang/test/SemaCXX/warn-missing-noreturn.cpp new file mode 100644 index 0000000..8072ac6 --- /dev/null +++ b/clang/test/SemaCXX/warn-missing-noreturn.cpp @@ -0,0 +1,125 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -Wmissing-noreturn -Wreturn-type +void f() __attribute__((noreturn)); + +template<typename T> void g(T) { +  f(); +} + +template void g<int>(int); + +template<typename T> struct A { +  void g() { +    f(); +  } +}; + +template struct A<int>; + +struct B { +  template<typename T> void g(T) { +    f(); +  } +}; + +template void B::g<int>(int); + +// We don't want a warning here. +struct X { +  virtual void g() { f(); } +}; + +namespace test1 { +  bool condition(); + +  // We don't want a warning here. +  void foo() { +    while (condition()) {} +  } +} + + +// <rdar://problem/7880658> - This test case previously had a false "missing return" +// warning. +struct R7880658 { +  R7880658 &operator++(); +  bool operator==(const R7880658 &) const; +  bool operator!=(const R7880658 &) const; +}; + +void f_R7880658(R7880658 f, R7880658 l) {  // no-warning +  for (; f != l; ++f) { +  } +} + +namespace test2 { + +  bool g(); +  void *h() __attribute__((noreturn)); +  void *j(); + +  struct A { +    void *f; + +    A() : f(0) { } +    A(int) : f(h()) { } // expected-warning {{function 'A' could be declared with attribute 'noreturn'}} +    A(char) : f(j()) { } +    A(bool b) : f(b ? h() : j()) { } +  }; +} + +namespace test3 { +  struct A { +    ~A(); +  }; + +  struct B { +    ~B() { } + +    A a; +  }; + +  struct C : A {  +    ~C() { } +  }; +} + +// <rdar://problem/8875247> - Properly handle CFGs with destructors. +struct rdar8875247 { +  ~rdar8875247 (); +}; +void rdar8875247_aux(); + +int rdar8875247_test() { +  rdar8875247 f; +} // expected-warning{{control reaches end of non-void function}} + +struct rdar8875247_B { +  rdar8875247_B(); +  ~rdar8875247_B(); +}; + +rdar8875247_B test_rdar8875247_B() { +  rdar8875247_B f; +  return f; +} // no-warning + +namespace PR10801 { +  struct Foo { +    void wibble() __attribute((__noreturn__)); +  }; + +  struct Bar { +    void wibble(); +  }; + +  template <typename T> void thingy(T thing) { +    thing.wibble(); +  } + +  void test() { +    Foo f; +    Bar b; +    thingy(f); +    thingy(b); +  } +} diff --git a/clang/test/SemaCXX/warn-missing-prototypes.cpp b/clang/test/SemaCXX/warn-missing-prototypes.cpp new file mode 100644 index 0000000..f7e8db3 --- /dev/null +++ b/clang/test/SemaCXX/warn-missing-prototypes.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-prototypes %s + +void f() { } // expected-warning {{no previous prototype for function 'f'}} + +namespace NS { +  void f() { } // expected-warning {{no previous prototype for function 'f'}} +} + +namespace { +  // Don't warn about functions in anonymous namespaces. +  void f() { } +} + +struct A { +  // Don't warn about member functions. +  void f() { } +}; + +// Don't warn about inline functions. +inline void g() { } + +// Don't warn about function templates. +template<typename> void h() { } + +// Don't warn when instantiating function templates. +template void h<int>(); + +// PR9519: don't warn about friend functions. +class I { +  friend void I_friend() {} +}; + diff --git a/clang/test/SemaCXX/warn-new-overaligned-2.cpp b/clang/test/SemaCXX/warn-new-overaligned-2.cpp new file mode 100644 index 0000000..5505009 --- /dev/null +++ b/clang/test/SemaCXX/warn-new-overaligned-2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned -verify %s + +// This test verifies that we don't warn when the global operator new is +// overridden. That's why we can't merge this with the other test file. + +void* operator new(unsigned long); +void* operator new[](unsigned long); + +struct Test { +  template <typename T> +  struct SeparateCacheLines { +    T data; +  } __attribute__((aligned(256))); + +  SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { +  Test t; +  new Test; +  new Test[10]; +} diff --git a/clang/test/SemaCXX/warn-new-overaligned-3.cpp b/clang/test/SemaCXX/warn-new-overaligned-3.cpp new file mode 100644 index 0000000..c9a57fb --- /dev/null +++ b/clang/test/SemaCXX/warn-new-overaligned-3.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned %s -isystem %S/Inputs -verify + +// This test ensures that we still get the warning even if we #include <new> +// where the header here simulates <new>. +#include <warn-new-overaligned-3.h> + +namespace test1 { +struct Test { +  template <typename T> +  struct SeparateCacheLines { +    T data; +  } __attribute__((aligned(256))); + +  SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { +  Test t; +  new Test;  // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +  new Test[10];  // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test2 { +struct helper { int i __attribute__((aligned(256))); }; + +struct Placement { +  Placement() { +    new (d) helper(); +  } +  helper *d; +}; +} diff --git a/clang/test/SemaCXX/warn-new-overaligned.cpp b/clang/test/SemaCXX/warn-new-overaligned.cpp new file mode 100644 index 0000000..42a4e35 --- /dev/null +++ b/clang/test/SemaCXX/warn-new-overaligned.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned -verify %s + +namespace test1 { +struct Test { +  template <typename T> +  struct SeparateCacheLines { +    T data; +  } __attribute__((aligned(256))); + +  SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { +  Test t; +  new Test;  // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +  new Test[10];  // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test2 { +class Test { +  typedef int __attribute__((aligned(256))) aligned_int; +  aligned_int high_contention_data[10]; +}; + +void helper() { +  Test t; +  new Test;  // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +  new Test[10];  // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test3 { +struct Test { +  template <typename T> +  struct SeparateCacheLines { +    T data; +  } __attribute__((aligned(256))); + +  void* operator new(unsigned long) { +    return 0; +  } + +  SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { +  Test t; +  new Test; +  new Test[10];  // expected-warning {{type 'test3::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test4 { +struct Test { +  template <typename T> +  struct SeparateCacheLines { +    T data; +  } __attribute__((aligned(256))); + +  void* operator new[](unsigned long) { +    return 0; +  } + +  SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { +  Test t; +  new Test;  // expected-warning {{type 'test4::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +  new Test[10]; +} +} diff --git a/clang/test/SemaCXX/warn-overloaded-virtual.cpp b/clang/test/SemaCXX/warn-overloaded-virtual.cpp new file mode 100644 index 0000000..8e2b671 --- /dev/null +++ b/clang/test/SemaCXX/warn-overloaded-virtual.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -fsyntax-only -Woverloaded-virtual -verify %s + +struct B1 { +  virtual void foo(int); // expected-note {{declared here}} +  virtual void foo(); // expected-note {{declared here}} +}; + +struct S1 : public B1 { +  void foo(float); // expected-warning {{hides overloaded virtual functions}} +}; + +struct S2 : public B1 { +  void foo(); // expected-note {{declared here}} +}; + +struct B2 { +  virtual void foo(void*); // expected-note {{declared here}} +}; + +struct MS1 : public S2, public B2 { +   virtual void foo(int); // expected-warning {{hides overloaded virtual functions}} +}; + +struct B3 { +  virtual void foo(int); +  virtual void foo(); +}; + +struct S3 : public B3 { +  using B3::foo; +  void foo(float); +}; + +struct B4 { +  virtual void foo(); +}; + +struct S4 : public B4 { +  void foo(float); +  void foo(); +}; + +namespace PR9182 { +struct Base { +  virtual void foo(int); +}; + +void Base::foo(int) { } + +struct Derived : public Base { +  virtual void foo(int);    +  void foo(int, int);    +}; +} + +namespace PR9396 { +class A { +public: +  virtual void f(int) {} +}; + +class B : public A { +public: +  static void f() {} +}; +} diff --git a/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp b/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp new file mode 100644 index 0000000..ade6198 --- /dev/null +++ b/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +struct A { +  A() { f(); } // expected-warning {{call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the constructor of 'A'}} +  ~A() { f(); } // expected-warning {{call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the destructor of 'A'}} + +  virtual void f() = 0; // expected-note 2 {{'f' declared here}} +}; + +// Don't warn (or note) when calling the function on a pointer. (PR10195) +struct B { +  A *a; +  B() { a->f(); }; +  ~B() { a->f(); }; +}; diff --git a/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp b/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp new file mode 100644 index 0000000..8c254e5 --- /dev/null +++ b/clang/test/SemaCXX/warn-reorder-ctor-initialization.cpp @@ -0,0 +1,132 @@ +// RUN: %clang_cc1  -fsyntax-only -Wreorder -verify %s + +struct BB {}; + +struct BB1 {}; + +class complex : public BB, BB1 {  +public:  +  complex() +    : s2(1), // expected-warning {{field 's2' will be initialized after field 's1'}} +      s1(1), +      s3(3), // expected-warning {{field 's3' will be initialized after base 'BB1'}}  +      BB1(), // expected-warning {{base class 'BB1' will be initialized after base 'BB'}} +      BB() +  {} +  int s1; +  int s2; +  int s3; +};  + + +// testing virtual bases. + + +struct V {  +  V(); +}; + +struct A : public virtual V {  +  A();  +}; + +struct B : public virtual V { +  B();  +}; + +struct Diamond : public A, public B { +  Diamond() : A(), B() {} +}; + + +struct C : public A, public B, private virtual V {  +  C() { } +}; + + +struct D : public A, public B {  +  D()  : A(), V() {   } // expected-warning {{base class 'A' will be initialized after base 'V'}} +}; + + +struct E : public A, public B, private virtual V {  +  E()  : A(), V() {  } // expected-warning {{base class 'A' will be initialized after base 'V'}} +}; + + +struct A1  {  +  A1();  +}; + +struct B1 { +  B1(); +}; + +struct F : public A1, public B1, private virtual V {  +  F()  : A1(), V() {  } // expected-warning {{base class 'A1' will be initialized after base 'V'}} +}; + +struct X : public virtual A, virtual V, public virtual B { +  X(): A(), V(), B() {} // expected-warning {{base class 'A' will be initialized after base 'V'}} +}; + +class Anon { +  int c; union {int a,b;}; int d; +  Anon() : c(10), b(1), d(2) {} +}; +class Anon2 { +  int c; union {int a,b;}; int d; +  Anon2() : c(2), +            d(10), // expected-warning {{field 'd' will be initialized after field 'b'}} +            b(1) {} +}; +class Anon3 { +  union {int a,b;}; +  Anon3() : b(1) {} +}; + +namespace T1 { + +struct S1 { }; +struct S2: virtual S1 { }; +struct S3 { }; + +struct S4: virtual S3, S2 { +  S4() : S2(), // expected-warning {{base class 'T1::S2' will be initialized after base 'T1::S3'}} +    S3() { }; +}; +} + +namespace test2 { +  struct Foo { Foo(); }; +  class A { +    template <class T> A(T *t) : +      y(),  // expected-warning {{field 'y' will be initialized after field 'x'}} +      x() +    {} +    Foo x; +    Foo y; +  }; +} + +// PR6575: this should not crash +namespace test3 { +  struct MyClass { +    MyClass() : m_int(0) {} +    union { +      struct { +        int m_int; +      }; +    }; +  }; +} + +namespace PR7179 { +  struct X +  { +    struct Y +    { +      template <class T> Y(T x) : X(x) { } +    }; +  }; +} diff --git a/clang/test/SemaCXX/warn-self-assign.cpp b/clang/test/SemaCXX/warn-self-assign.cpp new file mode 100644 index 0000000..fcdb2ab --- /dev/null +++ b/clang/test/SemaCXX/warn-self-assign.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -Wself-assign -verify %s + +void f() { +  int a = 42, b = 42; +  a = a; // expected-warning{{explicitly assigning}} +  b = b; // expected-warning{{explicitly assigning}} +  a = b; +  b = a = b; +  a = a = a; // expected-warning{{explicitly assigning}} +  a = b = b = a; +} + +// Dummy type. +struct S {}; + +void false_positives() { +#define OP = +#define LHS a +#define RHS a +  int a = 42; +  // These shouldn't warn due to the use of the preprocessor. +  a OP a; +  LHS = a; +  a = RHS; +  LHS OP RHS; +#undef OP +#undef LHS +#undef RHS + +  S s; +  s = s; // Not a builtin assignment operator, no warning. + +  // Volatile stores aren't side-effect free. +  volatile int vol_a; +  vol_a = vol_a; +  volatile int &vol_a_ref = vol_a; +  vol_a_ref = vol_a_ref; +} + +template <typename T> void g() { +  T a; +  a = a; // May or may not be a builtin assignment operator, no warning. +} +void instantiate() { +  g<int>(); +  g<S>(); +} diff --git a/clang/test/SemaCXX/warn-self-comparisons.cpp b/clang/test/SemaCXX/warn-self-comparisons.cpp new file mode 100644 index 0000000..620be19 --- /dev/null +++ b/clang/test/SemaCXX/warn-self-comparisons.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f(int (&array1)[2], int (&array2)[2]) { +  if (array1 == array2) { } // no warning +} diff --git a/clang/test/SemaCXX/warn-shadow.cpp b/clang/test/SemaCXX/warn-shadow.cpp new file mode 100644 index 0000000..68e9467 --- /dev/null +++ b/clang/test/SemaCXX/warn-shadow.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wshadow %s + +namespace { +  int i; // expected-note {{previous declaration is here}} +} + +namespace one { +namespace two { +  int j; // expected-note {{previous declaration is here}} +} +} + +namespace xx { +  int m; +} +namespace yy { +  int m; +} + +using namespace one::two; +using namespace xx; +using namespace yy; + +void foo() { +  int i; // expected-warning {{declaration shadows a variable in namespace '<anonymous>'}} +  int j; // expected-warning {{declaration shadows a variable in namespace 'one::two'}} +  int m; +} + +class A { +  static int data; // expected-note {{previous declaration}} +  int field; // expected-note {{previous declaration}} + +  void test() { +    char *field; // expected-warning {{declaration shadows a field of 'A'}} +    char *data; // expected-warning {{declaration shadows a static data member of 'A'}} +  } +}; + +// TODO: this should warn, <rdar://problem/5018057> +class B : A { +  int data; +  static int field; +}; + +// rdar://8900456 +namespace rdar8900456 { +struct Foo { +  static void Baz(); +private: +  int Bar; +}; + +void Foo::Baz() { +  double Bar = 12; // Don't warn. +} +} + +// http://llvm.org/PR9160 +namespace PR9160 { +struct V { +  V(int); +}; +struct S { +  V v; +  static void m() { +    if (1) { +      V v(0); +    } +  } +}; +} + +extern int bob; // expected-note {{previous declaration is here}} + +// rdar://8883302 +void rdar8883302() { +  extern int bob; // don't warn for shadowing. +} + +void test8() { +  int bob; // expected-warning {{declaration shadows a variable in the global namespace}} +} diff --git a/clang/test/SemaCXX/warn-sign-conversion.cpp b/clang/test/SemaCXX/warn-sign-conversion.cpp new file mode 100644 index 0000000..ba2bc9b --- /dev/null +++ b/clang/test/SemaCXX/warn-sign-conversion.cpp @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wsign-conversion %s + +// NOTE: When a 'enumeral mismatch' warning is implemented then expect several +// of the following cases to be impacted. + +// namespace for anonymous enums tests +namespace test1 { +  enum { A }; +  enum { B = -1 }; + +  template <typename T> struct Foo { +    enum { C }; +    enum { D = ~0U }; +  }; + +  enum { E = ~0U }; + +  void doit_anonymous( int i ) { +    int a1 = 1 ? i : A; +    int a2 = 1 ? A : i; + +    int b1 = 1 ? i : B; +    int b2 = 1 ? B : i; + +    int c1 = 1 ? i : Foo<bool>::C; +    int c2 = 1 ? Foo<bool>::C : i; + +    int d1a = 1 ? i : Foo<bool>::D; // expected-warning {{test1::Foo<bool>::<anonymous enum at }} +    int d1b = 1 ? i : Foo<bool>::D; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} +    int d2a = 1 ? Foo<bool>::D : i; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::<anonymous enum at }} +    int d2b = 1 ? Foo<bool>::D : i; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} +    int d3a = 1 ? B : Foo<bool>::D; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::<anonymous enum at }} +    int d3b = 1 ? B : Foo<bool>::D; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} +    int d4a = 1 ? Foo<bool>::D : B; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::<anonymous enum at }} +    int d4b = 1 ? Foo<bool>::D : B; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} + +    int e1a = 1 ? i : E; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} +    int e1b = 1 ? i : E; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} +    int e2a = 1 ? E : i; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} +    int e2b = 1 ? E : i; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} +    int e3a = 1 ? E : B; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} +    int e3b = 1 ? E : B; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} +    int e4a = 1 ? B : E; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} +    int e4b = 1 ? B : E; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} +  } +} + +// namespace for named enums tests +namespace test2 { +  enum Named1 { A }; +  enum Named2 { B = -1 }; + +  template <typename T> struct Foo { +    enum Named3 { C }; +    enum Named4 { D = ~0U }; +  }; + +  enum Named5 { E = ~0U }; + +  void doit_anonymous( int i ) { +    int a1 = 1 ? i : A; +    int a2 = 1 ? A : i; + +    int b1 = 1 ? i : B; +    int b2 = 1 ? B : i; + +    int c1 = 1 ? i : Foo<bool>::C; +    int c2 = 1 ? Foo<bool>::C : i; + +    int d1 = 1 ? i : Foo<bool>::D; // expected-warning {{operand of ? changes signedness: 'test2::Foo<bool>::Named4' to 'int'}} +    int d2 = 1 ? Foo<bool>::D : i; // expected-warning {{operand of ? changes signedness: 'test2::Foo<bool>::Named4' to 'int'}} +    int d3 = 1 ? B : Foo<bool>::D; // expected-warning {{operand of ? changes signedness: 'test2::Foo<bool>::Named4' to 'int'}} +    int d4 = 1 ? Foo<bool>::D : B; // expected-warning {{operand of ? changes signedness: 'test2::Foo<bool>::Named4' to 'int'}} + +    int e1 = 1 ? i : E; // expected-warning {{operand of ? changes signedness: 'test2::Named5' to 'int'}} +    int e2 = 1 ? E : i; // expected-warning {{operand of ? changes signedness: 'test2::Named5' to 'int'}} +    int e3 = 1 ? E : B; // expected-warning {{operand of ? changes signedness: 'test2::Named5' to 'int'}} +    int e4 = 1 ? B : E; // expected-warning {{operand of ? changes signedness: 'test2::Named5' to 'int'}} +  } +} diff --git a/clang/test/SemaCXX/warn-string-conversion.cpp b/clang/test/SemaCXX/warn-string-conversion.cpp new file mode 100644 index 0000000..23960e4 --- /dev/null +++ b/clang/test/SemaCXX/warn-string-conversion.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -Wstring-conversion -verify %s + +// Warn on cases where a string literal is converted into a bool. +// An exception is made for this in logical operators. +void assert(bool condition); +void test0() { +  bool b0 = "hi"; // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} +  b0 = ""; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}} +  b0 = 0 && ""; +  assert("error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}} +  assert(0 && "error"); + +  while("hi") {} // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} +  do {} while("hi"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} +  for (;"hi";); // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} +  if("hi") {} // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} +} + diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp new file mode 100644 index 0000000..566e5c1 --- /dev/null +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -0,0 +1,2243 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s + +#define LOCKABLE            __attribute__ ((lockable)) +#define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable)) +#define GUARDED_BY(x)       __attribute__ ((guarded_by(x))) +#define GUARDED_VAR         __attribute__ ((guarded_var)) +#define PT_GUARDED_BY(x)    __attribute__ ((pt_guarded_by(x))) +#define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var)) +#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) +#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...)   __attribute__ ((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...)      __attribute__ ((shared_lock_function(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__))) +#define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__))) +#define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x))) +#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) \ +  __attribute__ ((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) \ +  __attribute__ ((shared_locks_required(__VA_ARGS__))) +#define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis)) + +//-----------------------------------------// +//  Helper fields +//-----------------------------------------// + + +class  __attribute__((lockable)) Mutex { + public: +  void Lock() __attribute__((exclusive_lock_function)); +  void ReaderLock() __attribute__((shared_lock_function)); +  void Unlock() __attribute__((unlock_function)); +  bool TryLock() __attribute__((exclusive_trylock_function(true))); +  bool ReaderTryLock() __attribute__((shared_trylock_function(true))); +  void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); +}; + +class __attribute__((scoped_lockable)) MutexLock { + public: +  MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); +  ~MutexLock() __attribute__((unlock_function)); +}; + +class __attribute__((scoped_lockable)) ReaderMutexLock { + public: +  ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); +  ~ReaderMutexLock() __attribute__((unlock_function)); +}; + + +Mutex sls_mu; + +Mutex sls_mu2 __attribute__((acquired_after(sls_mu))); +int sls_guard_var __attribute__((guarded_var)) = 0; +int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0; + +bool getBool(); + +class MutexWrapper { +public: +   Mutex mu; +   int x __attribute__((guarded_by(mu))); +   void MyLock() __attribute__((exclusive_lock_function(mu)));  +}; + +MutexWrapper sls_mw; + +void sls_fun_0() { +  sls_mw.mu.Lock(); +  sls_mw.x = 5;  +  sls_mw.mu.Unlock(); +} + +void sls_fun_2() { +  sls_mu.Lock(); +  int x = sls_guard_var; +  sls_mu.Unlock(); +} + +void sls_fun_3() { +  sls_mu.Lock(); +  sls_guard_var = 2; +  sls_mu.Unlock(); +} + +void sls_fun_4() { +  sls_mu2.Lock(); +  sls_guard_var = 2; +  sls_mu2.Unlock(); +} + +void sls_fun_5() { +  sls_mu.Lock(); +  int x = sls_guardby_var; +  sls_mu.Unlock(); +} + +void sls_fun_6() { +  sls_mu.Lock(); +  sls_guardby_var = 2; +  sls_mu.Unlock(); +} + +void sls_fun_7() { +  sls_mu.Lock(); +  sls_mu2.Lock(); +  sls_mu2.Unlock(); +  sls_mu.Unlock(); +} + +void sls_fun_8() { +  sls_mu.Lock(); +  if (getBool()) +    sls_mu.Unlock(); +  else +    sls_mu.Unlock(); +} + +void sls_fun_9() { +  if (getBool()) +    sls_mu.Lock(); +  else +    sls_mu.Lock(); +  sls_mu.Unlock(); +} + +void sls_fun_good_6() { +  if (getBool()) { +    sls_mu.Lock(); +  } else { +    if (getBool()) { +      getBool(); // EMPTY +    } else { +      getBool(); // EMPTY +    } +    sls_mu.Lock(); +  } +  sls_mu.Unlock(); +} + +void sls_fun_good_7() { +  sls_mu.Lock(); +  while (getBool()) { +    sls_mu.Unlock(); +    if (getBool()) { +      if (getBool()) { +        sls_mu.Lock(); +        continue; +      } +    } +    sls_mu.Lock(); +  } +  sls_mu.Unlock(); +} + +void sls_fun_good_8() { +  sls_mw.MyLock(); +  sls_mw.mu.Unlock(); +} + +void sls_fun_bad_1() { +  sls_mu.Unlock(); // \ +    // expected-warning{{unlocking 'sls_mu' that was not locked}} +} + +void sls_fun_bad_2() { +  sls_mu.Lock(); +  sls_mu.Lock(); // \ +    // expected-warning{{locking 'sls_mu' that is already locked}} +  sls_mu.Unlock(); +} + +void sls_fun_bad_3() { +  sls_mu.Lock(); // expected-note {{mutex acquired here}} +} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} + +void sls_fun_bad_4() { +  if (getBool()) +    sls_mu.Lock(); // \ +  expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \ +  expected-note{{mutex acquired here}} + +  else +    sls_mu2.Lock(); // \ +  expected-note{{mutex acquired here}} +} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} + +void sls_fun_bad_5() { +  sls_mu.Lock(); // expected-note {{mutex acquired here}} +  if (getBool()) +    sls_mu.Unlock(); +} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} + +void sls_fun_bad_6() { +  if (getBool()) { +    sls_mu.Lock(); // expected-note {{mutex acquired here}} +  } else { +    if (getBool()) { +      getBool(); // EMPTY +    } else { +      getBool(); // EMPTY +    } +  } +  sls_mu.Unlock(); // \ +    expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\ +    expected-warning{{unlocking 'sls_mu' that was not locked}} +} + +void sls_fun_bad_7() { +  sls_mu.Lock(); +  while (getBool()) { +    sls_mu.Unlock(); +    if (getBool()) { +      if (getBool()) { +        continue; // \ +        expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} +      } +    } +    sls_mu.Lock(); // expected-note {{mutex acquired here}} +  } +  sls_mu.Unlock(); +} + +void sls_fun_bad_8() { +  sls_mu.Lock(); // expected-note{{mutex acquired here}} + +  // FIXME: TERRIBLE SOURCE LOCATION! +  do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} +    sls_mu.Unlock(); +  } while (getBool()); +} + +void sls_fun_bad_9() { +  do { +    sls_mu.Lock(); // \ +      // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \ +      // expected-note{{mutex acquired here}} +  } while (getBool()); +  sls_mu.Unlock(); +} + +void sls_fun_bad_10() { +  sls_mu.Lock(); // expected-note 2{{mutex acquired here}} +  while(getBool()) { +    sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} +  } +} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} + +void sls_fun_bad_11() { +  while (getBool()) { // \ +   expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} +    sls_mu.Lock(); // expected-note {{mutex acquired here}} +  } +  sls_mu.Unlock(); // \ +    // expected-warning{{unlocking 'sls_mu' that was not locked}} +} + +void sls_fun_bad_12() { +  sls_mu.Lock(); // expected-note {{mutex acquired here}} +  while (getBool()) { +    sls_mu.Unlock(); +    if (getBool()) { +      if (getBool()) { +        break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} +      } +    } +    sls_mu.Lock(); +  } +  sls_mu.Unlock(); +} + +//-----------------------------------------// +// Handling lock expressions in attribute args +// -------------------------------------------// + +Mutex aa_mu; + +class GlobalLocker { +public: +  void globalLock() __attribute__((exclusive_lock_function(aa_mu))); +  void globalUnlock() __attribute__((unlock_function(aa_mu))); +}; + +GlobalLocker glock; + +void aa_fun_1() { +  glock.globalLock(); +  glock.globalUnlock(); +} + +void aa_fun_bad_1() { +  glock.globalUnlock(); // \ +    // expected-warning{{unlocking 'aa_mu' that was not locked}} +} + +void aa_fun_bad_2() { +  glock.globalLock(); +  glock.globalLock(); // \ +    // expected-warning{{locking 'aa_mu' that is already locked}} +  glock.globalUnlock(); +} + +void aa_fun_bad_3() { +  glock.globalLock(); // expected-note{{mutex acquired here}} +} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}} + +//--------------------------------------------------// +// Regression tests for unusual method names +//--------------------------------------------------// + +Mutex wmu; + +// Test diagnostics for other method names. +class WeirdMethods { +  // FIXME: can't currently check inside constructors and destructors. +  WeirdMethods() { +    wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}} +  } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}} +  ~WeirdMethods() { +    wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}} +  } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}} +  void operator++() { +    wmu.Lock(); // expected-note {{mutex acquired here}} +  } // expected-warning {{mutex 'wmu' is still locked at the end of function}} +  operator int*() { +    wmu.Lock(); // expected-note {{mutex acquired here}} +    return 0; +  } // expected-warning {{mutex 'wmu' is still locked at the end of function}} +}; + +//-----------------------------------------------// +// Errors for guarded by or guarded var variables +// ----------------------------------------------// + +int *pgb_gvar __attribute__((pt_guarded_var)); +int *pgb_var __attribute__((pt_guarded_by(sls_mu))); + +class PGBFoo { + public: +  int x; +  int *pgb_field __attribute__((guarded_by(sls_mu2))) +                 __attribute__((pt_guarded_by(sls_mu))); +  void testFoo() { +    pgb_field = &x; // \ +      // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}} +    *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \ +      // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}} +    x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \ +      // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}} +    (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \ +      // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}} +  } +}; + +class GBFoo { + public: +  int gb_field __attribute__((guarded_by(sls_mu))); + +  void testFoo() { +    gb_field = 0; // \ +      // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}} +  } + +  void testNoAnal() __attribute__((no_thread_safety_analysis)) { +    gb_field = 0; +  } +}; + +GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu))); + +void gb_fun_0() { +  sls_mu.Lock(); +  int x = *pgb_var; +  sls_mu.Unlock(); +} + +void gb_fun_1() { +  sls_mu.Lock(); +  *pgb_var = 2; +  sls_mu.Unlock(); +} + +void gb_fun_2() { +  int x; +  pgb_var = &x; +} + +void gb_fun_3() { +  int *x = pgb_var; +} + +void gb_bad_0() { +  sls_guard_var = 1; // \ +    // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} +} + +void gb_bad_1() { +  int x = sls_guard_var; // \ +    // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}} +} + +void gb_bad_2() { +  sls_guardby_var = 1; // \ +    // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}} +} + +void gb_bad_3() { +  int x = sls_guardby_var; // \ +    // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}} +} + +void gb_bad_4() { +  *pgb_gvar = 1; // \ +    // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}} +} + +void gb_bad_5() { +  int x = *pgb_gvar; // \ +    // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}} +} + +void gb_bad_6() { +  *pgb_var = 1; // \ +    // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}} +} + +void gb_bad_7() { +  int x = *pgb_var; // \ +    // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}} +} + +void gb_bad_8() { +  GBFoo G; +  G.gb_field = 0; // \ +    // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}} +} + +void gb_bad_9() { +  sls_guard_var++; // \ +    // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} +  sls_guard_var--; // \ +    // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} +  ++sls_guard_var; // \ +    // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} +  --sls_guard_var;// \ +    // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} +} + +//-----------------------------------------------// +// Warnings on variables with late parsed attributes +// ----------------------------------------------// + +class LateFoo { +public: +  int a __attribute__((guarded_by(mu))); +  int b; + +  void foo() __attribute__((exclusive_locks_required(mu))) { } + +  void test() { +    a = 0; // \ +      // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} +    b = a; // \ +      // expected-warning {{reading variable 'a' requires locking 'mu'}} +    c = 0; // \ +      // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}} +  } + +  int c __attribute__((guarded_by(mu))); + +  Mutex mu; +}; + +class LateBar { + public: +  int a_ __attribute__((guarded_by(mu1_))); +  int b_; +  int *q __attribute__((pt_guarded_by(mu))); +  Mutex mu1_; +  Mutex mu; +  LateFoo Foo; +  LateFoo Foo2; +  LateFoo *FooPointer; +}; + +LateBar b1, *b3; + +void late_0() { +  LateFoo FooA; +  LateFoo FooB; +  FooA.mu.Lock(); +  FooA.a = 5; +  FooA.mu.Unlock(); +} + +void late_1() { +  LateBar BarA; +  BarA.FooPointer->mu.Lock(); +  BarA.FooPointer->a = 2; +  BarA.FooPointer->mu.Unlock(); +} + +void late_bad_0() { +  LateFoo fooA; +  LateFoo fooB; +  fooA.mu.Lock(); +  fooB.a = 5; // \ +    // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} +  fooA.mu.Unlock(); +} + +void late_bad_1() { +  Mutex mu; +  mu.Lock(); +  b1.mu1_.Lock(); +  int res = b1.a_ + b3->b_; +  b3->b_ = *b1.q; // \ +    // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}} +  b1.mu1_.Unlock(); +  b1.b_ = res; +  mu.Unlock(); +} + +void late_bad_2() { +  LateBar BarA; +  BarA.FooPointer->mu.Lock(); +  BarA.Foo.a = 2; // \ +    // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} +  BarA.FooPointer->mu.Unlock(); +} + +void late_bad_3() { +  LateBar BarA; +  BarA.Foo.mu.Lock(); +  BarA.FooPointer->a = 2; // \ +    // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} +  BarA.Foo.mu.Unlock(); +} + +void late_bad_4() { +  LateBar BarA; +  BarA.Foo.mu.Lock(); +  BarA.Foo2.a = 2; // \ +    // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} +  BarA.Foo.mu.Unlock(); +} + +//-----------------------------------------------// +// Extra warnings for shared vs. exclusive locks +// ----------------------------------------------// + +void shared_fun_0() { +  sls_mu.Lock(); +  do { +    sls_mu.Unlock(); +    sls_mu.Lock(); +  } while (getBool()); +  sls_mu.Unlock(); +} + +void shared_fun_1() { +  sls_mu.ReaderLock(); // \ +    // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} +  do { +    sls_mu.Unlock(); +    sls_mu.Lock();  // \ +      // expected-note {{the other lock of mutex 'sls_mu' is here}} +  } while (getBool()); +  sls_mu.Unlock(); +} + +void shared_fun_3() { +  if (getBool()) +    sls_mu.Lock(); +  else +    sls_mu.Lock(); +  *pgb_var = 1; +  sls_mu.Unlock(); +} + +void shared_fun_4() { +  if (getBool()) +    sls_mu.ReaderLock(); +  else +    sls_mu.ReaderLock(); +  int x = sls_guardby_var; +  sls_mu.Unlock(); +} + +void shared_fun_8() { +  if (getBool()) +    sls_mu.Lock(); // \ +      // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} +  else +    sls_mu.ReaderLock(); // \ +      // expected-note {{the other lock of mutex 'sls_mu' is here}} +  sls_mu.Unlock(); +} + +void shared_bad_0() { +  sls_mu.Lock();  // \ +    // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} +  do { +    sls_mu.Unlock(); +    sls_mu.ReaderLock();  // \ +      // expected-note {{the other lock of mutex 'sls_mu' is here}} +  } while (getBool()); +  sls_mu.Unlock(); +} + +void shared_bad_1() { +  if (getBool()) +    sls_mu.Lock(); // \ +      // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} +  else +    sls_mu.ReaderLock(); // \ +      // expected-note {{the other lock of mutex 'sls_mu' is here}} +  *pgb_var = 1; +  sls_mu.Unlock(); +} + +void shared_bad_2() { +  if (getBool()) +    sls_mu.ReaderLock(); // \ +      // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} +  else +    sls_mu.Lock(); // \ +      // expected-note {{the other lock of mutex 'sls_mu' is here}} +  *pgb_var = 1; +  sls_mu.Unlock(); +} + +// FIXME: Add support for functions (not only methods) +class LRBar { + public: +  void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu))); +  void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu))); +  void le_fun() __attribute__((locks_excluded(sls_mu))); +}; + +class LRFoo { + public: +  void test() __attribute__((exclusive_locks_required(sls_mu))); +  void testShared() __attribute__((shared_locks_required(sls_mu2))); +}; + +void elr_fun() __attribute__((exclusive_locks_required(sls_mu))); +void elr_fun() {} + +LRFoo MyLRFoo; +LRBar Bar; + +void es_fun_0() { +  aa_mu.Lock(); +  Bar.aa_elr_fun(); +  aa_mu.Unlock(); +} + +void es_fun_1() { +  aa_mu.Lock(); +  Bar.aa_elr_fun_s(); +  aa_mu.Unlock(); +} + +void es_fun_2() { +  aa_mu.ReaderLock(); +  Bar.aa_elr_fun_s(); +  aa_mu.Unlock(); +} + +void es_fun_3() { +  sls_mu.Lock(); +  MyLRFoo.test(); +  sls_mu.Unlock(); +} + +void es_fun_4() { +  sls_mu2.Lock(); +  MyLRFoo.testShared(); +  sls_mu2.Unlock(); +} + +void es_fun_5() { +  sls_mu2.ReaderLock(); +  MyLRFoo.testShared(); +  sls_mu2.Unlock(); +} + +void es_fun_6() { +  Bar.le_fun(); +} + +void es_fun_7() { +  sls_mu.Lock(); +  elr_fun(); +  sls_mu.Unlock(); +} + +void es_fun_8() __attribute__((no_thread_safety_analysis)); + +void es_fun_8() { +  Bar.aa_elr_fun_s(); +} + +void es_fun_9() __attribute__((shared_locks_required(aa_mu))); +void es_fun_9() { +  Bar.aa_elr_fun_s(); +} + +void es_fun_10() __attribute__((exclusive_locks_required(aa_mu))); +void es_fun_10() { +  Bar.aa_elr_fun_s(); +} + +void es_bad_0() { +  Bar.aa_elr_fun(); // \ +    // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}} +} + +void es_bad_1() { +  aa_mu.ReaderLock(); +  Bar.aa_elr_fun(); // \ +    // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}} +  aa_mu.Unlock(); +} + +void es_bad_2() { +  Bar.aa_elr_fun_s(); // \ +    // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}} +} + +void es_bad_3() { +  MyLRFoo.test(); // \ +    // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}} +} + +void es_bad_4() { +  MyLRFoo.testShared(); // \ +    // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}} +} + +void es_bad_5() { +  sls_mu.ReaderLock(); +  MyLRFoo.test(); // \ +    // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}} +  sls_mu.Unlock(); +} + +void es_bad_6() { +  sls_mu.Lock(); +  Bar.le_fun(); // \ +    // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}} +  sls_mu.Unlock(); +} + +void es_bad_7() { +  sls_mu.ReaderLock(); +  Bar.le_fun(); // \ +    // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}} +  sls_mu.Unlock(); +} + + +//-----------------------------------------------// +// Unparseable lock expressions +// ----------------------------------------------// + +// FIXME -- derive new tests for unhandled expressions + + +//----------------------------------------------------------------------------// +// The following test cases are ported from the gcc thread safety implementation +// They are each wrapped inside a namespace with the test number of the gcc test +// +// FIXME: add all the gcc tests, once this analysis passes them. +//----------------------------------------------------------------------------// + +//-----------------------------------------// +// Good testcases (no errors) +//-----------------------------------------// + +namespace thread_annot_lock_20 { +class Bar { + public: +  static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_); +  static int b_ GUARDED_BY(mu1_); +  static Mutex mu1_; +  static int a_ GUARDED_BY(mu1_); +}; + +Bar b1; + +int Bar::func1() +{ +  int res = 5; + +  if (a_ == 4) +    res = b_; +  return res; +} +} // end namespace thread_annot_lock_20 + +namespace thread_annot_lock_22 { +// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially +// uses in class definitions. +Mutex mu; + +class Bar { + public: +  int a_ GUARDED_BY(mu1_); +  int b_; +  int *q PT_GUARDED_BY(mu); +  Mutex mu1_ ACQUIRED_AFTER(mu); +}; + +Bar b1, *b3; +int *p GUARDED_BY(mu) PT_GUARDED_BY(mu); +int res GUARDED_BY(mu) = 5; + +int func(int i) +{ +  int x; +  mu.Lock(); +  b1.mu1_.Lock(); +  res = b1.a_ + b3->b_; +  *p = i; +  b1.a_ = res + b3->b_; +  b3->b_ = *b1.q; +  b1.mu1_.Unlock(); +  b1.b_ = res; +  x = res; +  mu.Unlock(); +  return x; +} +} // end namespace thread_annot_lock_22 + +namespace thread_annot_lock_27_modified { +// test lock annotations applied to function definitions +// Modified: applied annotations only to function declarations +Mutex mu1; +Mutex mu2 ACQUIRED_AFTER(mu1); + +class Foo { + public: +  int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1); +}; + +int Foo::method1(int i) { +  return i; +} + + +int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1); +int foo(int i) { +  return i; +} + +static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1); +static int bar(int i) { +  return i; +} + +void main() { +  Foo a; + +  mu1.Lock(); +  mu2.Lock(); +  a.method1(1); +  foo(2); +  mu2.Unlock(); +  bar(3); +  mu1.Unlock(); +} +} // end namespace thread_annot_lock_27_modified + + +namespace thread_annot_lock_38 { +// Test the case where a template member function is annotated with lock +// attributes in a non-template class. +class Foo { + public: +  void func1(int y) LOCKS_EXCLUDED(mu_); +  template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_); + private: +  Mutex mu_; +}; + +Foo *foo; + +void main() +{ +  foo->func1(5); +  foo->func2(5); +} +} // end namespace thread_annot_lock_38 + +namespace thread_annot_lock_43 { +// Tests lock canonicalization +class Foo { + public: +  Mutex *mu_; +}; + +class FooBar { + public: +  Foo *foo_; +  int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; } +  int a_ GUARDED_BY(foo_->mu_); +}; + +FooBar *fb; + +void main() +{ +  int x; +  fb->foo_->mu_->Lock(); +  x = fb->GetA(); +  fb->foo_->mu_->Unlock(); +} +} // end namespace thread_annot_lock_43 + +namespace thread_annot_lock_49 { +// Test the support for use of lock expression in the annotations +class Foo { + public: +  Mutex foo_mu_; +}; + +class Bar { + private: +  Foo *foo; +  Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_); + + public: +  void Test1() { +    foo->foo_mu_.Lock(); +    bar_mu_.Lock(); +    bar_mu_.Unlock(); +    foo->foo_mu_.Unlock(); +  } +}; + +void main() { +  Bar bar; +  bar.Test1(); +} +} // end namespace thread_annot_lock_49 + +namespace thread_annot_lock_61_modified { +  // Modified to fix the compiler errors +  // Test the fix for a bug introduced by the support of pass-by-reference +  // paramters. +  struct Foo { Foo &operator<< (bool) {return *this;} }; +  Foo &getFoo(); +  struct Bar { Foo &func () {return getFoo();} }; +  struct Bas { void operator& (Foo &) {} }; +  void mumble() +  { +    Bas() & Bar().func() << "" << ""; +    Bas() & Bar().func() << ""; +  } +} // end namespace thread_annot_lock_61_modified + + +namespace thread_annot_lock_65 { +// Test the fix for a bug in the support of allowing reader locks for +// non-const, non-modifying overload functions. (We didn't handle the builtin +// properly.) +enum MyFlags { +  Zero, +  One, +  Two, +  Three, +  Four, +  Five, +  Six, +  Seven, +  Eight, +  Nine +}; + +inline MyFlags +operator|(MyFlags a, MyFlags b) +{ +  return MyFlags(static_cast<int>(a) | static_cast<int>(b)); +} + +inline MyFlags& +operator|=(MyFlags& a, MyFlags b) +{ +    return a = a | b; +} +} // end namespace thread_annot_lock_65 + +namespace thread_annot_lock_66_modified { +// Modified: Moved annotation to function defn +// Test annotations on out-of-line definitions of member functions where the +// annotations refer to locks that are also data members in the class. +Mutex mu; + +class Foo { + public: +  int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2); +  int data GUARDED_BY(mu1); +  Mutex *mu1; +  Mutex *mu2; +}; + +int Foo::method1(int i) +{ +  return data + i; +} + +void main() +{ +  Foo a; + +  a.mu2->Lock(); +  a.mu1->Lock(); +  mu.Lock(); +  a.method1(1); +  mu.Unlock(); +  a.mu1->Unlock(); +  a.mu2->Unlock(); +} +} // end namespace thread_annot_lock_66_modified + +namespace thread_annot_lock_68_modified { +// Test a fix to a bug in the delayed name binding with nested template +// instantiation. We use a stack to make sure a name is not resolved to an +// inner context. +template <typename T> +class Bar { +  Mutex mu_; +}; + +template <typename T> +class Foo { + public: +  void func(T x) { +    mu_.Lock(); +    count_ = x; +    mu_.Unlock(); +  } + + private: +  T count_ GUARDED_BY(mu_); +  Bar<T> bar_; +  Mutex mu_; +}; + +void main() +{ +  Foo<int> *foo; +  foo->func(5); +} +} // end namespace thread_annot_lock_68_modified + +namespace thread_annot_lock_30_modified { +// Test delay parsing of lock attribute arguments with nested classes. +// Modified: trylocks replaced with exclusive_lock_fun +int a = 0; + +class Bar { +  struct Foo; + + public: +  void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu); + +  int func() { +    MyLock(); +//    if (foo == 0) { +//      return 0; +//    } +    a = 5; +    mu.Unlock(); +    return 1; +  } + +  class FooBar { +    int x; +    int y; +  }; + + private: +  Mutex mu; +}; + +Bar *bar; + +void main() +{ +  bar->func(); +} +} // end namespace thread_annot_lock_30_modified + +namespace thread_annot_lock_47 { +// Test the support for annotations on virtual functions. +// This is a good test case. (i.e. There should be no warning emitted by the +// compiler.) +class Base { + public: +  virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_); +  virtual void func2() LOCKS_EXCLUDED(mu_); +  Mutex mu_; +}; + +class Child : public Base { + public: +  virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_); +  virtual void func2() LOCKS_EXCLUDED(mu_); +}; + +void main() { +  Child *c; +  Base *b = c; + +  b->mu_.Lock(); +  b->func1(); +  b->mu_.Unlock(); +  b->func2(); + +  c->mu_.Lock(); +  c->func1(); +  c->mu_.Unlock(); +  c->func2(); +} +} // end namespace thread_annot_lock_47 + +//-----------------------------------------// +// Tests which produce errors +//-----------------------------------------// + +namespace thread_annot_lock_13 { +Mutex mu1; +Mutex mu2; + +int g GUARDED_BY(mu1); +int w GUARDED_BY(mu2); + +class Foo { + public: +  void bar() LOCKS_EXCLUDED(mu_, mu1); +  int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2); + + private: +  int a_ GUARDED_BY(mu_); + public: +  Mutex mu_ ACQUIRED_AFTER(mu1); +}; + +int Foo::foo() +{ +  int res; +  w = 5; +  res = a_ + 5; +  return res; +} + +void Foo::bar() +{ +  int x; +  mu_.Lock(); +  x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}} +  a_ = x + 1; +  mu_.Unlock(); +  if (x > 5) { +    mu1.Lock(); +    g = 2; +    mu1.Unlock(); +  } +} + +void main() +{ +  Foo f1, *f2; +  f1.mu_.Lock(); +  f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}} +  mu2.Lock(); +  f1.foo(); +  mu2.Unlock(); +  f1.mu_.Unlock(); +  f2->mu_.Lock(); +  f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}} +  f2->mu_.Unlock(); +  mu2.Lock(); +  w = 2; +  mu2.Unlock(); +} +} // end namespace thread_annot_lock_13 + +namespace thread_annot_lock_18_modified { +// Modified: Trylocks removed +// Test the ability to distnguish between the same lock field of +// different objects of a class. +  class Bar { + public: +  bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_); +  void MyUnlock() UNLOCK_FUNCTION(mu1_); +  int a_ GUARDED_BY(mu1_); + + private: +  Mutex mu1_; +}; + +Bar *b1, *b2; + +void func() +{ +  b1->MyLock(); +  b1->a_ = 5; +  b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}} +  b2->MyLock(); +  b2->MyUnlock(); +  b1->MyUnlock(); +} +} // end namespace thread_annot_lock_18_modified + +namespace thread_annot_lock_21 { +// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially +// uses in class definitions. +Mutex mu; + +class Bar { + public: +  int a_ GUARDED_BY(mu1_); +  int b_; +  int *q PT_GUARDED_BY(mu); +  Mutex mu1_ ACQUIRED_AFTER(mu); +}; + +Bar b1, *b3; +int *p GUARDED_BY(mu) PT_GUARDED_BY(mu); + +int res GUARDED_BY(mu) = 5; + +int func(int i) +{ +  int x; +  b3->mu1_.Lock(); +  res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \ +    // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}} +  *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \ +    // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}} +  b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \ +    // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}} +  b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}} +  b3->mu1_.Unlock(); +  b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}} +  x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}} +  return x; +} +} // end namespace thread_annot_lock_21 + +namespace thread_annot_lock_35_modified { +// Test the analyzer's ability to distinguish the lock field of different +// objects. +class Foo { + private: +  Mutex lock_; +  int a_ GUARDED_BY(lock_); + + public: +  void Func(Foo* child) LOCKS_EXCLUDED(lock_) { +     Foo *new_foo = new Foo; + +     lock_.Lock(); + +     child->Func(new_foo); // There shouldn't be any warning here as the +                           // acquired lock is not in child. +     child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}} +     child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}} +     lock_.Unlock(); +  } + +  void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) { +    a_ = y; +  } +}; + +Foo *x; + +void main() { +  Foo *child = new Foo; +  x->Func(child); +} +} // end namespace thread_annot_lock_35_modified + +namespace thread_annot_lock_36_modified { +// Modified to move the annotations to function defns. +// Test the analyzer's ability to distinguish the lock field of different +// objects +class Foo { + private: +  Mutex lock_; +  int a_ GUARDED_BY(lock_); + + public: +  void Func(Foo* child) LOCKS_EXCLUDED(lock_); +  void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_); +}; + +void Foo::Func(Foo* child) { +  Foo *new_foo = new Foo; + +  lock_.Lock(); + +  child->lock_.Lock(); +  child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}} +  child->bar(7); +  child->a_ = 5; +  child->lock_.Unlock(); + +  lock_.Unlock(); +} + +void Foo::bar(int y) { +  a_ = y; +} + + +Foo *x; + +void main() { +  Foo *child = new Foo; +  x->Func(child); +} +} // end namespace thread_annot_lock_36_modified + + +namespace thread_annot_lock_42 { +// Test support of multiple lock attributes of the same kind on a decl. +class Foo { + private: +  Mutex mu1, mu2, mu3; +  int x GUARDED_BY(mu1) GUARDED_BY(mu2); +  int y GUARDED_BY(mu2); + +  void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) { +    mu2.Lock(); +    y = 2; +    mu2.Unlock(); +  } + + public: +  void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) { +    x = 5; +    f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \ +      // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}} +  } +}; + +Foo *foo; + +void func() +{ +  foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \ +    // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}} +} +} // end namespace thread_annot_lock_42 + +namespace thread_annot_lock_46 { +// Test the support for annotations on virtual functions. +class Base { + public: +  virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_); +  virtual void func2() LOCKS_EXCLUDED(mu_); +  Mutex mu_; +}; + +class Child : public Base { + public: +  virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_); +  virtual void func2() LOCKS_EXCLUDED(mu_); +}; + +void main() { +  Child *c; +  Base *b = c; + +  b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}} +  b->mu_.Lock(); +  b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}} +  b->mu_.Unlock(); + +  c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}} +  c->mu_.Lock(); +  c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}} +  c->mu_.Unlock(); +} +} // end namespace thread_annot_lock_46 + +namespace thread_annot_lock_67_modified { +// Modified: attributes on definitions moved to declarations +// Test annotations on out-of-line definitions of member functions where the +// annotations refer to locks that are also data members in the class. +Mutex mu; +Mutex mu3; + +class Foo { + public: +  int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3); +  int data GUARDED_BY(mu1); +  Mutex *mu1; +  Mutex *mu2; +}; + +int Foo::method1(int i) { +  return data + i; +} + +void main() +{ +  Foo a; +  a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \ +    // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \ +    // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \ +    // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}} +} +} // end namespace thread_annot_lock_67_modified + + +namespace substitution_test { +  class MyData  { +  public: +    Mutex mu; + +    void lockData()    __attribute__((exclusive_lock_function(mu)))   { } +    void unlockData()  __attribute__((unlock_function(mu)))           { } + +    void doSomething() __attribute__((exclusive_locks_required(mu)))  { } +  }; + + +  class DataLocker { +  public: +    void lockData  (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { } +    void unlockData(MyData *d) __attribute__((unlock_function(d->mu)))         { } +  }; + + +  class Foo { +  public: +    void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { } + +    void bar1(MyData* d) { +      d->lockData(); +      foo(d); +      d->unlockData(); +    } + +    void bar2(MyData* d) { +      DataLocker dlr; +      dlr.lockData(d); +      foo(d); +      dlr.unlockData(d); +    } + +    void bar3(MyData* d1, MyData* d2) { +      DataLocker dlr; +      dlr.lockData(d1);   // expected-note {{mutex acquired here}} +      dlr.unlockData(d2); // \ +        // expected-warning {{unlocking 'mu' that was not locked}} +    } // expected-warning {{mutex 'mu' is still locked at the end of function}} + +    void bar4(MyData* d1, MyData* d2) { +      DataLocker dlr; +      dlr.lockData(d1); +      foo(d2); // \ +        // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}} +      dlr.unlockData(d1); +    } +  }; +} // end namespace substituation_test + + + +namespace constructor_destructor_tests { +  Mutex fooMu; +  int myVar GUARDED_BY(fooMu); + +  class Foo { +  public: +    Foo()  __attribute__((exclusive_lock_function(fooMu))) { } +    ~Foo() __attribute__((unlock_function(fooMu))) { } +  }; + +  void fooTest() { +    Foo foo; +    myVar = 0; +  } +} + + +namespace invalid_lock_expression_test { + +class LOCKABLE MyLockable { +public: +  MyLockable() __attribute__((exclusive_lock_function)) { } +  ~MyLockable() { } +}; + +// create an empty lock expression +void foo() { +  MyLockable lock;  // \ +    // expected-warning {{cannot resolve lock expression}} +} + +} // end namespace invalid_lock_expression_test + +namespace template_member_test { + +  struct S { int n; }; +  struct T { +    Mutex m; +    S *s GUARDED_BY(this->m); +  }; +  Mutex m; +  struct U { +    union { +      int n; +    }; +  } *u GUARDED_BY(m); + +  template<typename U> +  struct IndirectLock { +    int DoNaughtyThings(T *t) { +      u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}} +      return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}} +    } +  }; + +  template struct IndirectLock<int>; // expected-note {{here}} + +  struct V { +    void f(int); +    void f(double); + +    Mutex m; +    V *p GUARDED_BY(this->m); +  }; +  template<typename U> struct W { +    V v; +    void f(U u) { +      v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}} +    } +  }; +  template struct W<int>; // expected-note {{here}} + +} + +namespace test_scoped_lockable { + +struct TestScopedLockable { +  Mutex mu1; +  Mutex mu2; +  int a __attribute__((guarded_by(mu1))); +  int b __attribute__((guarded_by(mu2))); + +  bool getBool(); + +  void foo1() { +    MutexLock mulock(&mu1); +    a = 5; +  } + +  void foo2() { +    ReaderMutexLock mulock1(&mu1); +    if (getBool()) { +      MutexLock mulock2a(&mu2); +      b = a + 1; +    } +    else { +      MutexLock mulock2b(&mu2); +      b = a + 2; +    } +  } + +  void foo3() { +    MutexLock mulock_a(&mu1); +    MutexLock mulock_b(&mu1); // \ +      // expected-warning {{locking 'mu1' that is already locked}} +  }   // expected-warning {{unlocking 'mu1' that was not locked}} + +  void foo4() { +    MutexLock mulock1(&mu1), mulock2(&mu2); +    a = b+1; +    b = a+1; +  } +}; + +} // end namespace test_scoped_lockable + + +namespace FunctionAttrTest { + +class Foo { +public: +  Mutex mu_; +  int a GUARDED_BY(mu_); +}; + +Foo fooObj; + +void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_); + +void bar() { +  foo();  // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} +  fooObj.mu_.Lock(); +  foo(); +  fooObj.mu_.Unlock(); +} + +};  // end namespace FunctionAttrTest + + +struct TestTryLock { +  Mutex mu; +  int a GUARDED_BY(mu); +  bool cond; + +  void foo1() { +    if (mu.TryLock()) { +      a = 1; +      mu.Unlock(); +    } +  } + +  void foo2() { +    if (!mu.TryLock()) return; +    a = 2; +    mu.Unlock(); +  } + +  void foo3() { +    bool b = mu.TryLock(); +    if (b) { +      a = 3; +      mu.Unlock(); +    } +  } + +  void foo4() { +    bool b = mu.TryLock(); +    if (!b) return; +    a = 4; +    mu.Unlock(); +  } + +  void foo5() { +    while (mu.TryLock()) { +      a = a + 1; +      mu.Unlock(); +    } +  } + +  void foo6() { +    bool b = mu.TryLock(); +    b = !b; +    if (b) return; +    a = 6; +    mu.Unlock(); +  } + +  void foo7() { +    bool b1 = mu.TryLock(); +    bool b2 = !b1; +    bool b3 = !b2; +    if (b3) { +      a = 7; +      mu.Unlock(); +    } +  } + +  // Test use-def chains: join points +  void foo8() { +    bool b  = mu.TryLock(); +    bool b2 = b; +    if (cond) +      b = true; +    if (b) {    // b should be unknown at this point, becuase of the join point +      a = 8;    // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}} +    } +    if (b2) {   // b2 should be known at this point. +      a = 8; +      mu.Unlock(); +    } +  } + +  // Test use-def-chains: back edges +  void foo9() { +    bool b = mu.TryLock(); + +    for (int i = 0; i < 10; ++i); + +    if (b) {  // b is still known, because the loop doesn't alter it +      a = 9; +      mu.Unlock(); +    } +  } + +  // Test use-def chains: back edges +  void foo10() { +    bool b = mu.TryLock(); + +    while (cond) { +      if (b) {   // b should be uknown at this point b/c of the loop +        a = 10;  // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}} +      } +      b = !b; +    } +  } +};  // end TestTrylock + + +namespace TestTemplateAttributeInstantiation { + +class Foo1 { +public: +  Mutex mu_; +  int a GUARDED_BY(mu_); +}; + +class Foo2 { +public: +  int a GUARDED_BY(mu_); +  Mutex mu_; +}; + + +class Bar { +public: +  // Test non-dependent expressions in attributes on template functions +  template <class T> +  void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) { +    foo->a = 0; +  } + +  // Test dependent expressions in attributes on template functions +  template <class T> +  void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) { +    fooT->a = 0; +  } +}; + + +template <class T> +class BarT { +public: +  Foo1 fooBase; +  T    fooBaseT; + +  // Test non-dependent expression in ordinary method on template class +  void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) { +    fooBase.a = 0; +  } + +  // Test dependent expressions in ordinary methods on template class +  void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) { +    fooBaseT.a = 0; +  } + +  // Test dependent expressions in template method in template class +  template <class T2> +  void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) { +    fooBaseT.a = 0; +    fooT->a = 0; +  } +}; + +template <class T> +class Cell { +public: +  Mutex mu_; +  // Test dependent guarded_by +  T data GUARDED_BY(mu_); + +  void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) { +    data = 0; +  } + +  void foo() { +    mu_.Lock(); +    data = 0; +    mu_.Unlock(); +  } +}; + +void test() { +  Bar b; +  BarT<Foo2> bt; +  Foo1 f1; +  Foo2 f2; + +  f1.mu_.Lock(); +  f2.mu_.Lock(); +  bt.fooBase.mu_.Lock(); +  bt.fooBaseT.mu_.Lock(); + +  b.barND(&f1, &f2); +  b.barD(&f1, &f2); +  bt.barND(); +  bt.barD(); +  bt.barTD(&f2); + +  f1.mu_.Unlock(); +  bt.barTD(&f1);  // \ +    // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}} + +  bt.fooBase.mu_.Unlock(); +  bt.fooBaseT.mu_.Unlock(); +  f2.mu_.Unlock(); + +  Cell<int> cell; +  cell.data = 0; // \ +    // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}} +  cell.foo(); +  cell.mu_.Lock(); +  cell.fooEx(); +  cell.mu_.Unlock(); +} + + +template <class T> +class CellDelayed { +public: +  // Test dependent guarded_by +  T data GUARDED_BY(mu_); +  static T static_data GUARDED_BY(static_mu_); + +  void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) { +    this->data = other->data; +  } + +  template <class T2> +  void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) { +    this->data = otherT->data; +  } + +  void foo() { +    mu_.Lock(); +    data = 0; +    mu_.Unlock(); +  } + +  Mutex mu_; +  static Mutex static_mu_; +}; + +void testDelayed() { +  CellDelayed<int> celld; +  CellDelayed<int> celld2; +  celld.foo(); +  celld.mu_.Lock(); +  celld2.mu_.Lock(); + +  celld.fooEx(&celld2); +  celld.fooExT(&celld2); + +  celld2.mu_.Unlock(); +  celld.mu_.Unlock(); +} + +};  // end namespace TestTemplateAttributeInstantiation + + +namespace FunctionDeclDefTest { + +class Foo { +public: +  Mutex mu_; +  int a GUARDED_BY(mu_); + +  virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_); +}; + +// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_ +void Foo::foo1(Foo *f_defined) { +  f_defined->a = 0; +}; + +void test() { +  Foo myfoo; +  myfoo.foo1(&myfoo);  // \ +    // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}} +  myfoo.mu_.Lock(); +  myfoo.foo1(&myfoo); +  myfoo.mu_.Unlock(); +} + +}; + +namespace GoingNative { + +  struct __attribute__((lockable)) mutex { +    void lock() __attribute__((exclusive_lock_function)); +    void unlock() __attribute__((unlock_function)); +    // ... +  }; +  bool foo(); +  bool bar(); +  mutex m; +  void test() { +    m.lock(); +    while (foo()) { +      m.unlock(); +      // ... +      if (bar()) { +        // ... +        if (foo()) +          continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}} +        //... +      } +      // ... +      m.lock(); // expected-note {{mutex acquired here}} +    } +    m.unlock(); +  } + +} + + + +namespace FunctionDefinitionTest { + +class Foo { +public: +  void foo1(); +  void foo2(); +  void foo3(Foo *other); + +  template<class T> +  void fooT1(const T& dummy1); + +  template<class T> +  void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_); + +  Mutex mu_; +  int a GUARDED_BY(mu_); +}; + +template<class T> +class FooT { +public: +  void foo(); + +  Mutex mu_; +  T a GUARDED_BY(mu_); +}; + + +void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS { +  a = 1; +} + +void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) { +  a = 2; +} + +void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) { +  other->a = 3; +} + +template<class T> +void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) { +  a = dummy1; +} + +/* TODO -- uncomment with template instantiation of attributes. +template<class T> +void Foo::fooT2(const T& dummy2) { +  a = dummy2; +} +*/ + +void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { +  f->a = 1; +} + +void fooF2(Foo *f); +void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { +  f->a = 2; +} + +void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_); +void fooF3(Foo *f) { +  f->a = 3; +} + +template<class T> +void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { +  a = 0; +} + +void test() { +  int dummy = 0; +  Foo myFoo; + +  myFoo.foo2();        // \ +    // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}} +  myFoo.foo3(&myFoo);  // \ +    // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}} +  myFoo.fooT1(dummy);  // \ +    // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}} + +  // FIXME: uncomment with template instantiation of attributes patch +  // myFoo.fooT2(dummy);  // expected warning + +  fooF1(&myFoo);  // \ +    // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}} +  fooF2(&myFoo);  // \ +    // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}} +  fooF3(&myFoo);  // \ +    // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}} + +  myFoo.mu_.Lock(); +  myFoo.foo2(); +  myFoo.foo3(&myFoo); +  myFoo.fooT1(dummy); + +  // FIXME: uncomment with template instantiation of attributes patch +  // myFoo.fooT2(dummy); + +  fooF1(&myFoo); +  fooF2(&myFoo); +  fooF3(&myFoo); +  myFoo.mu_.Unlock(); + +  FooT<int> myFooT; +  myFooT.foo();  // \ +    // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} +} + +} // end namespace FunctionDefinitionTest + + +namespace SelfLockingTest { + +class LOCKABLE MyLock { +public: +  int foo GUARDED_BY(this); + +  void lock()   EXCLUSIVE_LOCK_FUNCTION(); +  void unlock() UNLOCK_FUNCTION(); + +  void doSomething() { +    this->lock();  // allow 'this' as a lock expression +    foo = 0; +    doSomethingElse(); +    this->unlock(); +  } + +  void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) { +    foo = 1; +  }; + +  void test() { +    foo = 2;  // \ +      // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}} +  } +}; + + +class LOCKABLE MyLock2 { +public: +  Mutex mu_; +  int foo GUARDED_BY(this); + +  // don't check inside lock and unlock functions +  void lock()   EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock();   } +  void unlock() UNLOCK_FUNCTION()         { mu_.Unlock(); } + +  // don't check inside constructors and destructors +  MyLock2()  { foo = 1; } +  ~MyLock2() { foo = 0; } +}; + + +} // end namespace SelfLockingTest + + +namespace InvalidNonstatic { + +// Forward decl here causes bogus "invalid use of non-static data member" +// on reference to mutex_ in guarded_by attribute. +class Foo; + +class Foo { +  Mutex* mutex_; + +  int foo __attribute__((guarded_by(mutex_))); +}; + +}  // end namespace InvalidNonStatic + + +namespace NoReturnTest { + +bool condition(); +void fatal() __attribute__((noreturn)); + +Mutex mu_; + +void test1() { +  MutexLock lock(&mu_); +  if (condition()) { +    fatal(); +    return; +  } +} + +} // end namespace NoReturnTest + + +namespace TestMultiDecl { + +class Foo { +public: +  int GUARDED_BY(mu_) a; +  int GUARDED_BY(mu_) b, c; + +  void foo() { +    a = 0; // \ +      // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +    b = 0; // \ +      // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}} +    c = 0; // \ +      // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}} +  } + +private: +  Mutex mu_; +}; + +} // end namespace TestMultiDecl + + +namespace WarnNoDecl { + +class Foo { +  void foo(int a);  __attribute__(( // \ +    // expected-warning {{declaration does not declare anything}} +    exclusive_locks_required(a))); // \ +    // expected-warning {{attribute exclusive_locks_required ignored}} +}; + +} // end namespace WarnNoDecl + + + +namespace MoreLockExpressions { + +class Foo { +public: +  Mutex mu_; +  int a GUARDED_BY(mu_); +}; + +class Bar { +public: +  int b; +  Foo* f; + +  Foo& getFoo()              { return *f; } +  Foo& getFoo2(int c)        { return *f; } +  Foo& getFoo3(int c, int d) { return *f; } + +  Foo& getFooey() { return *f; } +}; + +Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); } + +void test() { +  Foo foo; +  Foo *fooArray; +  Bar bar; +  int a; +  int b; +  int c; + +  bar.getFoo().mu_.Lock(); +  bar.getFoo().a = 0; +  bar.getFoo().mu_.Unlock(); + +  (bar.getFoo().mu_).Lock();   // test parenthesis +  bar.getFoo().a = 0; +  (bar.getFoo().mu_).Unlock(); + +  bar.getFoo2(a).mu_.Lock(); +  bar.getFoo2(a).a = 0; +  bar.getFoo2(a).mu_.Unlock(); + +  bar.getFoo3(a, b).mu_.Lock(); +  bar.getFoo3(a, b).a = 0; +  bar.getFoo3(a, b).mu_.Unlock(); + +  getBarFoo(bar, a).mu_.Lock(); +  getBarFoo(bar, a).a = 0; +  getBarFoo(bar, a).mu_.Unlock(); + +  bar.getFoo2(10).mu_.Lock(); +  bar.getFoo2(10).a = 0; +  bar.getFoo2(10).mu_.Unlock(); + +  bar.getFoo2(a + 1).mu_.Lock(); +  bar.getFoo2(a + 1).a = 0; +  bar.getFoo2(a + 1).mu_.Unlock(); + +  (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); +  (a > 0 ? fooArray[1] : fooArray[b]).a = 0; +  (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); + +  bar.getFoo().mu_.Lock(); +  bar.getFooey().a = 0; // \ +    // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +  bar.getFoo().mu_.Unlock(); + +  bar.getFoo2(a).mu_.Lock(); +  bar.getFoo2(b).a = 0; // \ +    // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +  bar.getFoo2(a).mu_.Unlock(); + +  bar.getFoo3(a, b).mu_.Lock(); +  bar.getFoo3(a, c).a = 0;  // \ +    // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +  bar.getFoo3(a, b).mu_.Unlock(); + +  getBarFoo(bar, a).mu_.Lock(); +  getBarFoo(bar, b).a = 0;  // \ +    // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +  getBarFoo(bar, a).mu_.Unlock(); + +  (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); +  (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \ +    // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +  (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); +} + + +} // end namespace + + diff --git a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp new file mode 100644 index 0000000..c2fa1d7 --- /dev/null +++ b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -0,0 +1,1345 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s + +#define LOCKABLE            __attribute__ ((lockable)) +#define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable)) +#define GUARDED_BY(x)       __attribute__ ((guarded_by(x))) +#define GUARDED_VAR         __attribute__ ((guarded_var)) +#define PT_GUARDED_BY(x)    __attribute__ ((pt_guarded_by(x))) +#define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var)) +#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) +#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...)   __attribute__ ((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...)      __attribute__ ((shared_lock_function(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__))) +#define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__))) +#define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x))) +#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) \ +  __attribute__ ((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) \ +  __attribute__ ((shared_locks_required(__VA_ARGS__))) +#define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis)) + + +class __attribute__((lockable)) Mu { +  public: +  void Lock(); +}; + +class UnlockableMu{ +}; + +class MuWrapper { +  public: +  Mu mu; +  Mu getMu() { +    return mu; +  } +  Mu * getMuPointer() { +    return μ +  } +}; + + +class MuDoubleWrapper { +  public: +  MuWrapper* muWrapper; +  MuWrapper* getWrapper() { +    return muWrapper; +  } +}; + +Mu mu1; +UnlockableMu umu; +Mu mu2; +MuWrapper muWrapper; +MuDoubleWrapper muDoubleWrapper; +Mu* muPointer; +Mu ** muDoublePointer = & muPointer; +Mu& muRef = mu1; + +//---------------------------------------// +// Scoping tests +//--------------------------------------// + +class Foo { +  Mu foomu;     +  void needLock() __attribute__((exclusive_lock_function(foomu))); +}; + +class Foo2 { +  void needLock() __attribute__((exclusive_lock_function(foomu))); +  Mu foomu;     +}; + +class Bar { + Mu barmu; + Mu barmu2 __attribute__((acquired_after(barmu))); +}; + + +//-----------------------------------------// +//   No Thread Safety Analysis (noanal)    // +//-----------------------------------------// + +// FIXME: Right now we cannot parse attributes put on function definitions +// We would like to patch this at some point. + +#if !__has_attribute(no_thread_safety_analysis) +#error "Should support no_thread_safety_analysis attribute" +#endif + +void noanal_fun() __attribute__((no_thread_safety_analysis)); + +void noanal_fun_args() __attribute__((no_thread_safety_analysis(1))); // \ +  // expected-error {{attribute takes no arguments}} + +int noanal_testfn(int y) __attribute__((no_thread_safety_analysis)); + +int noanal_testfn(int y) { +  int x __attribute__((no_thread_safety_analysis)) = y; // \ +    // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} +  return x; +}; + +int noanal_test_var __attribute__((no_thread_safety_analysis)); // \ +  // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + +class NoanalFoo { + private: +  int test_field __attribute__((no_thread_safety_analysis)); // \ +    // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} +  void test_method() __attribute__((no_thread_safety_analysis)); +}; + +class __attribute__((no_thread_safety_analysis)) NoanalTestClass { // \ +  // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} +}; + +void noanal_fun_params(int lvar __attribute__((no_thread_safety_analysis))); // \ +  // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + + +//-----------------------------------------// +//  Guarded Var Attribute (gv) +//-----------------------------------------// + +#if !__has_attribute(guarded_var) +#error "Should support guarded_var attribute" +#endif + +int gv_var_noargs __attribute__((guarded_var)); + +int gv_var_args __attribute__((guarded_var(1))); // \ +  // expected-error {{attribute takes no arguments}} + +class GVFoo { + private: +  int gv_field_noargs __attribute__((guarded_var)); +  int gv_field_args __attribute__((guarded_var(1))); // \ +    // expected-error {{attribute takes no arguments}} +}; + +class __attribute__((guarded_var)) GV { // \ +  // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} +}; + +void gv_function() __attribute__((guarded_var)); // \ +  // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} + +void gv_function_params(int gv_lvar __attribute__((guarded_var))); // \ +  // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} + +int gv_testfn(int y){ +  int x __attribute__((guarded_var)) = y; // \ +    // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} +  return x; +} + +//-----------------------------------------// +//   Pt Guarded Var Attribute (pgv) +//-----------------------------------------// + +//FIXME: add support for boost::scoped_ptr<int> fancyptr  and references + +#if !__has_attribute(pt_guarded_var) +#error "Should support pt_guarded_var attribute" +#endif + +int *pgv_pt_var_noargs __attribute__((pt_guarded_var)); + +int pgv_var_noargs __attribute__((pt_guarded_var)); // \ +    // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} + +class PGVFoo { + private: +  int *pt_field_noargs __attribute__((pt_guarded_var)); +  int field_noargs __attribute__((pt_guarded_var)); // \ +    // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} +  int *gv_field_args __attribute__((pt_guarded_var(1))); // \ +    // expected-error {{attribute takes no arguments}} +}; + +class __attribute__((pt_guarded_var)) PGV { // \ +  // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} +}; + +int *pgv_var_args __attribute__((pt_guarded_var(1))); // \ +  // expected-error {{attribute takes no arguments}} + + +void pgv_function() __attribute__((pt_guarded_var)); // \ +  // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} + +void pgv_function_params(int *gv_lvar __attribute__((pt_guarded_var))); // \ +  // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} + +void pgv_testfn(int y){ +  int *x __attribute__((pt_guarded_var)) = new int(0); // \ +    // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} +  delete x; +} + +//-----------------------------------------// +//  Lockable Attribute (l) +//-----------------------------------------// + +//FIXME: In future we may want to add support for structs, ObjC classes, etc. + +#if !__has_attribute(lockable) +#error "Should support lockable attribute" +#endif + +class __attribute__((lockable)) LTestClass { +}; + +class __attribute__((lockable (1))) LTestClass_args { // \ +    // expected-error {{attribute takes no arguments}} +}; + +void l_test_function() __attribute__((lockable));  // \ +  // expected-warning {{'lockable' attribute only applies to classes}} + +int l_testfn(int y) { +  int x __attribute__((lockable)) = y; // \ +    // expected-warning {{'lockable' attribute only applies to classes}} +  return x; +} + +int l_test_var __attribute__((lockable)); // \ +  // expected-warning {{'lockable' attribute only applies to classes}} + +class LFoo { + private: +  int test_field __attribute__((lockable)); // \ +    // expected-warning {{'lockable' attribute only applies to classes}} +  void test_method() __attribute__((lockable)); // \ +    // expected-warning {{'lockable' attribute only applies to classes}} +}; + + +void l_function_params(int lvar __attribute__((lockable))); // \ +  // expected-warning {{'lockable' attribute only applies to classes}} + + +//-----------------------------------------// +//  Scoped Lockable Attribute (sl) +//-----------------------------------------// + +#if !__has_attribute(scoped_lockable) +#error "Should support scoped_lockable attribute" +#endif + +class __attribute__((scoped_lockable)) SLTestClass { +}; + +class __attribute__((scoped_lockable (1))) SLTestClass_args { // \ +  // expected-error {{attribute takes no arguments}} +}; + +void sl_test_function() __attribute__((scoped_lockable));  // \ +  // expected-warning {{'scoped_lockable' attribute only applies to classes}} + +int sl_testfn(int y) { +  int x __attribute__((scoped_lockable)) = y; // \ +    // expected-warning {{'scoped_lockable' attribute only applies to classes}} +  return x; +} + +int sl_test_var __attribute__((scoped_lockable)); // \ +  // expected-warning {{'scoped_lockable' attribute only applies to classes}} + +class SLFoo { + private: +  int test_field __attribute__((scoped_lockable)); // \ +    // expected-warning {{'scoped_lockable' attribute only applies to classes}} +  void test_method() __attribute__((scoped_lockable)); // \ +    // expected-warning {{'scoped_lockable' attribute only applies to classes}} +}; + + +void sl_function_params(int lvar __attribute__((scoped_lockable))); // \ +  // expected-warning {{'scoped_lockable' attribute only applies to classes}} + + +//-----------------------------------------// +//  Guarded By Attribute (gb) +//-----------------------------------------// + +// FIXME: Eventually, would we like this attribute to take more than 1 arg? + +#if !__has_attribute(guarded_by) +#error "Should support guarded_by attribute" +#endif + +//1. Check applied to the right types & argument number + +int gb_var_arg __attribute__((guarded_by(mu1))); + +int gb_var_args __attribute__((guarded_by(mu1, mu2))); // \ +  // expected-error {{attribute takes one argument}} + +int gb_var_noargs __attribute__((guarded_by)); // \ +  // expected-error {{attribute takes one argument}} + +class GBFoo { + private: +  int gb_field_noargs __attribute__((guarded_by)); // \ +    // expected-error {{attribute takes one argument}} +  int gb_field_args __attribute__((guarded_by(mu1))); +}; + +class __attribute__((guarded_by(mu1))) GB { // \ +  // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} +}; + +void gb_function() __attribute__((guarded_by(mu1))); // \ +  // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} + +void gb_function_params(int gv_lvar __attribute__((guarded_by(mu1)))); // \ +  // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} + +int gb_testfn(int y){ +  int x __attribute__((guarded_by(mu1))) = y; // \ +    // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} +  return x; +} + +//2. Check argument parsing. + +// legal attribute arguments +int gb_var_arg_1 __attribute__((guarded_by(muWrapper.mu))); +int gb_var_arg_2 __attribute__((guarded_by(muDoubleWrapper.muWrapper->mu))); +int gb_var_arg_3 __attribute__((guarded_by(muWrapper.getMu()))); +int gb_var_arg_4 __attribute__((guarded_by(*muWrapper.getMuPointer()))); +int gb_var_arg_5 __attribute__((guarded_by(&mu1))); +int gb_var_arg_6 __attribute__((guarded_by(muRef))); +int gb_var_arg_7 __attribute__((guarded_by(muDoubleWrapper.getWrapper()->getMu()))); +int gb_var_arg_8 __attribute__((guarded_by(muPointer))); + + +// illegal attribute arguments +int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \ +  // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}} +int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \ +  // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}} +int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \ +  // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}} +int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \ +  // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}} + +//3. +// Thread Safety analysis tests + + +//-----------------------------------------// +//  Pt Guarded By Attribute (pgb) +//-----------------------------------------// + +#if !__has_attribute(pt_guarded_by) +#error "Should support pt_guarded_by attribute" +#endif + +//1. Check applied to the right types & argument number + +int *pgb_var_noargs __attribute__((pt_guarded_by)); // \ +  // expected-error {{attribute takes one argument}} + +int *pgb_ptr_var_arg __attribute__((pt_guarded_by(mu1))); + +int *pgb_ptr_var_args __attribute__((guarded_by(mu1, mu2))); // \ +  // expected-error {{attribute takes one argument}} + +int pgb_var_args __attribute__((pt_guarded_by(mu1))); // \ +  // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}} + +class PGBFoo { + private: +  int *pgb_field_noargs __attribute__((pt_guarded_by)); // \ +    // expected-error {{attribute takes one argument}} +  int *pgb_field_args __attribute__((pt_guarded_by(mu1))); +}; + +class __attribute__((pt_guarded_by(mu1))) PGB { // \ +  // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} +}; + +void pgb_function() __attribute__((pt_guarded_by(mu1))); // \ +  // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} + +void pgb_function_params(int gv_lvar __attribute__((pt_guarded_by(mu1)))); // \ +  // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} + +void pgb_testfn(int y){ +  int *x __attribute__((pt_guarded_by(mu1))) = new int(0); // \ +    // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} +  delete x; +} + +//2. Check argument parsing. + +// legal attribute arguments +int * pgb_var_arg_1 __attribute__((pt_guarded_by(muWrapper.mu))); +int * pgb_var_arg_2 __attribute__((pt_guarded_by(muDoubleWrapper.muWrapper->mu))); +int * pgb_var_arg_3 __attribute__((pt_guarded_by(muWrapper.getMu()))); +int * pgb_var_arg_4 __attribute__((pt_guarded_by(*muWrapper.getMuPointer()))); +int * pgb_var_arg_5 __attribute__((pt_guarded_by(&mu1))); +int * pgb_var_arg_6 __attribute__((pt_guarded_by(muRef))); +int * pgb_var_arg_7 __attribute__((pt_guarded_by(muDoubleWrapper.getWrapper()->getMu()))); +int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer))); + + +// illegal attribute arguments +int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \ +  // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} +int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \ +  // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} +int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \ +  // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} +int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \ +  // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + +//-----------------------------------------// +//  Acquired After (aa) +//-----------------------------------------// + +// FIXME: Would we like this attribute to take more than 1 arg? + +#if !__has_attribute(acquired_after) +#error "Should support acquired_after attribute" +#endif + +Mu mu_aa __attribute__((acquired_after(mu1))); + +Mu aa_var_noargs __attribute__((acquired_after)); // \ +  // expected-error {{attribute takes at least 1 argument}} + +class AAFoo { + private: +  Mu aa_field_noargs __attribute__((acquired_after)); // \ +    // expected-error {{attribute takes at least 1 argument}} +  Mu aa_field_args __attribute__((acquired_after(mu1))); +}; + +class __attribute__((acquired_after(mu1))) AA { // \ +  // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} +}; + +void aa_function() __attribute__((acquired_after(mu1))); // \ +  // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} + +void aa_function_params(int gv_lvar __attribute__((acquired_after(mu1)))); // \ +  // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} + +void aa_testfn(int y){ +  Mu x __attribute__((acquired_after(mu1))) = Mu(); // \ +    // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} +} + +//Check argument parsing. + +// legal attribute arguments +Mu aa_var_arg_1 __attribute__((acquired_after(muWrapper.mu))); +Mu aa_var_arg_2 __attribute__((acquired_after(muDoubleWrapper.muWrapper->mu))); +Mu aa_var_arg_3 __attribute__((acquired_after(muWrapper.getMu()))); +Mu aa_var_arg_4 __attribute__((acquired_after(*muWrapper.getMuPointer()))); +Mu aa_var_arg_5 __attribute__((acquired_after(&mu1))); +Mu aa_var_arg_6 __attribute__((acquired_after(muRef))); +Mu aa_var_arg_7 __attribute__((acquired_after(muDoubleWrapper.getWrapper()->getMu()))); +Mu aa_var_arg_8 __attribute__((acquired_after(muPointer))); + + +// illegal attribute arguments +Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \ +  // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} +Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \ +  // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} +Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \ +  // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} +Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \ +  // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} +UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \ +  // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}} + +//-----------------------------------------// +//  Acquired Before (ab) +//-----------------------------------------// + +#if !__has_attribute(acquired_before) +#error "Should support acquired_before attribute" +#endif + +Mu mu_ab __attribute__((acquired_before(mu1))); + +Mu ab_var_noargs __attribute__((acquired_before)); // \ +  // expected-error {{attribute takes at least 1 argument}} + +class ABFoo { + private: +  Mu ab_field_noargs __attribute__((acquired_before)); // \ +    // expected-error {{attribute takes at least 1 argument}} +  Mu ab_field_args __attribute__((acquired_before(mu1))); +}; + +class __attribute__((acquired_before(mu1))) AB { // \ +  // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} +}; + +void ab_function() __attribute__((acquired_before(mu1))); // \ +  // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} + +void ab_function_params(int gv_lvar __attribute__((acquired_before(mu1)))); // \ +  // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} + +void ab_testfn(int y){ +  Mu x __attribute__((acquired_before(mu1))) = Mu(); // \ +    // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} +} + +// Note: illegal int ab_int __attribute__((acquired_before(mu1))) will +// be taken care of by warnings that ab__int is not lockable. + +//Check argument parsing. + +// legal attribute arguments +Mu ab_var_arg_1 __attribute__((acquired_before(muWrapper.mu))); +Mu ab_var_arg_2 __attribute__((acquired_before(muDoubleWrapper.muWrapper->mu))); +Mu ab_var_arg_3 __attribute__((acquired_before(muWrapper.getMu()))); +Mu ab_var_arg_4 __attribute__((acquired_before(*muWrapper.getMuPointer()))); +Mu ab_var_arg_5 __attribute__((acquired_before(&mu1))); +Mu ab_var_arg_6 __attribute__((acquired_before(muRef))); +Mu ab_var_arg_7 __attribute__((acquired_before(muDoubleWrapper.getWrapper()->getMu()))); +Mu ab_var_arg_8 __attribute__((acquired_before(muPointer))); + + +// illegal attribute arguments +Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \ +  // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} +Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \ +  // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} +Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \ +  // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} +Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \ +  // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} +UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \ +  // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}} + + +//-----------------------------------------// +//  Exclusive Lock Function (elf) +//-----------------------------------------// + +#if !__has_attribute(exclusive_lock_function) +#error "Should support exclusive_lock_function attribute" +#endif + +// takes zero or more arguments, all locks (vars/fields) + +void elf_function() __attribute__((exclusive_lock_function)); + +void elf_function_args() __attribute__((exclusive_lock_function(mu1, mu2))); + +int elf_testfn(int y) __attribute__((exclusive_lock_function)); + +int elf_testfn(int y) { +  int x __attribute__((exclusive_lock_function)) = y; // \ +    // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} +  return x; +}; + +int elf_test_var __attribute__((exclusive_lock_function)); // \ +  // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + +class ElfFoo { + private: +  int test_field __attribute__((exclusive_lock_function)); // \ +    // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} +  void test_method() __attribute__((exclusive_lock_function)); +}; + +class __attribute__((exclusive_lock_function)) ElfTestClass { // \ +  // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} +}; + +void elf_fun_params(int lvar __attribute__((exclusive_lock_function))); // \ +  // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + +// Check argument parsing. + +// legal attribute arguments +int elf_function_1() __attribute__((exclusive_lock_function(muWrapper.mu))); +int elf_function_2() __attribute__((exclusive_lock_function(muDoubleWrapper.muWrapper->mu))); +int elf_function_3() __attribute__((exclusive_lock_function(muWrapper.getMu()))); +int elf_function_4() __attribute__((exclusive_lock_function(*muWrapper.getMuPointer()))); +int elf_function_5() __attribute__((exclusive_lock_function(&mu1))); +int elf_function_6() __attribute__((exclusive_lock_function(muRef))); +int elf_function_7() __attribute__((exclusive_lock_function(muDoubleWrapper.getWrapper()->getMu()))); +int elf_function_8() __attribute__((exclusive_lock_function(muPointer))); +int elf_function_9(Mu x) __attribute__((exclusive_lock_function(1))); +int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2))); + + +// illegal attribute arguments +int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \ +  // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} +int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \ +  // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} +int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \ +  // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + +int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \ +  // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} +int elf_function_bad_5(Mu x) __attribute__((exclusive_lock_function(0))); // \ +  // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} +int elf_function_bad_6(Mu x, Mu y) __attribute__((exclusive_lock_function(0))); // \ +  // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} +int elf_function_bad_7() __attribute__((exclusive_lock_function(0))); // \ +  // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} + + +//-----------------------------------------// +//  Shared Lock Function (slf) +//-----------------------------------------// + +#if !__has_attribute(shared_lock_function) +#error "Should support shared_lock_function attribute" +#endif + +// takes zero or more arguments, all locks (vars/fields) + +void slf_function() __attribute__((shared_lock_function)); + +void slf_function_args() __attribute__((shared_lock_function(mu1, mu2))); + +int slf_testfn(int y) __attribute__((shared_lock_function)); + +int slf_testfn(int y) { +  int x __attribute__((shared_lock_function)) = y; // \ +    // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} +  return x; +}; + +int slf_test_var __attribute__((shared_lock_function)); // \ +  // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + +void slf_fun_params(int lvar __attribute__((shared_lock_function))); // \ +  // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + +class SlfFoo { + private: +  int test_field __attribute__((shared_lock_function)); // \ +    // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} +  void test_method() __attribute__((shared_lock_function)); +}; + +class __attribute__((shared_lock_function)) SlfTestClass { // \ +  // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} +}; + +// Check argument parsing. + +// legal attribute arguments +int slf_function_1() __attribute__((shared_lock_function(muWrapper.mu))); +int slf_function_2() __attribute__((shared_lock_function(muDoubleWrapper.muWrapper->mu))); +int slf_function_3() __attribute__((shared_lock_function(muWrapper.getMu()))); +int slf_function_4() __attribute__((shared_lock_function(*muWrapper.getMuPointer()))); +int slf_function_5() __attribute__((shared_lock_function(&mu1))); +int slf_function_6() __attribute__((shared_lock_function(muRef))); +int slf_function_7() __attribute__((shared_lock_function(muDoubleWrapper.getWrapper()->getMu()))); +int slf_function_8() __attribute__((shared_lock_function(muPointer))); +int slf_function_9(Mu x) __attribute__((shared_lock_function(1))); +int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2))); + + +// illegal attribute arguments +int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \ +  // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} +int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \ +  // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} +int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \ +  // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + +int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \ +  // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} +int slf_function_bad_5(Mu x) __attribute__((shared_lock_function(0))); // \ +  // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} +int slf_function_bad_6(Mu x, Mu y) __attribute__((shared_lock_function(0))); // \ +  // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} +int slf_function_bad_7() __attribute__((shared_lock_function(0))); // \ +  // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} + + +//-----------------------------------------// +//  Exclusive TryLock Function (etf) +//-----------------------------------------// + +#if !__has_attribute(exclusive_trylock_function) +#error "Should support exclusive_trylock_function attribute" +#endif + +// takes a mandatory boolean or integer argument specifying the retval +// plus an optional list of locks (vars/fields) + +void etf_function() __attribute__((exclusive_trylock_function));  // \ +  // expected-error {{attribute takes at least 1 argument}} + +void etf_function_args() __attribute__((exclusive_trylock_function(1, mu2))); + +void etf_function_arg() __attribute__((exclusive_trylock_function(1))); + +int etf_testfn(int y) __attribute__((exclusive_trylock_function(1))); + +int etf_testfn(int y) { +  int x __attribute__((exclusive_trylock_function(1))) = y; // \ +    // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} +  return x; +}; + +int etf_test_var __attribute__((exclusive_trylock_function(1))); // \ +  // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + +class EtfFoo { + private: +  int test_field __attribute__((exclusive_trylock_function(1))); // \ +    // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} +  void test_method() __attribute__((exclusive_trylock_function(1))); +}; + +class __attribute__((exclusive_trylock_function(1))) EtfTestClass { // \ +  // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} +}; + +void etf_fun_params(int lvar __attribute__((exclusive_trylock_function(1)))); // \ +  // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + +// Check argument parsing. + +// legal attribute arguments +int etf_function_1() __attribute__((exclusive_trylock_function(1, muWrapper.mu))); +int etf_function_2() __attribute__((exclusive_trylock_function(1, muDoubleWrapper.muWrapper->mu))); +int etf_function_3() __attribute__((exclusive_trylock_function(1, muWrapper.getMu()))); +int etf_function_4() __attribute__((exclusive_trylock_function(1, *muWrapper.getMuPointer()))); +int etf_function_5() __attribute__((exclusive_trylock_function(1, &mu1))); +int etf_function_6() __attribute__((exclusive_trylock_function(1, muRef))); +int etf_function_7() __attribute__((exclusive_trylock_function(1, muDoubleWrapper.getWrapper()->getMu()))); +int etf_functetfn_8() __attribute__((exclusive_trylock_function(1, muPointer))); +int etf_function_9() __attribute__((exclusive_trylock_function(true))); + + +// illegal attribute arguments +int etf_function_bad_1() __attribute__((exclusive_trylock_function(mu1))); // \ +  // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} +int etf_function_bad_2() __attribute__((exclusive_trylock_function("mu"))); // \ +  // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} +int etf_function_bad_3() __attribute__((exclusive_trylock_function(muDoublePointer))); // \ +  // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} + +int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \ +  // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} +int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \ +  // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} +int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \ +  // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + +//-----------------------------------------// +//  Shared TryLock Function (stf) +//-----------------------------------------// + +#if !__has_attribute(shared_trylock_function) +#error "Should support shared_trylock_function attribute" +#endif + +// takes a mandatory boolean or integer argument specifying the retval +// plus an optional list of locks (vars/fields) + +void stf_function() __attribute__((shared_trylock_function));  // \ +  // expected-error {{attribute takes at least 1 argument}} + +void stf_function_args() __attribute__((shared_trylock_function(1, mu2))); + +void stf_function_arg() __attribute__((shared_trylock_function(1))); + +int stf_testfn(int y) __attribute__((shared_trylock_function(1))); + +int stf_testfn(int y) { +  int x __attribute__((shared_trylock_function(1))) = y; // \ +    // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} +  return x; +}; + +int stf_test_var __attribute__((shared_trylock_function(1))); // \ +  // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + +void stf_fun_params(int lvar __attribute__((shared_trylock_function(1)))); // \ +  // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + + +class StfFoo { + private: +  int test_field __attribute__((shared_trylock_function(1))); // \ +    // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} +  void test_method() __attribute__((shared_trylock_function(1))); +}; + +class __attribute__((shared_trylock_function(1))) StfTestClass { // \ +    // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} +}; + +// Check argument parsing. + +// legal attribute arguments +int stf_function_1() __attribute__((shared_trylock_function(1, muWrapper.mu))); +int stf_function_2() __attribute__((shared_trylock_function(1, muDoubleWrapper.muWrapper->mu))); +int stf_function_3() __attribute__((shared_trylock_function(1, muWrapper.getMu()))); +int stf_function_4() __attribute__((shared_trylock_function(1, *muWrapper.getMuPointer()))); +int stf_function_5() __attribute__((shared_trylock_function(1, &mu1))); +int stf_function_6() __attribute__((shared_trylock_function(1, muRef))); +int stf_function_7() __attribute__((shared_trylock_function(1, muDoubleWrapper.getWrapper()->getMu()))); +int stf_function_8() __attribute__((shared_trylock_function(1, muPointer))); +int stf_function_9() __attribute__((shared_trylock_function(true))); + + +// illegal attribute arguments +int stf_function_bad_1() __attribute__((shared_trylock_function(mu1))); // \ +  // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} +int stf_function_bad_2() __attribute__((shared_trylock_function("mu"))); // \ +  // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} +int stf_function_bad_3() __attribute__((shared_trylock_function(muDoublePointer))); // \ +  // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} + +int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \ +  // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} +int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \ +  // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} +int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \ +  // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + +//-----------------------------------------// +//  Unlock Function (uf) +//-----------------------------------------// + +#if !__has_attribute(unlock_function) +#error "Should support unlock_function attribute" +#endif + +// takes zero or more arguments, all locks (vars/fields) + +void uf_function() __attribute__((unlock_function)); + +void uf_function_args() __attribute__((unlock_function(mu1, mu2))); + +int uf_testfn(int y) __attribute__((unlock_function)); + +int uf_testfn(int y) { +  int x __attribute__((unlock_function)) = y; // \ +    // expected-warning {{'unlock_function' attribute only applies to functions and methods}} +  return x; +}; + +int uf_test_var __attribute__((unlock_function)); // \ +  // expected-warning {{'unlock_function' attribute only applies to functions and methods}} + +class UfFoo { + private: +  int test_field __attribute__((unlock_function)); // \ +    // expected-warning {{'unlock_function' attribute only applies to functions and methods}} +  void test_method() __attribute__((unlock_function)); +}; + +class __attribute__((no_thread_safety_analysis)) UfTestClass { // \ +  // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} +}; + +void uf_fun_params(int lvar __attribute__((unlock_function))); // \ +  // expected-warning {{'unlock_function' attribute only applies to functions and methods}} + +// Check argument parsing. + +// legal attribute arguments +int uf_function_1() __attribute__((unlock_function(muWrapper.mu))); +int uf_function_2() __attribute__((unlock_function(muDoubleWrapper.muWrapper->mu))); +int uf_function_3() __attribute__((unlock_function(muWrapper.getMu()))); +int uf_function_4() __attribute__((unlock_function(*muWrapper.getMuPointer()))); +int uf_function_5() __attribute__((unlock_function(&mu1))); +int uf_function_6() __attribute__((unlock_function(muRef))); +int uf_function_7() __attribute__((unlock_function(muDoubleWrapper.getWrapper()->getMu()))); +int uf_function_8() __attribute__((unlock_function(muPointer))); +int uf_function_9(Mu x) __attribute__((unlock_function(1))); +int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2))); + + +// illegal attribute arguments +int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \ +  // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} +int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \ +  // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} +int uf_function_bad_4() __attribute__((unlock_function(umu))); // \ +  // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + +int uf_function_bad_1() __attribute__((unlock_function(1))); // \ +  // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} +int uf_function_bad_5(Mu x) __attribute__((unlock_function(0))); // \ +  // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} +int uf_function_bad_6(Mu x, Mu y) __attribute__((unlock_function(0))); // \ +  // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} +int uf_function_bad_7() __attribute__((unlock_function(0))); // \ +  // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} + + +//-----------------------------------------// +//  Lock Returned (lr) +//-----------------------------------------// + +#if !__has_attribute(lock_returned) +#error "Should support lock_returned attribute" +#endif + +// Takes exactly one argument, a var/field + +void lr_function() __attribute__((lock_returned)); // \ +  // expected-error {{attribute takes one argument}} + +void lr_function_arg() __attribute__((lock_returned(mu1))); + +void lr_function_args() __attribute__((lock_returned(mu1, mu2))); // \ +  // expected-error {{attribute takes one argument}} + +int lr_testfn(int y) __attribute__((lock_returned(mu1))); + +int lr_testfn(int y) { +  int x __attribute__((lock_returned(mu1))) = y; // \ +    // expected-warning {{'lock_returned' attribute only applies to functions and methods}} +  return x; +}; + +int lr_test_var __attribute__((lock_returned(mu1))); // \ +  // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + +void lr_fun_params(int lvar __attribute__((lock_returned(mu1)))); // \ +  // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + +class LrFoo { + private: +  int test_field __attribute__((lock_returned(mu1))); // \ +    // expected-warning {{'lock_returned' attribute only applies to functions and methods}} +  void test_method() __attribute__((lock_returned(mu1))); +}; + +class __attribute__((lock_returned(mu1))) LrTestClass { // \ +    // expected-warning {{'lock_returned' attribute only applies to functions and methods}} +}; + +// Check argument parsing. + +// legal attribute arguments +int lr_function_1() __attribute__((lock_returned(muWrapper.mu))); +int lr_function_2() __attribute__((lock_returned(muDoubleWrapper.muWrapper->mu))); +int lr_function_3() __attribute__((lock_returned(muWrapper.getMu()))); +int lr_function_4() __attribute__((lock_returned(*muWrapper.getMuPointer()))); +int lr_function_5() __attribute__((lock_returned(&mu1))); +int lr_function_6() __attribute__((lock_returned(muRef))); +int lr_function_7() __attribute__((lock_returned(muDoubleWrapper.getWrapper()->getMu()))); +int lr_function_8() __attribute__((lock_returned(muPointer))); + + +// illegal attribute arguments +int lr_function_bad_1() __attribute__((lock_returned(1))); // \ +  // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} +int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \ +  // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} +int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \ +  // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} +int lr_function_bad_4() __attribute__((lock_returned(umu))); // \ +  // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + + +//-----------------------------------------// +//  Locks Excluded (le) +//-----------------------------------------// + +#if !__has_attribute(locks_excluded) +#error "Should support locks_excluded attribute" +#endif + +// takes one or more arguments, all locks (vars/fields) + +void le_function() __attribute__((locks_excluded)); // \ +  // expected-error {{attribute takes at least 1 argument}} + +void le_function_arg() __attribute__((locks_excluded(mu1))); + +void le_function_args() __attribute__((locks_excluded(mu1, mu2))); + +int le_testfn(int y) __attribute__((locks_excluded(mu1))); + +int le_testfn(int y) { +  int x __attribute__((locks_excluded(mu1))) = y; // \ +    // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} +  return x; +}; + +int le_test_var __attribute__((locks_excluded(mu1))); // \ +  // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + +void le_fun_params(int lvar __attribute__((locks_excluded(mu1)))); // \ +  // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + +class LeFoo { + private: +  int test_field __attribute__((locks_excluded(mu1))); // \ +    // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} +  void test_method() __attribute__((locks_excluded(mu1))); +}; + +class __attribute__((locks_excluded(mu1))) LeTestClass { // \ +  // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} +}; + +// Check argument parsing. + +// legal attribute arguments +int le_function_1() __attribute__((locks_excluded(muWrapper.mu))); +int le_function_2() __attribute__((locks_excluded(muDoubleWrapper.muWrapper->mu))); +int le_function_3() __attribute__((locks_excluded(muWrapper.getMu()))); +int le_function_4() __attribute__((locks_excluded(*muWrapper.getMuPointer()))); +int le_function_5() __attribute__((locks_excluded(&mu1))); +int le_function_6() __attribute__((locks_excluded(muRef))); +int le_function_7() __attribute__((locks_excluded(muDoubleWrapper.getWrapper()->getMu()))); +int le_function_8() __attribute__((locks_excluded(muPointer))); + + +// illegal attribute arguments +int le_function_bad_1() __attribute__((locks_excluded(1))); // \ +  // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} +int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \ +  // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} +int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \ +  // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} +int le_function_bad_4() __attribute__((locks_excluded(umu))); // \ +  // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + + +//-----------------------------------------// +//  Exclusive Locks Required (elr) +//-----------------------------------------// + +#if !__has_attribute(exclusive_locks_required) +#error "Should support exclusive_locks_required attribute" +#endif + +// takes one or more arguments, all locks (vars/fields) + +void elr_function() __attribute__((exclusive_locks_required)); // \ +  // expected-error {{attribute takes at least 1 argument}} + +void elr_function_arg() __attribute__((exclusive_locks_required(mu1))); + +void elr_function_args() __attribute__((exclusive_locks_required(mu1, mu2))); + +int elr_testfn(int y) __attribute__((exclusive_locks_required(mu1))); + +int elr_testfn(int y) { +  int x __attribute__((exclusive_locks_required(mu1))) = y; // \ +    // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} +  return x; +}; + +int elr_test_var __attribute__((exclusive_locks_required(mu1))); // \ +  // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + +void elr_fun_params(int lvar __attribute__((exclusive_locks_required(mu1)))); // \ +  // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + +class ElrFoo { + private: +  int test_field __attribute__((exclusive_locks_required(mu1))); // \ +    // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} +  void test_method() __attribute__((exclusive_locks_required(mu1))); +}; + +class __attribute__((exclusive_locks_required(mu1))) ElrTestClass { // \ +  // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} +}; + +// Check argument parsing. + +// legal attribute arguments +int elr_function_1() __attribute__((exclusive_locks_required(muWrapper.mu))); +int elr_function_2() __attribute__((exclusive_locks_required(muDoubleWrapper.muWrapper->mu))); +int elr_function_3() __attribute__((exclusive_locks_required(muWrapper.getMu()))); +int elr_function_4() __attribute__((exclusive_locks_required(*muWrapper.getMuPointer()))); +int elr_function_5() __attribute__((exclusive_locks_required(&mu1))); +int elr_function_6() __attribute__((exclusive_locks_required(muRef))); +int elr_function_7() __attribute__((exclusive_locks_required(muDoubleWrapper.getWrapper()->getMu()))); +int elr_function_8() __attribute__((exclusive_locks_required(muPointer))); + + +// illegal attribute arguments +int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \ +  // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} +int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \ +  // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} +int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \ +  // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} +int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \ +  // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + + + +//-----------------------------------------// +//  Shared Locks Required (slr) +//-----------------------------------------// + +#if !__has_attribute(shared_locks_required) +#error "Should support shared_locks_required attribute" +#endif + +// takes one or more arguments, all locks (vars/fields) + +void slr_function() __attribute__((shared_locks_required)); // \ +  // expected-error {{attribute takes at least 1 argument}} + +void slr_function_arg() __attribute__((shared_locks_required(mu1))); + +void slr_function_args() __attribute__((shared_locks_required(mu1, mu2))); + +int slr_testfn(int y) __attribute__((shared_locks_required(mu1))); + +int slr_testfn(int y) { +  int x __attribute__((shared_locks_required(mu1))) = y; // \ +    // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} +  return x; +}; + +int slr_test_var __attribute__((shared_locks_required(mu1))); // \ +  // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + +void slr_fun_params(int lvar __attribute__((shared_locks_required(mu1)))); // \ +  // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + +class SlrFoo { + private: +  int test_field __attribute__((shared_locks_required(mu1))); // \ +    // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} +  void test_method() __attribute__((shared_locks_required(mu1))); +}; + +class __attribute__((shared_locks_required(mu1))) SlrTestClass { // \ +  // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} +}; + +// Check argument parsing. + +// legal attribute arguments +int slr_function_1() __attribute__((shared_locks_required(muWrapper.mu))); +int slr_function_2() __attribute__((shared_locks_required(muDoubleWrapper.muWrapper->mu))); +int slr_function_3() __attribute__((shared_locks_required(muWrapper.getMu()))); +int slr_function_4() __attribute__((shared_locks_required(*muWrapper.getMuPointer()))); +int slr_function_5() __attribute__((shared_locks_required(&mu1))); +int slr_function_6() __attribute__((shared_locks_required(muRef))); +int slr_function_7() __attribute__((shared_locks_required(muDoubleWrapper.getWrapper()->getMu()))); +int slr_function_8() __attribute__((shared_locks_required(muPointer))); + + +// illegal attribute arguments +int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \ +  // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} +int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \ +  // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} +int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \ +  // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} +int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \ +  // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} + + +//-----------------------------------------// +//  Regression tests for unusual cases. +//-----------------------------------------// + +int trivially_false_edges(bool b) { +  // Create NULL (never taken) edges in CFG +  if (false) return 1; +  else       return 2; +} + +// Possible Clang bug -- method pointer in template parameter +class UnFoo { +public: +  void foo(); +}; + +template<void (UnFoo::*methptr)()> +class MCaller { +public: +  static void call_method_ptr(UnFoo *f) { +    // FIXME: Possible Clang bug: +    // getCalleeDecl() returns NULL in the following case: +    (f->*methptr)(); +  } +}; + +void call_method_ptr_inst(UnFoo* f) { +  MCaller<&UnFoo::foo>::call_method_ptr(f); +} + +int temp; +void empty_back_edge() { +  // Create a back edge to a block with with no statements +  for (;;) { +    ++temp; +    if (temp > 10) break; +  } +} + +struct Foomger { +  void operator++(); +}; + +struct Foomgoper { +  Foomger f; + +  bool done(); +  void invalid_back_edge() { +    do { +      // FIXME: Possible Clang bug: +      // The first statement in this basic block has no source location +      ++f; +    } while (!done()); +  } +}; + + +//----------------------------------------------------- +// Parsing of member variables and function parameters +//------------------------------------------------------ + +Mu gmu; + +class StaticMu { +  static Mu statmu; +}; + +class FooLate { +public: +  void foo1()           __attribute__((exclusive_locks_required(gmu)))   { } +  void foo2()           __attribute__((exclusive_locks_required(mu)))    { } +  void foo3(Mu *m)      __attribute__((exclusive_locks_required(m)))     { } +  void foo3(FooLate *f) __attribute__((exclusive_locks_required(f->mu))) { } +  void foo4(FooLate *f) __attribute__((exclusive_locks_required(f->mu))); + +  static void foo5()    __attribute__((exclusive_locks_required(mu))); // \ +    // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + +  template <class T> +  void foo6() __attribute__((exclusive_locks_required(T::statmu))) { } + +  template <class T> +  void foo7(T* f) __attribute__((exclusive_locks_required(f->mu))) { } + +  int a __attribute__((guarded_by(gmu))); +  int b __attribute__((guarded_by(mu))); +  int c __attribute__((guarded_by(this->mu))); + +  Mu mu; +}; + +//------------------------- +// Empty argument lists +//------------------------- + +class __attribute__((lockable)) EmptyArgListsTest { +  void lock() __attribute__((exclusive_lock_function())) { } +  void unlock() __attribute__((unlock_function())) { } +}; + + +namespace FunctionDefinitionParseTest { +// Test parsing of attributes on function definitions. + +class Foo { +public: +  Mu mu_; +  void foo1(); +  void foo2(Foo *f); +}; + +template <class T> +class Bar { +public: +  Mu mu_; +  void bar(); +}; + +void Foo::foo1()       __attribute__((exclusive_locks_required(mu_))) { } +void Foo::foo2(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { } + +template <class T> +void Bar<T>::bar() __attribute__((exclusive_locks_required(mu_))) { } + +void baz(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { } + +} // end namespace + + +namespace TestMultiDecl { + +class Foo { +public: +  int __attribute__((guarded_by(mu_))) a; +  int __attribute__((guarded_by(mu_))) b, c; + +private: +  Mu mu_; +}; + + +namespace NestedClassLateDecl { + +class Foo { +  class Bar { +    int a GUARDED_BY(mu); +    int b GUARDED_BY(fooMuStatic); + +    void bar()        EXCLUSIVE_LOCKS_REQUIRED(mu)       { a = 0;    } +    void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu)    { b->a = 0; } +    void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; } + +    Mu mu; +  }; + +  int a GUARDED_BY(fooMu); +  Mu fooMu; +  static Mu fooMuStatic; +}; + +} + +} // end namespace TestMultiDecl + diff --git a/clang/test/SemaCXX/warn-unreachable.cpp b/clang/test/SemaCXX/warn-unreachable.cpp new file mode 100644 index 0000000..f36300a --- /dev/null +++ b/clang/test/SemaCXX/warn-unreachable.cpp @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -Wunreachable-code -Wno-unused-value + +int &halt() __attribute__((noreturn)); +int &live(); +int dead(); +int liveti() throw(int); +int (*livetip)() throw(int); + +int test1() { +  try { +    live(); +  } catch (int i) { +    live(); +  } +  return 1; +} + +void test2() { +  try { +    live(); +  } catch (int i) { +    live(); +  } +  try { +    liveti(); +  } catch (int i) { +    live(); +  } +  try { +    livetip(); +  } catch (int i) { +    live(); +  } +  throw 1; +  dead();       // expected-warning {{will never be executed}} +} + + +void test3() { +  halt() +    --;         // expected-warning {{will never be executed}} +  // FIXME: The unreachable part is just the '?', but really all of this +  // code is unreachable and shouldn't be separately reported. +  halt()        // expected-warning {{will never be executed}} +    ?  +    dead() : dead(); +  live(), +    float        +      (halt()); // expected-warning {{will never be executed}} +} + +void test4() { +  struct S { +    int mem; +  } s; +  S &foor(); +  halt(), foor()// expected-warning {{will never be executed}} +    .mem;        +} + +void test5() { +  struct S { +    int mem; +  } s; +  S &foor() __attribute__((noreturn)); +  foor() +    .mem;       // expected-warning {{will never be executed}} +} + +void test6() { +  struct S { +    ~S() { } +    S(int i) { } +  }; +  live(), +    S +      (halt());  // expected-warning {{will never be executed}} +} + +// Don't warn about unreachable code in template instantiations, as +// they may only be unreachable in that specific instantiation. +void isUnreachable(); + +template <typename T> void test_unreachable_templates() { +  T::foo(); +  isUnreachable();  // no-warning +} + +struct TestUnreachableA { +  static void foo() __attribute__((noreturn)); +}; +struct TestUnreachableB { +  static void foo(); +}; + +void test_unreachable_templates_harness() { +  test_unreachable_templates<TestUnreachableA>(); +  test_unreachable_templates<TestUnreachableB>();  +} + +// Do warn about explict template specializations, as they represent +// actual concrete functions that somebody wrote. + +template <typename T> void funcToSpecialize() {} +template <> void funcToSpecialize<int>() { +  halt(); +  dead(); // expected-warning {{will never be executed}} +} + diff --git a/clang/test/SemaCXX/warn-unused-comparison.cpp b/clang/test/SemaCXX/warn-unused-comparison.cpp new file mode 100644 index 0000000..0153f21 --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-comparison.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -Wno-unused -Wunused-comparison %s + +struct A { +  bool operator==(const A&); +  bool operator!=(const A&); +  A operator|=(const A&); +  operator bool(); +}; + +void test() { +  int x, *p; +  A a, b; + +  x == 7; // expected-warning {{equality comparison result unused}} \ +          // expected-note {{use '=' to turn this equality comparison into an assignment}} +  x != 7; // expected-warning {{inequality comparison result unused}} \ +          // expected-note {{use '|=' to turn this inequality comparison into an or-assignment}} +  7 == x; // expected-warning {{equality comparison result unused}} +  p == p; // expected-warning {{equality comparison result unused}} \ +          // expected-note {{use '=' to turn this equality comparison into an assignment}} \ +          // expected-warning {{self-comparison always evaluates to true}} +  a == a; // expected-warning {{equality comparison result unused}} \ +          // expected-note {{use '=' to turn this equality comparison into an assignment}} +  a == b; // expected-warning {{equality comparison result unused}} \ +          // expected-note {{use '=' to turn this equality comparison into an assignment}} +  a != b; // expected-warning {{inequality comparison result unused}} \ +          // expected-note {{use '|=' to turn this inequality comparison into an or-assignment}} +  A() == b; // expected-warning {{equality comparison result unused}} +  if (42) x == 7; // expected-warning {{equality comparison result unused}} \ +                  // expected-note {{use '=' to turn this equality comparison into an assignment}} +  else if (42) x == 7; // expected-warning {{equality comparison result unused}} \ +                       // expected-note {{use '=' to turn this equality comparison into an assignment}} +  else x == 7; // expected-warning {{equality comparison result unused}} \ +               // expected-note {{use '=' to turn this equality comparison into an assignment}} +  do x == 7; // expected-warning {{equality comparison result unused}} \ +             // expected-note {{use '=' to turn this equality comparison into an assignment}} +  while (false); +  while (false) x == 7; // expected-warning {{equality comparison result unused}} \ +                        // expected-note {{use '=' to turn this equality comparison into an assignment}} +  for (x == 7; // expected-warning {{equality comparison result unused}} \ +               // expected-note {{use '=' to turn this equality comparison into an assignment}} +       x == 7; // No warning -- result is used +       x == 7) // expected-warning {{equality comparison result unused}} \ +               // expected-note {{use '=' to turn this equality comparison into an assignment}} +    x == 7; // expected-warning {{equality comparison result unused}} \ +            // expected-note {{use '=' to turn this equality comparison into an assignment}} +  switch (42) default: x == 7; // expected-warning {{equality comparison result unused}} \ +                               // expected-note {{use '=' to turn this equality comparison into an assignment}} +  switch (42) case 42: x == 7; // expected-warning {{equality comparison result unused}} \ +                               // expected-note {{use '=' to turn this equality comparison into an assignment}} +  switch (42) { +    case 1: +    case 2: +    default: +    case 3: +    case 4: +      x == 7; // expected-warning {{equality comparison result unused}} \ +              // expected-note {{use '=' to turn this equality comparison into an assignment}} +  } + +  (void)(x == 7); +  (void)(p == p); // expected-warning {{self-comparison always evaluates to true}} +  { bool b = x == 7; } + +  { bool b = ({ x == 7; // expected-warning {{equality comparison result unused}} \ +                        // expected-note {{use '=' to turn this equality comparison into an assignment}} +                x == 7; }); } // no warning on the second, its result is used! + +#define EQ(x,y) (x) == (y) +  EQ(x, 5); +#undef EQ +} + +namespace PR10291 { +  template<typename T> +  class X +  { +  public: + +    X() : i(0) { }  + +    void foo() +    {    +      throw  +        i == 0u ? +        5 : 6; +    }    + +  private: +    int i; +  }; + +  X<int> x; +} diff --git a/clang/test/SemaCXX/warn-unused-filescoped.cpp b/clang/test/SemaCXX/warn-unused-filescoped.cpp new file mode 100644 index 0000000..dbff4b0 --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-filescoped.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function %s + +static void f1(); // expected-warning{{unused}} + +namespace { +  void f2();  // expected-warning{{unused}} + +  void f3() { }  // expected-warning{{unused}} + +  struct S { +    void m1() { }  // expected-warning{{unused}} +    void m2();  // expected-warning{{unused}} +    void m3(); +    S(const S&); +    void operator=(const S&); +  }; + +  template <typename T> +  struct TS { +    void m(); +  }; +  template <> void TS<int>::m() { }  // expected-warning{{unused}} + +  template <typename T> +  void tf() { } +  template <> void tf<int>() { }  // expected-warning{{unused}} +   +  struct VS { +    virtual void vm() { } +  }; +   +  struct SVS : public VS { +    void vm() { } +  }; +} + +void S::m3() { }  // expected-warning{{unused}} + +static inline void f4() { } +const unsigned int cx = 0; + +static int x1;  // expected-warning{{unused}} + +namespace { +  int x2;  // expected-warning{{unused}} +   +  struct S2 { +    static int x;  // expected-warning{{unused}} +  }; + +  template <typename T> +  struct TS2 { +    static int x; +  }; +  template <> int TS2<int>::x;  // expected-warning{{unused}} +} + +namespace PR8841 { +  // Ensure that friends of class templates are considered to have a dependent +  // context and not marked unused. +  namespace { +    template <typename T> struct X { +      friend bool operator==(const X&, const X&) { return false; } +    }; +  } +  template <typename T> void template_test(X<T> x) { +    (void)(x == x); +  } +  void test() { +    X<int> x; +    template_test(x); +  } +} + +namespace test4 { +  namespace { struct A {}; } + +  void test(A a); // expected-warning {{unused function}} +  extern "C" void test4(A a); +} + +namespace rdar8733476 { +  static void foo() { } // expected-warning {{not needed and will not be emitted}} + +  template <int> +  void bar() { +    foo(); +  } +} diff --git a/clang/test/SemaCXX/warn-unused-parameters.cpp b/clang/test/SemaCXX/warn-unused-parameters.cpp new file mode 100644 index 0000000..00ce1a9 --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-parameters.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify -std=c++11 %s +template<typename T> +struct X { +  T f0(T x); +  T f1(T x); +  T f2(T); +  template<typename U> U f3(U x); +  template<typename U> U f4(U x); +  template<typename U> U f5(U); +}; + +template<typename T> T X<T>::f0(T x) { return x; } +template<typename T> T X<T>::f1(T) { return T(); } +template<typename T> T X<T>::f2(T x) { return T(); } // expected-warning{{unused parameter 'x'}} +template<typename T> template<typename U> U X<T>::f3(U x) { return x; } +template<typename T> template<typename U> U X<T>::f4(U) { return U(); } +template<typename T> template<typename U> U X<T>::f5(U x) { return U(); } // expected-warning{{unused parameter 'x'}} + +void test_X(X<int> &x, int i) { +  x.f0(i); +  x.f1(i); +  x.f2(i); +  x.f3(i); +  x.f4(i); +  x.f5(i); +} + +// Make sure both parameters aren't considered unused. +template <typename... T> +static int test_pack(T... t, T... s) +{ +  auto l = [&t...]() { return sizeof...(s); }; +  return l(); +} diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp new file mode 100644 index 0000000..d14fdf9 --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int f() __attribute__((warn_unused_result)); + +struct S { +  void t() const; +}; +S g1() __attribute__((warn_unused_result)); +S *g2() __attribute__((warn_unused_result)); +S &g3() __attribute__((warn_unused_result)); + +void test() { +  f(); // expected-warning {{ignoring return value}} +  g1(); // expected-warning {{ignoring return value}} +  g2(); // expected-warning {{ignoring return value}} +  g3(); // expected-warning {{ignoring return value}} + +  (void)f(); +  (void)g1(); +  (void)g2(); +  (void)g3(); + +  if (f() == 0) return; + +  g1().t(); +  g2()->t(); +  g3().t(); + +  int i = f(); +  S s1 = g1(); +  S *s2 = g2(); +  S &s3 = g3(); +  const S &s4 = g1(); +} + +struct X { + int foo() __attribute__((warn_unused_result)); +}; + +void bah() { +  X x, *x2; +  x.foo(); // expected-warning {{ignoring return value}} +  x2->foo(); // expected-warning {{ignoring return value}} +} diff --git a/clang/test/SemaCXX/warn-unused-value.cpp b/clang/test/SemaCXX/warn-unused-value.cpp new file mode 100644 index 0000000..1c0263c --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-value.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s + +// PR4806 +namespace test0 { +  class Box { +  public: +    int i; +    volatile int j; +  }; + +  void doit() { +    // pointer to volatile has side effect (thus no warning) +    Box* box = new Box; +    box->i; // expected-warning {{expression result unused}} +    box->j; +  } +} + +namespace test1 { +struct Foo { +  int i; +  bool operator==(const Foo& rhs) { +    return i == rhs.i; +  } +}; + +#define NOP(x) (x) +void b(Foo f1, Foo f2) { +  NOP(f1 == f2);  // expected-warning {{expression result unused}} +} +#undef NOP +} + +namespace test2 { +  extern "C" { +    namespace std { +      template<typename T> struct basic_string { +        struct X {}; +        void method() const { +         X* x; +         &x[0];  // expected-warning {{expression result unused}} +        }   +      }; +      typedef basic_string<char> string; +      void func(const std::string& str) {  +        str.method();  // expected-note {{in instantiation of member function}} +      } +    }  +  } +} + diff --git a/clang/test/SemaCXX/warn-unused-variables.cpp b/clang/test/SemaCXX/warn-unused-variables.cpp new file mode 100644 index 0000000..5827019 --- /dev/null +++ b/clang/test/SemaCXX/warn-unused-variables.cpp @@ -0,0 +1,124 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s +template<typename T> void f() { +  T t; +  t = 17; +} + +// PR5407 +struct A { A(); }; +struct B { ~B(); }; +void f() { +  A a; +  B b; +} + +// PR5531 +namespace PR5531 { +  struct A { +  }; + +  struct B { +    B(int); +  }; + +  struct C { +    ~C(); +  }; + +  void test() { +    A(); +    B(17); +    C(); +  } +} + +template<typename T> +struct X0 { }; + +template<typename T> +void test_dependent_init(T *p) { +  X0<int> i(p); +  (void)i; +} + +namespace PR6948 { +  template<typename T> class X; +   +  void f() { +    X<char> str (read_from_file()); // expected-error{{use of undeclared identifier 'read_from_file'}} +  } +} + +void unused_local_static() { +  static int x = 0; +  static int y = 0; // expected-warning{{unused variable 'y'}} +#pragma unused(x) +} + +// PR10168 +namespace PR10168 { +  // We expect a warning in the definition only for non-dependent variables, and +  // a warning in the instantiation only for dependent variables. +  template<typename T> +  struct S { +    void f() { +      int a; // expected-warning {{unused variable 'a'}} +      T b; // expected-warning 2{{unused variable 'b'}} +    } +  }; + +  template<typename T> +  void f() { +    int a; // expected-warning {{unused variable 'a'}} +    T b; // expected-warning 2{{unused variable 'b'}} +  } + +  void g() { +    S<int>().f(); // expected-note {{here}} +    S<char>().f(); // expected-note {{here}} +    f<int>(); // expected-note {{here}} +    f<char>(); // expected-note {{here}} +  } +} + +namespace PR11550 { +  struct S1 { +    S1(); +  }; +  S1 makeS1(); +  void testS1(S1 a) { +    // This constructor call can be elided. +    S1 x = makeS1(); // expected-warning {{unused variable 'x'}} + +    // This one cannot, so no warning. +    S1 y; + +    // This call cannot, but the constructor is trivial. +    S1 z = a; // expected-warning {{unused variable 'z'}} +  } + +  // The same is true even when we know thet constructor has side effects. +  void foo(); +  struct S2 { +    S2() { +      foo(); +    } +  }; +  S2 makeS2(); +  void testS2(S2 a) { +    S2 x = makeS2(); // expected-warning {{unused variable 'x'}} +    S2 y; +    S2 z = a; // expected-warning {{unused variable 'z'}} +  } + +  // Or when the constructor is not declared by the user. +  struct S3 { +    S1 m; +  }; +  S3 makeS3(); +  void testS3(S3 a) { +    S3 x = makeS3(); // expected-warning {{unused variable 'x'}} +    S3 y; +    S3 z = a; // expected-warning {{unused variable 'z'}} +  } +} diff --git a/clang/test/SemaCXX/warn-using-namespace-in-header.cpp b/clang/test/SemaCXX/warn-using-namespace-in-header.cpp new file mode 100644 index 0000000..72c2552 --- /dev/null +++ b/clang/test/SemaCXX/warn-using-namespace-in-header.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -fsyntax-only -Wheader-hygiene -verify %s + +#include "warn-using-namespace-in-header.h" + +namespace dont_warn {} +using namespace dont_warn; + +// Warning is actually in the header but only the cpp file gets scanned. +// expected-warning {{using namespace directive in global context in header}} + + + + + + + + + +// Warn inside linkage specs too. +// expected-warning {{using namespace directive in global context in header}} + + + + + + +// expected-warning {{using namespace directive in global context in header}} + + + + + + + + + + + + + + + + + + + + + + +// expected-warning {{using namespace directive in global context in header}} + +// |using namespace| through a macro shouldn't warn if the instantiation is in a +// cc file. +USING_MACRO diff --git a/clang/test/SemaCXX/warn-using-namespace-in-header.h b/clang/test/SemaCXX/warn-using-namespace-in-header.h new file mode 100644 index 0000000..b544c54 --- /dev/null +++ b/clang/test/SemaCXX/warn-using-namespace-in-header.h @@ -0,0 +1,50 @@ + + + + + +// Lots of vertical space to make the error line match up with the line of the +// expected line in the source file. +namespace warn_in_header_in_global_context {} +using namespace warn_in_header_in_global_context; + +// While we want to error on the previous using directive, we don't when we are +// inside a namespace +namespace dont_warn_here { +using namespace warn_in_header_in_global_context; +} + +// We should warn in toplevel extern contexts. +namespace warn_inside_linkage {} +extern "C++" { +using namespace warn_inside_linkage; +} + +// This is really silly, but we should warn on it: +extern "C++" { +extern "C" { +extern "C++" { +using namespace warn_inside_linkage; +} +} +} + +// But we shouldn't warn in extern contexts inside namespaces. +namespace dont_warn_here { +extern "C++" { +using namespace warn_in_header_in_global_context; +} +} + +// We also shouldn't warn in case of functions. +inline void foo() { +  using namespace warn_in_header_in_global_context; +} + + +namespace macronamespace {} +#define USING_MACRO using namespace macronamespace; + +// |using namespace| through a macro should warn if the instantiation is in a +// header. +USING_MACRO diff --git a/clang/test/SemaCXX/warn-weak-vtables.cpp b/clang/test/SemaCXX/warn-weak-vtables.cpp new file mode 100644 index 0000000..135e034 --- /dev/null +++ b/clang/test/SemaCXX/warn-weak-vtables.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables -Wweak-template-vtables + +struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} +  virtual void f() { }  +}; + +template<typename T> struct B { +  virtual void f() { }  +}; + +namespace { +  struct C {  +    virtual void f() { } +  }; +} + +void f() { +  struct A { +    virtual void f() { } +  }; + +  A *a; +  a->f(); +} + +// Use the vtables +void uses(A &a, B<int> &b, C &c) { +  a.f(); +  b.f(); +  c.f(); +} + +// <rdar://problem/9979458> +class Parent { +public: +  Parent() {} +  virtual ~Parent(); +  virtual void * getFoo() const = 0;     +}; +   +class Derived : public Parent { +public: +  Derived(); +  void * getFoo() const; +}; + +class VeryDerived : public Derived { // expected-warning{{'VeryDerived' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} +public: +  void * getFoo() const { return 0; } +}; + +Parent::~Parent() {} + +void uses(Parent &p, Derived &d, VeryDerived &vd) { +  p.getFoo(); +  d.getFoo(); +  vd.getFoo(); +} + +template<typename T> struct TemplVirt { +  virtual void f(); +}; + +template class TemplVirt<float>; // expected-warning{{explicit template instantiation 'TemplVirt<float>' will emit a vtable in every translation unit}} + +template<> struct TemplVirt<bool> { +  virtual void f(); +}; + +template<> struct TemplVirt<long> { // expected-warning{{'TemplVirt<long>' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} +  virtual void f() {} +}; + +void uses(TemplVirt<float>& f, TemplVirt<bool>& b, TemplVirt<long>& l) { +  f.f(); +  b.f(); +  l.f(); +} diff --git a/clang/test/SemaCXX/wchar_t.cpp b/clang/test/SemaCXX/wchar_t.cpp new file mode 100644 index 0000000..f9d7b61 --- /dev/null +++ b/clang/test/SemaCXX/wchar_t.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s  +wchar_t x; + +void f(wchar_t p) { +  wchar_t x; +  unsigned wchar_t y; // expected-warning {{'wchar_t' cannot be signed or unsigned}} +  signed wchar_t z; // expected-warning {{'wchar_t' cannot be signed or unsigned}} +  ++x; +} + +// PR4502 +wchar_t const c = L'c'; +int a[c == L'c' ? 1 : -1]; + + +// PR5917 +template<typename _CharT> +struct basic_string { +}; + +template<typename _CharT> +basic_string<_CharT> operator+ (const basic_string<_CharT>&, _CharT); + +int t(void) { +  basic_string<wchar_t>() + L'-'; +  return (0); +} + + +// rdar://8040728 +wchar_t in[] = L"\x434" "\x434";  // No warning + diff --git a/clang/test/SemaCXX/writable-strings-deprecated.cpp b/clang/test/SemaCXX/writable-strings-deprecated.cpp new file mode 100644 index 0000000..8295401 --- /dev/null +++ b/clang/test/SemaCXX/writable-strings-deprecated.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-deprecated-writable-strings -verify %s +// RUN: %clang_cc1 -fsyntax-only -fwritable-strings -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wno-write-strings -verify %s +// rdar://8827606 + +char *fun(void) +{ +   return "foo"; +} + +void test(bool b) +{ +  ++b; // expected-warning {{incrementing expression of type bool is deprecated}} +} diff --git a/clang/test/SemaCXX/zero-length-arrays.cpp b/clang/test/SemaCXX/zero-length-arrays.cpp new file mode 100644 index 0000000..05ded4a --- /dev/null +++ b/clang/test/SemaCXX/zero-length-arrays.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/10228639> +class Foo { +  ~Foo(); +  Foo(const Foo&); +public: +  Foo(int); +}; + +class Bar { +  int foo_count; +  Foo foos[0]; +  Foo foos2[0][2]; +  Foo foos3[2][0]; + +public: +  Bar(): foo_count(0) { }     +  ~Bar() { } +}; + +void testBar() { +  Bar b; +  Bar b2(b); +  b = b2; +}  | 
