diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/SemaCXX | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
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; +} |