diff options
Diffstat (limited to 'test/SemaCXX')
145 files changed, 4525 insertions, 449 deletions
diff --git a/test/SemaCXX/2008-01-11-BadWarning.cpp b/test/SemaCXX/2008-01-11-BadWarning.cpp new file mode 100644 index 000000000000..b84e7c1cf862 --- /dev/null +++ b/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/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp new file mode 100644 index 000000000000..dfc47d6fc956 --- /dev/null +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -0,0 +1,158 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -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 {{illegal 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 initialization}} + 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 {{illegal 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 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 refers to inaccessible member 'ms_using_declaration_bug::B::f', which refers to accessible member 'ms_using_declaration_bug::A::f', accepted for Microsoft compatibility}}
+};
+
+}
+
+
+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);
+
+}
+
+
+
+namespace lookup_dependent_bases_id_expr {
+
+template<class T> class A {
+public:
+ int var;
+};
+
+
+template<class T>
+class B : public A<T> {
+public:
+ void f() {
+ var = 3;
+ }
+};
+
+template class B<int>;
+
+}
\ No newline at end of file diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 9b03feb53909..63e058b36daa 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -81,6 +81,10 @@ struct M { float __stdcall subtractP(); }; +// __unaligned handling +typedef char __unaligned *aligned_type; + + template<typename T> void h1(T (__stdcall M::* const )()) { } void m1() { @@ -148,40 +152,6 @@ template <class T> void BB<T>::f(int g = 0) { } // expected-warning {{redefinition of default argument}} -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}} - }; - -} - - - extern void static_func(); void static_func(); // expected-note {{previous declaration is here}} @@ -209,26 +179,6 @@ void pointer_to_integral_type_conv(char* ptr) { sh = (short)ptr; } -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 refers to inaccessible member 'ms_using_declaration_bug::B::f', which refers to accessible member 'ms_using_declaration_bug::A::f', accepted for Microsoft compatibility}} -}; - -} - - namespace friend_as_a_forward_decl { @@ -251,4 +201,5 @@ void f() Z* b; } - }
\ No newline at end of file +} + diff --git a/test/SemaCXX/PR10243.cpp b/test/SemaCXX/PR10243.cpp index 9a5851049803..129ff80e2d2e 100644 --- a/test/SemaCXX/PR10243.cpp +++ b/test/SemaCXX/PR10243.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s struct S; // expected-note 4{{forward declaration of 'S'}} diff --git a/test/SemaCXX/PR10458.cpp b/test/SemaCXX/PR10458.cpp new file mode 100644 index 000000000000..57588ebcf1f0 --- /dev/null +++ b/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/test/SemaCXX/PR5086-ambig-resolution-enum.cpp b/test/SemaCXX/PR5086-ambig-resolution-enum.cpp index 720566a69b05..b5aac5f09c16 100644 --- a/test/SemaCXX/PR5086-ambig-resolution-enum.cpp +++ b/test/SemaCXX/PR5086-ambig-resolution-enum.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 class C { public: diff --git a/test/SemaCXX/PR7944.cpp b/test/SemaCXX/PR7944.cpp index a998a15c3e0b..51b3f6bccec0 100644 --- a/test/SemaCXX/PR7944.cpp +++ b/test/SemaCXX/PR7944.cpp @@ -8,5 +8,5 @@ struct A { B* b() { return new B; } }; void g() { A a; - MACRO(a.b->f()); // expected-error{{base of member reference is a function}} + 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/test/SemaCXX/PR8012.cpp b/test/SemaCXX/PR8012.cpp index f2f07ad36400..9cfc2b000c01 100644 --- a/test/SemaCXX/PR8012.cpp +++ b/test/SemaCXX/PR8012.cpp @@ -1,3 +1,3 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// 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/test/SemaCXX/PR9572.cpp b/test/SemaCXX/PR9572.cpp index 25c0c017b7f6..b0bbfa6318cd 100644 --- a/test/SemaCXX/PR9572.cpp +++ b/test/SemaCXX/PR9572.cpp @@ -3,7 +3,7 @@ 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 {{accepted as a C++0x extension}} + const int kBlah = 3; // expected-warning {{accepted as a C++11 extension}} Foo(); }; struct Bar : public Foo { diff --git a/test/SemaCXX/PR9902.cpp b/test/SemaCXX/PR9902.cpp index ec76789b9657..80086e445c5d 100644 --- a/test/SemaCXX/PR9902.cpp +++ b/test/SemaCXX/PR9902.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template <class _Tp, class _Up, bool = false> struct __allocator_traits_rebind diff --git a/test/SemaCXX/PR9908.cpp b/test/SemaCXX/PR9908.cpp index 3b98b724dd87..fc090cc42f92 100644 --- a/test/SemaCXX/PR9908.cpp +++ b/test/SemaCXX/PR9908.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template <class _Tp, class _Up> struct __allocator_traits_rebind diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index c262230962f9..b164d9eda6a5 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 #ifndef __GXX_EXPERIMENTAL_CXX0X__ #define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) diff --git a/test/SemaCXX/address-of.cpp b/test/SemaCXX/address-of.cpp index a7e712b04c1d..69fcaff8f1ed 100644 --- a/test/SemaCXX/address-of.cpp +++ b/test/SemaCXX/address-of.cpp @@ -33,3 +33,14 @@ void test2() { // 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/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index b9e69b00b7fe..3c0e4483c441 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // Verify that we can't initialize non-aggregates with an initializer // list. -// FIXME: Note that due to a (likely) standard bug, this is technically an -// aggregate. +// Note that due to a (likely) standard bug, this is technically an aggregate, +// but we do not treat it as one. struct NonAggr1 { NonAggr1(int) { } @@ -24,7 +24,7 @@ struct NonAggr4 { virtual void f(); }; -NonAggr1 na1 = { 17 }; +NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}} NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}} NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}} NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}} diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index f29a9327dab3..6cff4206faa4 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/test/SemaCXX/alias-template.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -std=c++0x %s +// RUN: %clang_cc1 -verify -std=c++11 %s namespace RedeclAliasTypedef { template<typename U> using T = int; diff --git a/test/SemaCXX/alignof-sizeof-reference.cpp b/test/SemaCXX/alignof-sizeof-reference.cpp index 93ba203ae112..ccdf45e52dd7 100644 --- a/test/SemaCXX/alignof-sizeof-reference.cpp +++ b/test/SemaCXX/alignof-sizeof-reference.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// 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}} @@ -8,14 +8,15 @@ void test() { static_assert(sizeof(r) == 1, "bad size"); } -void f(); // expected-note{{candidate function}} -void f(int); // expected-note{{candidate function}} +void f(); // expected-note{{possible target for call}} +void f(int); // expected-note{{possible target for call}} void g() { - sizeof(&f); // expected-error{{cannot resolve overloaded function 'f' from context}} + 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{{candidate function}} -template<typename T> void f_template(T*); // expected-note{{candidate function}} +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{{cannot resolve overloaded function 'f_template' from context}} + (void)alignof(f_template<int>); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } diff --git a/test/SemaCXX/ambig-user-defined-conversions.cpp b/test/SemaCXX/ambig-user-defined-conversions.cpp index bf45e5d4d888..1a3c102f034c 100644 --- a/test/SemaCXX/ambig-user-defined-conversions.cpp +++ b/test/SemaCXX/ambig-user-defined-conversions.cpp @@ -53,7 +53,7 @@ namespace test1 { 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. + // b -> A via constructor or conversion function. } } diff --git a/test/SemaCXX/ambiguous-builtin-unary-operator.cpp b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp index 836e319f8404..6e96e03f7245 100644 --- a/test/SemaCXX/ambiguous-builtin-unary-operator.cpp +++ b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct A { operator int&(); diff --git a/test/SemaCXX/array-bounds-ptr-arith.cpp b/test/SemaCXX/array-bounds-ptr-arith.cpp new file mode 100644 index 000000000000..ce1ace6f2fb6 --- /dev/null +++ b/test/SemaCXX/array-bounds-ptr-arith.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -verify -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/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp index 3bd6c35420d7..555ac33af559 100644 --- a/test/SemaCXX/array-bounds.cpp +++ b/test/SemaCXX/array-bounds.cpp @@ -3,9 +3,11 @@ 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 *p = &y[2]; // no-warning (void) sizeof(x[2]); // no-warning y[2] = 2; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} + z[1] = 'x'; // expected-warning {{array index of '1' indexes past the end of an array (that contains 1 element)}} return x[2] + // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} y[-1] + // expected-warning {{array index of '-1' indexes before the beginning of the array}} x[sizeof(x)] + // expected-warning {{array index of '8' indexes past the end of an array (that contains 2 elements)}} @@ -24,8 +26,8 @@ void f1(int a[1]) { int val = a[3]; // no warning for function argumnet } -void f2(const int (&a)[1]) { // expected-note {{declared here}} - int val = a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 elements)}} +void f2(const int (&a)[2]) { // expected-note {{declared here}} + int val = a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} } void test() { @@ -35,15 +37,20 @@ void test() { s2.a[3] = 0; // no warning for 0-sized array union { - short a[2]; // expected-note {{declared here}} + short a[2]; // expected-note 4 {{declared here}} char c[4]; } u; u.a[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} u.c[3] = 1; // no warning + short *p = &u.a[2]; // no warning + p = &u.a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + *(&u.a[2]) = 1; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} + *(&u.a[3]) = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + *(&u.c[3]) = 1; // no warning const int const_subscript = 3; - int array[1]; // expected-note {{declared here}} - array[const_subscript] = 0; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 elements)}} + int array[2]; // expected-note {{declared here}} + array[const_subscript] = 0; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} int *ptr; ptr[3] = 0; // no warning for pointer references @@ -58,8 +65,8 @@ void test() { const char str2[] = "foo"; // expected-note {{declared here}} char c2 = str2[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 4 elements)}} - int (*array_ptr)[1]; - (*array_ptr)[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 elements)}} + int (*array_ptr)[2]; + (*array_ptr)[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} } template <int I> struct S { @@ -151,8 +158,7 @@ void test_switch() { 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() -{ +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: ; @@ -173,3 +179,59 @@ void test_all_enums_covered(enum Values v) { } x[2] = 0; // no-warning } + +namespace tailpad { + struct foo { + char c1[1]; // expected-note {{declared here}} + int x; + char c2[1]; + }; + + char bar(struct foo *F) { + return F->c1[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}} + return F->c2[3]; // no warning, foo 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 of '3' indexes past the end of an array (that contains 1 element)}} + B->c[3]; // expected-warning {{array index of '3' indexes past the end of an array (that 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 of '5' indexes past the end of an array (that contains 5 elements)}} + ++foo[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}} + if (foo[6]) // expected-warning {{array index of '6' indexes past the end of an array (that contains 5 elements)}} + return --foo[6]; // expected-warning {{array index of '6' indexes past the end of an array (that contains 5 elements)}} + else + return foo[5]; // expected-warning {{array index of '5' indexes past the end of an array (that 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 of '32768' indexes past the end of an array (that 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 of '1000' indexes past the end of an array}} +} + diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index 725f0182db50..de9d7d1c2a6e 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -1,15 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -int align_illegal [[align(3)]]; //expected-error {{requested alignment is not a power of 2}} -char align_big [[align(int)]]; -int align_small [[align(1)]]; // FIXME: this should be rejected -int align_multiple [[align(1), align(8), align(1)]]; +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 [[align(8)]]; + int member alignas(8); }; -typedef char align_typedef [[align(8)]]; +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"); diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index fe7c833d322b..945aff363eb1 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -198,7 +198,7 @@ namespace test6 { }; void testA() { A x; // expected-warning {{'A' is deprecated}} - x = a0; + x = a0; // expected-warning {{'A' is deprecated}} } enum B { @@ -218,7 +218,7 @@ namespace test6 { }; void testC() { C<int>::Enum x; // expected-warning {{'Enum' is deprecated}} - x = C<int>::c0; + x = C<int>::c0; // expected-warning {{'Enum' is deprecated}} } template <class T> struct D { diff --git a/test/SemaCXX/auto-cxx0x.cpp b/test/SemaCXX/auto-cxx0x.cpp index f9246beff92a..a8f9e84423a7 100644 --- a/test/SemaCXX/auto-cxx0x.cpp +++ b/test/SemaCXX/auto-cxx0x.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 void f() { - auto int a; // expected-warning {{'auto' storage class specifier is redundant and will be removed in future releases}} + 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/test/SemaCXX/auto-cxx98.cpp b/test/SemaCXX/auto-cxx98.cpp index fe028114880a..6c401ba11a93 100644 --- a/test/SemaCXX/auto-cxx98.cpp +++ b/test/SemaCXX/auto-cxx98.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 void f() { - auto int a; - int auto b; + 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/test/SemaCXX/auto-subst-failure.cpp b/test/SemaCXX/auto-subst-failure.cpp index 442c7e82ccdb..b323dfc6b049 100644 --- a/test/SemaCXX/auto-subst-failure.cpp +++ b/test/SemaCXX/auto-subst-failure.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 void f() { auto a = f(); // expected-error {{variable has incomplete type 'void'}} diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp index 726fa6cb60fc..2b3ab68848eb 100644 --- a/test/SemaCXX/bool.cpp +++ b/test/SemaCXX/bool.cpp @@ -25,6 +25,9 @@ void static_assert_arg_is_bool(T x) { void test2() { int n = 2; - static_assert_arg_is_bool(n && 4); // expected-warning {{use of logical && with constant operand}} - static_assert_arg_is_bool(n || 5); // expected-warning {{use of logical || with constant operand}} + 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/test/SemaCXX/builtin-ptrtomember-ambig.cpp b/test/SemaCXX/builtin-ptrtomember-ambig.cpp index 32a893dafcef..61e347879a75 100644 --- a/test/SemaCXX/builtin-ptrtomember-ambig.cpp +++ b/test/SemaCXX/builtin-ptrtomember-ambig.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct A {}; diff --git a/test/SemaCXX/builtin-ptrtomember-overload-1.cpp b/test/SemaCXX/builtin-ptrtomember-overload-1.cpp index f736394a4caa..2d93c6b2dff3 100644 --- a/test/SemaCXX/builtin-ptrtomember-overload-1.cpp +++ b/test/SemaCXX/builtin-ptrtomember-overload-1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct A {}; struct E {}; diff --git a/test/SemaCXX/builtin-ptrtomember-overload.cpp b/test/SemaCXX/builtin-ptrtomember-overload.cpp index 6c132366199b..c7b5173a4fbe 100644 --- a/test/SemaCXX/builtin-ptrtomember-overload.cpp +++ b/test/SemaCXX/builtin-ptrtomember-overload.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct A {}; diff --git a/test/SemaCXX/cast-conversion.cpp b/test/SemaCXX/cast-conversion.cpp index 80707d13d20b..dd2bc98e02cc 100644 --- a/test/SemaCXX/cast-conversion.cpp +++ b/test/SemaCXX/cast-conversion.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct R { R(int); @@ -8,7 +8,8 @@ struct A { A(R); }; -struct B { // expected-note 3 {{candidate constructor (the implicit copy constructor) not viable}} +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}} }; diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp index 44fa0ce7ec9f..160f365f4bbf 100644 --- a/test/SemaCXX/class.cpp +++ b/test/SemaCXX/class.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s class C { public: - auto int errx; // expected-error {{error: storage class specified for a member declaration}} + auto int errx; // expected-error {{error: storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}} register int erry; // expected-error {{error: storage class specified for a member declaration}} extern int errz; // expected-error {{error: storage class specified for a member declaration}} @@ -34,11 +34,12 @@ public: enum E1 { en1, en2 }; - int i = 0; // expected-warning {{in-class initialization of non-static data member accepted as a C++0x extension}} + int i = 0; // expected-warning {{in-class initialization of non-static data member accepted as 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 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() { @@ -172,8 +173,8 @@ 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 C++0x extension}} - static const float y = foo(); // expected-warning {{in-class initializer for static data member of type 'const float' is a C++0x extension}} expected-error {{in-class initializer is not a constant expression}} + 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 is not a constant expression}} }; } @@ -188,3 +189,7 @@ void f() { S::c; // expected-error {{invalid use of nonstatic data member}} } } + +struct PR9989 { + static int const PR9989_Member = sizeof PR9989_Member; +}; diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp index ca8af2186f74..28e2dd0ad51a 100644 --- a/test/SemaCXX/compare.cpp +++ b/test/SemaCXX/compare.cpp @@ -212,3 +212,14 @@ 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/test/SemaCXX/complex-init-list.cpp b/test/SemaCXX/complex-init-list.cpp new file mode 100644 index 000000000000..e75833a37dbc --- /dev/null +++ b/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/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index b95700e9ba18..5648d022b522 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++0x -Wsign-compare %s +// 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. @@ -180,12 +180,12 @@ void test() unsigned long test0 = 5; - test0 = test0 ? (long) test0 : test0; // expected-warning {{operands of ? are integers of different signs}} - test0 = test0 ? (int) test0 : test0; // expected-warning {{operands of ? are integers of different signs}} - test0 = test0 ? (short) test0 : test0; // expected-warning {{operands of ? are integers of different signs}} - test0 = test0 ? test0 : (long) test0; // expected-warning {{operands of ? are integers of different signs}} - test0 = test0 ? test0 : (int) test0; // expected-warning {{operands of ? are integers of different signs}} - test0 = test0 ? test0 : (short) test0; // expected-warning {{operands of ? are integers of different signs}} + 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; @@ -193,8 +193,15 @@ void test() test0 = test0 ? (int) 10 : test0; test0 = test0 ? (short) 10 : test0; + int test1; test0 = test0 ? EVal : test0; - test0 = test0 ? EVal : (int) 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 diff --git a/test/SemaCXX/conversion-delete-expr.cpp b/test/SemaCXX/conversion-delete-expr.cpp index 862ae5ae02bb..0f298a819fa3 100644 --- a/test/SemaCXX/conversion-delete-expr.cpp +++ b/test/SemaCXX/conversion-delete-expr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // Test1 struct B { diff --git a/test/SemaCXX/convert-to-bool.cpp b/test/SemaCXX/convert-to-bool.cpp index 4cd22e90c0e0..c9a355549fdf 100644 --- a/test/SemaCXX/convert-to-bool.cpp +++ b/test/SemaCXX/convert-to-bool.cpp @@ -8,7 +8,7 @@ struct ConvToInt { }; struct ExplicitConvToBool { - explicit operator bool(); // expected-warning{{explicit conversion functions are a C++0x extension}} + explicit operator bool(); // expected-warning{{explicit conversion functions are a C++11 extension}} }; void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) { @@ -39,7 +39,7 @@ void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) { void accepts_bool(bool) { } // expected-note{{candidate function}} struct ExplicitConvToRef { - explicit operator int&(); // expected-warning{{explicit conversion functions are a C++0x extension}} + explicit operator int&(); // expected-warning{{explicit conversion functions are a C++11 extension}} }; void test_explicit_bool(ExplicitConvToBool ecb) { @@ -56,7 +56,7 @@ void test_explicit_conv_to_ref(ExplicitConvToRef ecr) { struct A { }; struct B { }; struct C { - explicit operator A&(); // expected-warning{{explicit conversion functions are a C++0x extension}} + explicit operator A&(); // expected-warning{{explicit conversion functions are a C++11 extension}} operator B&(); // expected-note{{candidate}} }; diff --git a/test/SemaCXX/cxx0x-class.cpp b/test/SemaCXX/cxx0x-class.cpp new file mode 100644 index 000000000000..3527ccb55577 --- /dev/null +++ b/test/SemaCXX/cxx0x-class.cpp @@ -0,0 +1,28 @@ +// 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 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(); + + 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 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}} + }; +} diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp new file mode 100644 index 000000000000..a01b26c5f91b --- /dev/null +++ b/test/SemaCXX/cxx0x-compat.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++0x-compat -verify %s + +namespace N { + template<typename T> void f(T) {} // expected-note {{here}} + namespace M { + template void f<int>(int); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}} + } +} + +template<typename T> void f(T) {} // expected-note {{here}} +namespace M { + template void f<int>(int); // expected-warning {{explicit instantiation of 'f' must occur in the global namespace}} +} + +void f() { + 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}} diff --git a/test/SemaCXX/cxx0x-constexpr-const.cpp b/test/SemaCXX/cxx0x-constexpr-const.cpp index 79e6dda3e11c..197edeb097b6 100644 --- a/test/SemaCXX/cxx0x-constexpr-const.cpp +++ b/test/SemaCXX/cxx0x-constexpr-const.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s constexpr int x = 1; constexpr int id(int x) { return x; } diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index 61aee0e45633..17933c2f009a 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s struct non_copiable { non_copiable(const non_copiable&) = delete; // expected-note {{marked deleted here}} @@ -35,7 +35,7 @@ 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' or 'volatile' qualifiers}} + bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const', 'constexpr' or 'volatile' qualifiers}} }; struct A {}; struct B {}; diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 86c5fd10e23c..d01f63bedb6b 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s void fn() = default; // expected-error {{only special member}} struct foo { diff --git a/test/SemaCXX/cxx0x-delegating-ctors.cpp b/test/SemaCXX/cxx0x-delegating-ctors.cpp index a3e6ff3b4f92..2d49f0fc599d 100644 --- a/test/SemaCXX/cxx0x-delegating-ctors.cpp +++ b/test/SemaCXX/cxx0x-delegating-ctors.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s struct foo { int i; diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index dcb6ba2790be..16c56642c06b 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s struct non_trivial { non_trivial(); @@ -118,3 +118,15 @@ struct late_delete { late_delete(); }; late_delete::late_delete() = default; // expected-error {{would delete it}} + +// See also rdar://problem/8125400. +namespace empty { + static union {}; // expected-error {{deleted constructor}} expected-note {{here}} + static union { union {}; }; + static union { struct {}; }; + static union { union { union {}; }; }; + static union { union { struct {}; }; }; + static union { struct { union {}; }; }; // expected-error {{deleted constructor}} expected-note {{here}} + static union { struct { struct {}; }; }; +} + diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp new file mode 100644 index 000000000000..41fc2193891c --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +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}} + } + + int direct_usage() { + int ar[10]; + (void) ar[{1}]; // expected-error {{array subscript is not an integer}} + + return {1}; + } + + void inline_init() { + (void) int{1}; + (void) new int{1}; + } + + struct A { + int i; + A() : i{1} {} + }; + +} diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp index 666e64be66ab..6275af6bac52 100644 --- a/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s struct non_trivial { non_trivial(); diff --git a/test/SemaCXX/cxx0x-return-init-list.cpp b/test/SemaCXX/cxx0x-return-init-list.cpp index 2005a7f9f676..b786922b71a8 100644 --- a/test/SemaCXX/cxx0x-return-init-list.cpp +++ b/test/SemaCXX/cxx0x-return-init-list.cpp @@ -1,17 +1,17 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // This test checks for a teeny tiny subset of the functionality in -// the C++0x generalized initializer lists feature, which happens to +// the C++11 generalized initializer lists feature, which happens to // be used in libstdc++ 4.5. We accept only this syntax so that Clang // can handle the libstdc++ 4.5 headers. int test0(int i) { - return { i }; // expected-warning{{generalized initializer lists are a C++0x extension unsupported in Clang}} + return { i }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}} } template<typename T, typename U> T test1(U u) { - return { u }; // expected-warning{{generalized initializer lists are a C++0x extension unsupported in Clang}} + return { u }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}} } template int test1(char); diff --git a/test/SemaCXX/cxx0x-type-convert-construct.cpp b/test/SemaCXX/cxx0x-type-convert-construct.cpp new file mode 100644 index 000000000000..6a7fe45281f5 --- /dev/null +++ b/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/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp new file mode 100644 index 000000000000..2ca0ae4d1ec8 --- /dev/null +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat-pedantic -verify %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}} diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp new file mode 100644 index 000000000000..6a3881cf4217 --- /dev/null +++ b/test/SemaCXX/cxx98-compat.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s + +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 {}; +S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}} diff --git a/test/SemaCXX/decl-init-ref.cpp b/test/SemaCXX/decl-init-ref.cpp index 34c4578e9d6d..4c635c1a2447 100644 --- a/test/SemaCXX/decl-init-ref.cpp +++ b/test/SemaCXX/decl-init-ref.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s struct A {}; diff --git a/test/SemaCXX/decltype-crash.cpp b/test/SemaCXX/decltype-crash.cpp index f94ba453ffb4..50b3e49b78a5 100644 --- a/test/SemaCXX/decltype-crash.cpp +++ b/test/SemaCXX/decltype-crash.cpp @@ -3,5 +3,5 @@ int& a(); void f() { - decltype(a()) c; // expected-error {{use of undeclared identifier 'decltype'}} + decltype(a()) c; // expected-warning {{'decltype' is a keyword in C++11}} expected-error {{use of undeclared identifier 'decltype'}} } diff --git a/test/SemaCXX/decltype-overloaded-functions.cpp b/test/SemaCXX/decltype-overloaded-functions.cpp index f4aacd64ddbc..b0a43a999bb6 100644 --- a/test/SemaCXX/decltype-overloaded-functions.cpp +++ b/test/SemaCXX/decltype-overloaded-functions.cpp @@ -1,15 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -void f(); // expected-note{{candidate function}} -void f(int); // expected-note{{candidate function}} -decltype(f) a; // expected-error{{cannot resolve overloaded function 'f' from context}} +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{{cannot resolve overloaded function 'f' from context}} + 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{{candidate function}} - void f(int); // expected-note{{candidate function}} + 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/test/SemaCXX/decltype-pr4444.cpp b/test/SemaCXX/decltype-pr4444.cpp index 456b22c5f7f2..2f95075067a4 100644 --- a/test/SemaCXX/decltype-pr4444.cpp +++ b/test/SemaCXX/decltype-pr4444.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 template<typename T, T t> struct TestStruct { diff --git a/test/SemaCXX/decltype-pr4448.cpp b/test/SemaCXX/decltype-pr4448.cpp index ead24ce0ca86..9d33ce7341a2 100644 --- a/test/SemaCXX/decltype-pr4448.cpp +++ b/test/SemaCXX/decltype-pr4448.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 template< typename T, T t, decltype(t+2) v > struct Convoluted {}; diff --git a/test/SemaCXX/decltype-this.cpp b/test/SemaCXX/decltype-this.cpp index f9bf49973b5c..a13416f089dd 100644 --- a/test/SemaCXX/decltype-this.cpp +++ b/test/SemaCXX/decltype-this.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template<typename T, typename U> struct is_same { static const bool value = false; diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp index f61a92b71e1e..78fb8ef02078 100644 --- a/test/SemaCXX/decltype.cpp +++ b/test/SemaCXX/decltype.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s // PR5290 int const f0(); diff --git a/test/SemaCXX/defaulted-ctor-loop.cpp b/test/SemaCXX/defaulted-ctor-loop.cpp index 6a41972cf75a..6416336c6eed 100644 --- a/test/SemaCXX/defaulted-ctor-loop.cpp +++ b/test/SemaCXX/defaulted-ctor-loop.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // WARNING: This test may recurse infinitely if failing. diff --git a/test/SemaCXX/delete.cpp b/test/SemaCXX/delete.cpp index 4567888a37b1..5824facc507b 100644 --- a/test/SemaCXX/delete.cpp +++ b/test/SemaCXX/delete.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: cp %s %t // RUN: %clang_cc1 -fixit -x c++ %t -// RUN: FileCheck -input-file=%t %s +// RUN: %clang_cc1 -E -o - %t | FileCheck %s void f(int a[10][20]) { // CHECK: delete[] a; diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index 6a8965ceb578..4620a19d46fb 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s int i = delete; // expected-error {{only functions can have deleted definitions}} diff --git a/test/SemaCXX/deleted-operator.cpp b/test/SemaCXX/deleted-operator.cpp new file mode 100644 index 000000000000..e357401bf942 --- /dev/null +++ b/test/SemaCXX/deleted-operator.cpp @@ -0,0 +1,13 @@ +// 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}} +} diff --git a/test/SemaCXX/dependent-auto.cpp b/test/SemaCXX/dependent-auto.cpp index 52b15eda7324..1be1566bb3b0 100644 --- a/test/SemaCXX/dependent-auto.cpp +++ b/test/SemaCXX/dependent-auto.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 template<typename T> struct only { diff --git a/test/SemaCXX/dependent-noexcept-unevaluated.cpp b/test/SemaCXX/dependent-noexcept-unevaluated.cpp index 5bf6f9e96a12..8066b859f189 100644 --- a/test/SemaCXX/dependent-noexcept-unevaluated.cpp +++ b/test/SemaCXX/dependent-noexcept-unevaluated.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s template <class T> T&& diff --git a/test/SemaCXX/dependent-types.cpp b/test/SemaCXX/dependent-types.cpp index 053e79bb6981..13ed72f7231e 100644 --- a/test/SemaCXX/dependent-types.cpp +++ b/test/SemaCXX/dependent-types.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify -std=c++11 %s template<typename T> using U = int &; diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index ec0539b81901..14a0cda8df35 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s class A { public: ~A(); diff --git a/test/SemaCXX/enum-bitfield.cpp b/test/SemaCXX/enum-bitfield.cpp index a766116b1c3c..1a657408f8a6 100644 --- a/test/SemaCXX/enum-bitfield.cpp +++ b/test/SemaCXX/enum-bitfield.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++0x -verify -triple x86_64-apple-darwin %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s enum E {}; diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index 73e7578ecb6e..35ba1b4017ae 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++0x -verify -triple x86_64-apple-darwin %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple x86_64-apple-darwin %s enum class E1 { Val1 = 1L diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp index 717ed1e3caf2..11b9672a8501 100644 --- a/test/SemaCXX/explicit.cpp +++ b/test/SemaCXX/explicit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s namespace Constructor { struct A { A(int); @@ -36,4 +36,149 @@ namespace Conversion { 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}} \ + 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 default constructor) not viable: requires 0 arguments, but 1 was provided}} \ + 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 default constructor) not viable: requires 0 arguments, but 1 was provided}} \ + 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 default constructor) not viable: requires 0 arguments, but 1 was provided}} + 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'}} + // FIXME: These are well-formed per C++0x 13.3.1.4p1 (see DR899). + Y y3 = (Y)z; // expected-error {{no matching conversion for C-style cast from 'Conversion::Z' to 'Conversion::Y''}} + Y y4 = Y(z); // expected-error {{no matching conversion for functional-style cast from 'Conversion::Z' to 'Conversion::Y'}} + Y y5 = static_cast<Y>(z); // expected-error {{no matching conversion for static_cast from 'Conversion::Z' to 'Conversion::Y'}} + // 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/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 4555192280f0..32b3ff91e95b 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -136,7 +136,7 @@ void conv_ptr_1() void expr_6() { - // expr/6: If an expression initially has the type “reference to T” + // 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; @@ -185,8 +185,8 @@ struct Class : BaseClass template <class T> struct NestedClassTemplate {}; - template <class T> - static int& NestedFuncTemplate() { return variable; } // expected-note{{candidate function}} + template <class T> // expected-note{{possible target for call}} + static int& NestedFuncTemplate() { return variable; } template <class T> int& NestedMemfunTemplate() { return variable; } @@ -234,13 +234,13 @@ struct Class : BaseClass // 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{{cannot resolve overloaded function 'NestedFuncTemplate' from context}} + // 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{{a bound member function may only be called}} + // expected-error{{reference to non-static member function must be called}} __is_lvalue_expr(::Class::operator+); // operator-function-id: template \ - // expected-error{{a bound member function may only be called}} + // expected-error{{reference to non-static member function must be called}} //ASSERT_RVALUE(::Class::operator*); // operator-function-id: member function } @@ -310,9 +310,9 @@ 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 + // shall have the type "pointer to T" and the other shall have // enumeration or integral type. The result is an lvalue of type - // “T.” + // "T." ASSERT_LVALUE(pointer[1]); // The expression E1[E2] is identical (by definition) to *((E1)+(E2)). @@ -348,32 +348,32 @@ 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 + // 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 + // - 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, + // - 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 + // - 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, + // - 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 + // - 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); @@ -404,8 +404,8 @@ void expr_dynamic_cast_2() 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 + // 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; @@ -416,13 +416,13 @@ void expr_dynamic_cast_5() // expr.dynamic.cast/8: The run-time check logically executes as follows: // -// — If, in the most derived object pointed (referred) to by v, v +// - 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 +// - 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 @@ -525,7 +525,7 @@ void expr_cond(bool cond) // 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 + // - 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. @@ -535,7 +535,7 @@ void expr_cond(bool cond) ASSERT_RVALUE(cond ? throw 1 : classLvalue); ASSERT_RVALUE(cond ? classLvalue : throw 1); - // — Both the second and the third operands have type void; the result + // - 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); diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp index 8a294face380..355833e693fa 100644 --- a/test/SemaCXX/expressions.cpp +++ b/test/SemaCXX/expressions.cpp @@ -34,7 +34,9 @@ namespace test1 { } int test2(int x) { - return x && 4; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + 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; @@ -42,38 +44,69 @@ int test2(int x) { return x || true; return x || false; - return x && (unsigned)0; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + 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; switch to bitwise | or remove constant}} + 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; switch to bitwise | or remove constant}} - return x || 1; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x || -1; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x || 5; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x && 0; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && 1; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && -1; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && 5; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x || (0); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x || (1); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x || (-1); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x || (5); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} - return x && (0); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && (1); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && (-1); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && (5); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + 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; switch to bitwise & or remove constant}} + 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; switch to bitwise & or remove constant}} + 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; } diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index 810f1de441a1..b994e8c10bd6 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 namespace value_range_detail { template<typename T> diff --git a/test/SemaCXX/for-range-no-std.cpp b/test/SemaCXX/for-range-no-std.cpp index 8cc71e5111a2..dae41f1bb296 100644 --- a/test/SemaCXX/for-range-no-std.cpp +++ b/test/SemaCXX/for-range-no-std.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions struct S { int *begin(); diff --git a/test/SemaCXX/for-range-unused.cpp b/test/SemaCXX/for-range-unused.cpp index 7b7d84d3f9c8..ce6b379cc192 100644 --- a/test/SemaCXX/for-range-unused.cpp +++ b/test/SemaCXX/for-range-unused.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x -Wunused +// 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. diff --git a/test/SemaCXX/function-overload-typo-crash.cpp b/test/SemaCXX/function-overload-typo-crash.cpp index 0fea312a97f2..8c5cec8af3a9 100644 --- a/test/SemaCXX/function-overload-typo-crash.cpp +++ b/test/SemaCXX/function-overload-typo-crash.cpp @@ -1,12 +1,28 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // PR10283 -void min(); +void min(); //expected-note {{'min' declared here}} void min(int); -template <typename T> void max(T); +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/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp index b15d86616585..0d9ecf334e6a 100644 --- a/test/SemaCXX/function-redecl.cpp +++ b/test/SemaCXX/function-redecl.cpp @@ -24,3 +24,74 @@ namespace N { } } } + +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'}} +// ...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'}} + +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/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp index 6e2bee7e301d..a1891c9c322e 100644 --- a/test/SemaCXX/generalized-initializers.cpp +++ b/test/SemaCXX/generalized-initializers.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s // XFAIL: * template <typename T, typename U> @@ -40,25 +40,9 @@ namespace std { 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}} - { const short a{100000}; } // expected-error {{narrowing conversion}} - { const short a = {100000}; } // expected-error {{narrowing conversion}} - } - int function_call() { void takes_int(int); takes_int({1}); - - int ar[10]; - (void) ar[{1}]; // expected-error {{initializer list is illegal with the built-in index operator}} - - return {1}; } void inline_init() { @@ -76,11 +60,6 @@ namespace integral { for (int i : {1, 2, 3, 4}) {} } - struct A { - int i; - A() : i{1} {} - }; - } namespace objects { diff --git a/test/SemaCXX/generic-selection.cpp b/test/SemaCXX/generic-selection.cpp index b171fce540d8..c0a5d89fff67 100644 --- a/test/SemaCXX/generic-selection.cpp +++ b/test/SemaCXX/generic-selection.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s template <typename T, typename U = void*> struct A { diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index 186e32126a39..4d02ca8f174e 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -54,4 +54,10 @@ struct A { 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; }; +int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp index 81babc043ff7..559c3013f7e9 100644 --- a/test/SemaCXX/implicit-exception-spec.cpp +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x -Wall %s +// 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; }; diff --git a/test/SemaCXX/issue547.cpp b/test/SemaCXX/issue547.cpp index 03c5b7c978aa..5b82dc6b145e 100644 --- a/test/SemaCXX/issue547.cpp +++ b/test/SemaCXX/issue547.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s template<typename T> struct classify_function { diff --git a/test/SemaCXX/libstdcxx_is_pod_hack.cpp b/test/SemaCXX/libstdcxx_is_pod_hack.cpp index 3581c796ce91..3ac233627ccb 100644 --- a/test/SemaCXX/libstdcxx_is_pod_hack.cpp +++ b/test/SemaCXX/libstdcxx_is_pod_hack.cpp @@ -27,3 +27,7 @@ struct test_is_signed { }; 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/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp index b5a10a795ebc..cb7e32c05d88 100644 --- a/test/SemaCXX/linkage-spec.cpp +++ b/test/SemaCXX/linkage-spec.cpp @@ -89,3 +89,16 @@ 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/test/SemaCXX/literal-operators.cpp b/test/SemaCXX/literal-operators.cpp index ec585a61da9f..06ef49fc0ae1 100644 --- a/test/SemaCXX/literal-operators.cpp +++ b/test/SemaCXX/literal-operators.cpp @@ -1,41 +1,41 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// 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 *); + 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 *); } +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 *); } +extern "C++" void operator "" _extern_good (const char *); +extern "C++" { void operator "" _extern_good (const char *); } -void fn () { void operator "" fn_bad (const char *); } // expected-error {{literal operator 'operator "" fn_bad' must be in a namespace or global scope}} +void fn () { void operator "" _fn_bad (const char *); } // expected-error {{literal operator 'operator "" _fn_bad' must be in a namespace or global scope}} // 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); +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); +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[]); +void operator "" _good (const char[]); typedef const char c; -void operator "" good (c*); +void operator "" _good (c*); // Check extra cv-qualifiers -void operator "" cv_good (volatile const char *, const size_t); +void operator "" _cv_good (volatile const char *, const size_t); // Template delcaration (not implemented yet) // template <char...> void operator "" good (); diff --git a/test/SemaCXX/literal-type.cpp b/test/SemaCXX/literal-type.cpp index 6a61823adb28..60bfcf00cf0b 100644 --- a/test/SemaCXX/literal-type.cpp +++ b/test/SemaCXX/literal-type.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// 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 diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 981bae7c770b..2e3fd73d7ff5 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -28,7 +28,7 @@ struct B { A *f0(); }; int f0(B *b) { - return b->f0->f0; // expected-error{{perhaps you meant to call it with no arguments}} + return b->f0->f0; // expected-error{{did you mean to call it with no arguments}} } int i; @@ -118,32 +118,32 @@ namespace rdar8231724 { namespace PR9025 { struct S { int x; }; - S fun(); - int fun(int i); + 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{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + return fun.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} } - S fun2(); - S fun2(int i); + 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{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + 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); - int fun3(int i, int j); + 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{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + 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(); + template <typename T> S fun4(); // expected-note{{possible target for call}} int g4() { - return fun4.x; // expected-error{{base of member reference is a function; perhaps you meant to call it?}} + 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{{possibly valid overload here}} - S fun5(float f); // expected-note{{possibly valid overload here}} + 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{{base of member reference is an overloaded function; perhaps you meant to call it?}} + return fun5.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } } diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 7ca1f0e4513e..819c8d13db89 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x -Wall %s +// 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}} @@ -52,3 +52,21 @@ struct CheckExcSpecFail { 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/test/SemaCXX/microsoft-cxx0x.cpp b/test/SemaCXX/microsoft-cxx0x.cpp new file mode 100644 index 000000000000..3f78eda79cd5 --- /dev/null +++ b/test/SemaCXX/microsoft-cxx0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++0x-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/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp index fd0c976bdd78..76ceea1d4d5b 100644 --- a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp +++ b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp @@ -1,8 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s -namespace fizbin { class Foobar; } // expected-note{{'fizbin::Foobar' declared here}} -Foobar *my_bar = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} \ - // expected-error{{expected a type}} +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{{unknown type name 'FooBar'; did you mean 'Foobar'?}} namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}} int Double(int x) { return x + x; } @@ -62,11 +64,13 @@ void f() { // Test case from http://llvm.org/bugs/show_bug.cgi?id=10318 namespace llvm { - template <typename T> class GraphWriter {}; // expected-note{{'llvm::GraphWriter' declared here}} + template <typename T> class GraphWriter {}; // expected-note {{'llvm::GraphWriter' declared here}} \ + // expected-note {{'GraphWriter' 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 {{expected a type}} + (void)new llvm::Graphwriter<S>; // expected-error {{no template named 'Graphwriter' in namespace 'llvm'; did you mean 'GraphWriter'?}} } diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index ee6ca8857374..e13030cc38a8 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -27,10 +27,10 @@ int A::C::cx = 17; static int A::C::cx2 = 17; // expected-error{{'static' can}} class C2 { - void m(); // expected-note{{member declaration nearly matches}} + void m(); // expected-note{{member declaration does not match because it is not const qualified}} - void f(const int& parm); // expected-note{{member declaration nearly matches}} - void f(int) const; // expected-note{{member declaration nearly matches}} + 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; @@ -121,7 +121,7 @@ namespace E { class Operators { - Operators operator+(const Operators&) const; // expected-note{{member declaration nearly matches}} + Operators operator+(const Operators&) const; // expected-note{{member declaration does not match because it is const qualified}} operator bool(); }; @@ -140,7 +140,7 @@ Operators::operator bool() { } namespace A { - void g(int&); // expected-note{{member declaration nearly matches}} + 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'}} diff --git a/test/SemaCXX/new-array-size-conv.cpp b/test/SemaCXX/new-array-size-conv.cpp index 80219a906209..e8bb67955f97 100644 --- a/test/SemaCXX/new-array-size-conv.cpp +++ b/test/SemaCXX/new-array-size-conv.cpp @@ -19,8 +19,8 @@ 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++0x extension}} - (void)new int[ValueEnum()]; // expected-warning{{implicit conversion from array size expression of type 'ValueEnum' to enumeration type 'E' is a C++0x extension}} + (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/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index efdfa0f066db..748ce7770097 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -397,3 +397,22 @@ namespace ArrayNewNeedsDtor { 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}} +} diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp index fab6f10ab785..24590ce633f2 100644 --- a/test/SemaCXX/null_in_arithmetic_ops.cpp +++ b/test/SemaCXX/null_in_arithmetic_ops.cpp @@ -64,12 +64,12 @@ void f() { a |= NULL; // expected-warning{{use of NULL in arithmetic operation}} a ^= NULL; // expected-warning{{use of NULL in arithmetic operation}} - b = a < NULL || NULL < a; // expected-warning 2{{use of NULL in arithmetic operation}} - b = a > NULL || NULL > a; // expected-warning 2{{use of NULL in arithmetic operation}} - b = a <= NULL || NULL <= a; // expected-warning 2{{use of NULL in arithmetic operation}} - b = a >= NULL || NULL >= a; // expected-warning 2{{use of NULL in arithmetic operation}} - b = a == NULL || NULL == a; // expected-warning 2{{use of NULL in arithmetic operation}} - b = a != NULL || NULL != a; // expected-warning 2{{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; @@ -82,7 +82,7 @@ void f() { b = NULL <= NULL || NULL >= NULL; b = NULL == NULL || NULL != NULL; - b = ((NULL)) != a; // expected-warning{{use of NULL in arithmetic operation}} + 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; diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index d69af588a7d0..6f660366e998 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++0x -ffreestanding %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding %s #include <stdint.h> typedef decltype(nullptr) nullptr_t; diff --git a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp index e839ed116f8d..9671353907c7 100644 --- a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp +++ b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fblocks -std=c++0x -verify %s +// RUN: %clang_cc1 -fsyntax-only -fblocks -std=c++11 -verify %s void foo() { int a; diff --git a/test/SemaCXX/out-of-line-def-mismatch.cpp b/test/SemaCXX/out-of-line-def-mismatch.cpp new file mode 100644 index 000000000000..6ade5b802b65 --- /dev/null +++ b/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/test/SemaCXX/overload-0x.cpp b/test/SemaCXX/overload-0x.cpp new file mode 100644 index 000000000000..677d16a32c12 --- /dev/null +++ b/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/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 9cc48993fde9..00f6a9460a7a 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -525,3 +525,12 @@ namespace PR9507 { f(n); // expected-error{{call to 'f' is ambiguous}} } } + +namespace rdar9803316 { + void foo(float); + int &foo(int); + + void bar() { + int &ir = (&foo)(0); + } +} diff --git a/test/SemaCXX/overloaded-builtin-operators-0x.cpp b/test/SemaCXX/overloaded-builtin-operators-0x.cpp index 32f199529064..6a5a162af679 100644 --- a/test/SemaCXX/overloaded-builtin-operators-0x.cpp +++ b/test/SemaCXX/overloaded-builtin-operators-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -std=c++0x -verify %s +// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -std=c++11 -verify %s template <class T> struct X diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp index 73f12a902723..a5ec51ced23d 100644 --- a/test/SemaCXX/overloaded-name.cpp +++ b/test/SemaCXX/overloaded-name.cpp @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int ovl(int); // expected-note 3{{candidate function}} -float ovl(float); // expected-note 3{{candidate function}} +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{{candidate function}} +template<typename T> T ovl(T); // expected-note 3{{possible target for call}} void test(bool b) { - (void)((void)0, ovl); // expected-error{{cannot resolve overloaded function 'ovl' from context}} + (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{{cannot resolve overloaded function 'ovl' from context}} - (void)(b? ovl<float> : &ovl); // expected-error{{cannot resolve overloaded function 'ovl' from context}} + (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>); } @@ -21,10 +21,11 @@ namespace rdar9623945 { public: const char* text(void); void g(void) { + // FIXME: why 2x? f(text()); - f(text); // expected-error{{a bound member function may only be called}} + f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}} f(text()); - f(text); // expected-error{{a bound member function may only be called}} + f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } }; } diff --git a/test/SemaCXX/overloaded-operator-decl.cpp b/test/SemaCXX/overloaded-operator-decl.cpp index 5f8655cee70c..4519a2d1f9ad 100644 --- a/test/SemaCXX/overloaded-operator-decl.cpp +++ b/test/SemaCXX/overloaded-operator-decl.cpp @@ -43,3 +43,8 @@ namespace PR6238 { 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/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 462d0234f39f..1e4a3b7514ba 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -36,7 +36,7 @@ A make_A(); bool operator==(A&, Z&); // expected-note 3{{candidate function}} void h(A a, const A ac, Z z) { - make_A() == 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')}} } @@ -45,7 +45,7 @@ struct B { bool operator==(const B&) const; void test(Z z) { - make_A() == z; + make_A() == z; // expected-warning{{equality comparison result unused}} } }; @@ -396,7 +396,7 @@ namespace rdar9136502 { }; void f(X x, Y y) { - y << x.i; // expected-error{{a bound member function may only be called}} + y << x.i; // expected-error{{reference to non-static member function must be called}} } } diff --git a/test/SemaCXX/ptrtomember-overload-resolution.cpp b/test/SemaCXX/ptrtomember-overload-resolution.cpp index 4c7908e1137e..787e33022aa3 100644 --- a/test/SemaCXX/ptrtomember-overload-resolution.cpp +++ b/test/SemaCXX/ptrtomember-overload-resolution.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// 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::*, diff --git a/test/SemaCXX/ptrtomember.cpp b/test/SemaCXX/ptrtomember.cpp index c3917333a540..aee535e5593b 100644 --- a/test/SemaCXX/ptrtomember.cpp +++ b/test/SemaCXX/ptrtomember.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct S { int i; @@ -22,12 +22,12 @@ struct S3 { }; void f3(S3* p, void (S3::*m)()) { - p->*m; // expected-error {{a bound member function may only be called}} - (void)(p->*m); // expected-error {{a bound member function may only be called}} - (void)(void*)(p->*m); // expected-error {{a bound member function may only be called}} - (void)reinterpret_cast<void*>(p->*m); // expected-error {{a bound member function may only be called}} - if (p->*m) {} // expected-error {{a bound member function may only be called}} - if (!(p->*m)) {} // expected-error {{a bound member function may only be called}} - if (p->m) {}; // expected-error {{a bound member function may only be called}} - if (!p->m) {}; // expected-error {{a bound member function may only be called}} + 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/test/SemaCXX/redeclared-alias-template.cpp b/test/SemaCXX/redeclared-alias-template.cpp index b368fcfe5508..09e9d0d83bf5 100644 --- a/test/SemaCXX/redeclared-alias-template.cpp +++ b/test/SemaCXX/redeclared-alias-template.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// 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')}} diff --git a/test/SemaCXX/redeclared-auto.cpp b/test/SemaCXX/redeclared-auto.cpp index 34de54c0f01d..87ad6bd7e5d8 100644 --- a/test/SemaCXX/redeclared-auto.cpp +++ b/test/SemaCXX/redeclared-auto.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 extern int a; auto a = 0; // expected-note 2{{here}} diff --git a/test/SemaCXX/ref-init-ambiguous.cpp b/test/SemaCXX/ref-init-ambiguous.cpp index 752a3484d025..ce47e10c9ae3 100644 --- a/test/SemaCXX/ref-init-ambiguous.cpp +++ b/test/SemaCXX/ref-init-ambiguous.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 enum E2 { }; diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index ab44e78453b2..70d3799a0ea5 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -134,3 +134,6 @@ namespace PR7149 { 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/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp index 53ed0d724527..e06ba403efec 100644 --- a/test/SemaCXX/return-noreturn.cpp +++ b/test/SemaCXX/return-noreturn.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code +// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code // A destructor may be marked noreturn and should still influence the CFG. void pr6884_abort() __attribute__((noreturn)); @@ -8,23 +9,93 @@ struct pr6884_abort_struct { ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); } }; -int pr6884_f(int x) { - switch (x) { default: pr6884_abort(); } -} +struct other { ~other() {} }; -int pr6884_g(int x) { - switch (x) { default: pr6884_abort_struct(); } -} +// 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(); } + } -int pr6884_g_positive(int x) { - switch (x) { default: ; } -} // expected-warning {{control reaches end of non-void function}} + // 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(); } + } -int pr6884_h(int x) { - switch (x) { - default: { - pr6884_abort_struct a; - } + // 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; } } } diff --git a/test/SemaCXX/rval-references-examples.cpp b/test/SemaCXX/rval-references-examples.cpp index f4921a9b5168..110ae26fb5d2 100644 --- a/test/SemaCXX/rval-references-examples.cpp +++ b/test/SemaCXX/rval-references-examples.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s template<typename T> class unique_ptr { diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp index 74afdbe41043..fc341e87f4a4 100644 --- a/test/SemaCXX/rval-references.cpp +++ b/test/SemaCXX/rval-references.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s typedef int&& irr; typedef irr& ilr_c1; // Collapses to int& diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index 3a90cc08f6a2..ad109f4d4e03 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-unreachable-code -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++0x %s -Wno-unreachable-code +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu++11 %s -Wno-unreachable-code namespace test0 { struct D { ~D(); }; @@ -171,3 +171,39 @@ namespace test9 { } } } + +// 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/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp index 516243ec70e1..0991a5f89cc8 100644 --- a/test/SemaCXX/static-assert.cpp +++ b/test/SemaCXX/static-assert.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 int f(); diff --git a/test/SemaCXX/switch-0x.cpp b/test/SemaCXX/switch-0x.cpp index adaeb85bce17..2e74da0a4634 100644 --- a/test/SemaCXX/switch-0x.cpp +++ b/test/SemaCXX/switch-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // PR5518 struct A { diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp index b52b240da35d..e25939fa3ebf 100644 --- a/test/SemaCXX/trailing-return-0x.cpp +++ b/test/SemaCXX/trailing-return-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template <class T> struct only diff --git a/test/SemaCXX/trivial-constructor.cpp b/test/SemaCXX/trivial-constructor.cpp index 494d1ec0843f..bda206b61f9a 100644 --- a/test/SemaCXX/trivial-constructor.cpp +++ b/test/SemaCXX/trivial-constructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct T1 { }; static_assert(__has_trivial_constructor(T1), "T1 has trivial constructor!"); diff --git a/test/SemaCXX/trivial-destructor.cpp b/test/SemaCXX/trivial-destructor.cpp index 29358d8bd228..db415cf9050a 100644 --- a/test/SemaCXX/trivial-destructor.cpp +++ b/test/SemaCXX/trivial-destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct T1 { }; static_assert(__has_trivial_destructor(T1), "T1 has trivial destructor!"); diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 30cc6a3f1ce2..0914c7cf94e3 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++0x %s +// 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 @@ -89,6 +89,13 @@ 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(); +}; + void is_pod() { { int arr[T(__is_pod(int))]; } @@ -1102,6 +1109,7 @@ void has_trivial_default_constructor() { { 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))]; } } void has_trivial_copy_constructor() { @@ -1129,6 +1137,7 @@ void has_trivial_copy_constructor() { { 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))]; } } void has_trivial_copy_assignment() { @@ -1155,6 +1164,7 @@ void has_trivial_copy_assignment() { { 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))]; } } void has_trivial_destructor() { @@ -1181,6 +1191,7 @@ void has_trivial_destructor() { { 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))]; } } struct A { ~A() {} }; @@ -1191,6 +1202,23 @@ void f() { { 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))]; } @@ -1208,6 +1236,8 @@ void has_nothrow_assign() { { 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))]; } @@ -1219,6 +1249,7 @@ void has_nothrow_assign() { { 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() { @@ -1243,6 +1274,7 @@ void has_nothrow_copy() { { 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))]; } @@ -1272,6 +1304,7 @@ void has_nothrow_constructor() { { 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))]; } @@ -1316,6 +1349,7 @@ void has_virtual_destructor() { { 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))]; } } diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp new file mode 100644 index 000000000000..fa32c57fc7ed --- /dev/null +++ b/test/SemaCXX/typo-correction.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-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)); +} diff --git a/test/SemaCXX/underlying_type.cpp b/test/SemaCXX/underlying_type.cpp index 607d9ad843a4..dcfaab3c8b4d 100644 --- a/test/SemaCXX/underlying_type.cpp +++ b/test/SemaCXX/underlying_type.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -std=c++0x %s +// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -std=c++11 %s #include "limits.h" diff --git a/test/SemaCXX/uninit-variables-conditional.cpp b/test/SemaCXX/uninit-variables-conditional.cpp index 3324215621bf..3c44c7249d51 100644 --- a/test/SemaCXX/uninit-variables-conditional.cpp +++ b/test/SemaCXX/uninit-variables-conditional.cpp @@ -15,7 +15,7 @@ int init(double *); // the destructor in Foo fouls about the minor bit of path-sensitivity in // -Wuninitialized. double test() { - double x; // expected-note {{variable 'x' is declared here}} expected-note{{add initialization to silence this warning}} + double x; // expected-note{{initialize the variable 'x' to silence this warning}} if (bar() || baz() || Foo() || init(&x)) return 1.0; diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index a0180e3d3a15..358a5723563f 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -26,7 +26,7 @@ void unevaluated_tests() { // Warn for glvalue arguments to typeid whose type is polymorphic. struct A { virtual ~A() {} }; void polymorphic_test() { - A *a; // expected-note{{declared here}} expected-note{{add initialization}} + A *a; // expected-note{{initialize the variable 'a' to silence this warning}} (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here }} } @@ -50,7 +50,7 @@ unsigned test3_b() { return x; // no-warning } unsigned test3_c() { - unsigned x; // expected-note{{declared here}} expected-note{{add initialization}} + unsigned x; // expected-note{{initialize the variable 'x' to silence this warning}} const bool flag = false; if (flag && (x = test3_aux()) == 0) { x = 1; @@ -66,6 +66,16 @@ test4_A test4() { 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: @@ -108,4 +118,26 @@ void RDar9251392() { } } +// 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/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 0a3b5d938dd3..c25bd201d626 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -24,6 +24,78 @@ 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; } + 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 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}} +} + +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; @@ -43,3 +115,5 @@ struct S { S(char (*)[5]) : x(boo(x)) {} S(char (*)[6]) : x(far(x)) {} }; + +struct C { char a[100], *e; } car = { .e = car.a }; diff --git a/test/SemaCXX/unknown-anytype.cpp b/test/SemaCXX/unknown-anytype.cpp index b0a2981f470d..ba52122bc490 100644 --- a/test/SemaCXX/unknown-anytype.cpp +++ b/test/SemaCXX/unknown-anytype.cpp @@ -34,3 +34,14 @@ namespace test3 { ((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/test/SemaCXX/unused-functions.cpp b/test/SemaCXX/unused-functions.cpp index f164bf276846..359808203892 100644 --- a/test/SemaCXX/unused-functions.cpp +++ b/test/SemaCXX/unused-functions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -Wunused -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wunused -verify %s static int foo(int x) { return x; } diff --git a/test/SemaCXX/user-defined-conversions.cpp b/test/SemaCXX/user-defined-conversions.cpp index 5de7f44be92c..43ec5a3d4ab9 100644 --- a/test/SemaCXX/user-defined-conversions.cpp +++ b/test/SemaCXX/user-defined-conversions.cpp @@ -82,3 +82,18 @@ 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/test/SemaCXX/using-decl-templates.cpp b/test/SemaCXX/using-decl-templates.cpp index 7b4da9d50d03..2f8abca02d6e 100644 --- a/test/SemaCXX/using-decl-templates.cpp +++ b/test/SemaCXX/using-decl-templates.cpp @@ -63,3 +63,20 @@ template <class T> struct Bar : public Foo<T>, Baz { }; 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/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp index dfe0f46ea255..19be03af8f46 100644 --- a/test/SemaCXX/value-initialization.cpp +++ b/test/SemaCXX/value-initialization.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 struct A { //expected-note {{marked deleted here}} \ // expected-warning {{does not declare any constructor to initialize}} diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index 3ca07b0215c3..42c27fb30e1b 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -118,4 +118,3 @@ void t8(int n, ...) { (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}} __builtin_va_end(list); } - diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp index 23d86d37426e..b477438ee988 100644 --- a/test/SemaCXX/virtual-override.cpp +++ b/test/SemaCXX/virtual-override.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 namespace T1 { class A { diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp index d8c26efcfb42..ea7d203ca70f 100644 --- a/test/SemaCXX/virtuals.cpp +++ b/test/SemaCXX/virtuals.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x %s +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 %s class A { virtual void f(); diff --git a/test/SemaCXX/warn-assignment-condition.cpp b/test/SemaCXX/warn-assignment-condition.cpp index c0ef35b252d8..04f2e7952547 100644 --- a/test/SemaCXX/warn-assignment-condition.cpp +++ b/test/SemaCXX/warn-assignment-condition.cpp @@ -109,6 +109,12 @@ void test() { 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)) diff --git a/test/SemaCXX/warn-bad-memaccess.cpp b/test/SemaCXX/warn-bad-memaccess.cpp index 9a998f020cb4..3a02c84e9fc4 100644 --- a/test/SemaCXX/warn-bad-memaccess.cpp +++ b/test/SemaCXX/warn-bad-memaccess.cpp @@ -3,6 +3,7 @@ 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; @@ -27,16 +28,22 @@ void test_warn() { // 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}} \ + // 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}} \ + // 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}} \ + // 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}} \ + // 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); // \ @@ -108,5 +115,3 @@ namespace N { N::memset(&x1, 0, sizeof x1); } } - - diff --git a/test/SemaCXX/warn-bool-conversion.cpp b/test/SemaCXX/warn-bool-conversion.cpp index f6fa9f28369d..595c749bcecd 100644 --- a/test/SemaCXX/warn-bool-conversion.cpp +++ b/test/SemaCXX/warn-bool-conversion.cpp @@ -1,18 +1,18 @@ // 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}} +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}} +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(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}} + 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}} + foo(kFlag); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} } char f(struct Undefined*); diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp new file mode 100644 index 000000000000..95f8c61ebb77 --- /dev/null +++ b/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/test/SemaCXX/warn-literal-conversion.cpp b/test/SemaCXX/warn-literal-conversion.cpp index b9c952873b9f..5fcae5dc80e6 100644 --- a/test/SemaCXX/warn-literal-conversion.cpp +++ b/test/SemaCXX/warn-literal-conversion.cpp @@ -8,18 +8,13 @@ void test0() { 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 = 12E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ - // expected-note {{this can be rewritten as an integer literal with the exact same value}} - int y4 = 1.2E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ - // expected-note {{this can be rewritten as an integer literal with the exact same value}} + 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 = 12E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ - // expected-note {{this can be rewritten as an integer literal with the exact same value}} - int y7 = 1.2E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ - // expected-note {{this can be rewritten as an integer literal with the exact same value}} - int y8 = (1.2E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} \ - // expected-note {{this can be rewritten as an integer literal with the exact same value}} + 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}} @@ -30,8 +25,7 @@ void test0() { // 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}} - // FIXME: -Wconversion-literal doesn't catch "-1.2F". - int y10 = -1.2F; + 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.) diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp index 90ac50472e98..a018223cbdae 100644 --- a/test/SemaCXX/warn-memset-bad-sizeof.cpp +++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -3,6 +3,7 @@ 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; @@ -51,6 +52,11 @@ void f(Mat m, const Foo& const_foo, char *buffer) { 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)); @@ -99,3 +105,35 @@ void f(Mat m, const Foo& const_foo, char *buffer) { memcpy(&foo, &arr, sizeof(Foo)); memcpy(&arr, &foo, sizeof(Foo)); } + +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}} + strncat(buff, BAR, sizeof(BAR)); // \ + // expected-warning {{argument to 'sizeof' in 'strncat' 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/test/SemaCXX/warn-missing-noreturn.cpp b/test/SemaCXX/warn-missing-noreturn.cpp index 4caff66af703..8072ac6b8249 100644 --- a/test/SemaCXX/warn-missing-noreturn.cpp +++ b/test/SemaCXX/warn-missing-noreturn.cpp @@ -1,27 +1,27 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -Wmissing-noreturn -Wreturn-type void f() __attribute__((noreturn)); -template<typename T> void g(T) { // expected-warning {{function could be attribute 'noreturn'}} +template<typename T> void g(T) { f(); } -template void g<int>(int); // expected-note {{in instantiation of function template specialization 'g<int>' requested here}} +template void g<int>(int); template<typename T> struct A { - void g() { // expected-warning {{function could be attribute 'noreturn'}} + void g() { f(); } }; -template struct A<int>; // expected-note {{in instantiation of member function 'A<int>::g' requested here}} +template struct A<int>; struct B { - template<typename T> void g(T) { // expected-warning {{function could be attribute 'noreturn'}} + template<typename T> void g(T) { f(); } }; -template void B::g<int>(int); // expected-note {{in instantiation of function template specialization 'B::g<int>' requested here}} +template void B::g<int>(int); // We don't want a warning here. struct X { @@ -61,7 +61,7 @@ namespace test2 { void *f; A() : f(0) { } - A(int) : f(h()) { } // expected-warning {{function could be attribute 'noreturn'}} + 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()) { } }; @@ -103,3 +103,23 @@ rdar8875247_B test_rdar8875247_B() { 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/test/SemaCXX/warn-sign-compare.cpp b/test/SemaCXX/warn-sign-compare.cpp deleted file mode 100644 index 3042bfde6e06..000000000000 --- a/test/SemaCXX/warn-sign-compare.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// RUN: %clang_cc1 -verify -fsyntax-only -Wsign-compare %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 d1 = 1 ? i : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} - int d2 = 1 ? Foo<bool>::D : i; // expected-warning {{operands of ? are integers of different signs}} - int d3 = 1 ? B : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} - int d4 = 1 ? Foo<bool>::D : B; // expected-warning {{operands of ? are integers of different signs}} - - int e1 = 1 ? i : E; // expected-warning {{operands of ? are integers of different signs}} - int e2 = 1 ? E : i; // expected-warning {{operands of ? are integers of different signs}} - int e3 = 1 ? E : B; // expected-warning {{operands of ? are integers of different signs}} - int e4 = 1 ? B : E; // expected-warning {{operands of ? are integers of different signs}} - } -} - -// 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 {{operands of ? are integers of different signs}} - int d2 = 1 ? Foo<bool>::D : i; // expected-warning {{operands of ? are integers of different signs}} - int d3 = 1 ? B : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} - int d4 = 1 ? Foo<bool>::D : B; // expected-warning {{operands of ? are integers of different signs}} - - int e1 = 1 ? i : E; // expected-warning {{operands of ? are integers of different signs}} - int e2 = 1 ? E : i; // expected-warning {{operands of ? are integers of different signs}} - int e3 = 1 ? E : B; // expected-warning {{operands of ? are integers of different signs}} - int e4 = 1 ? B : E; // expected-warning {{operands of ? are integers of different signs}} - } -} diff --git a/test/SemaCXX/warn-sign-conversion.cpp b/test/SemaCXX/warn-sign-conversion.cpp new file mode 100644 index 000000000000..ba2bc9b3d026 --- /dev/null +++ b/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/test/SemaCXX/warn-string-conversion.cpp b/test/SemaCXX/warn-string-conversion.cpp new file mode 100644 index 000000000000..23960e48df61 --- /dev/null +++ b/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/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp new file mode 100644 index 000000000000..90a8933150ac --- /dev/null +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -0,0 +1,1422 @@ +// 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)); +}; + + +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-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_3'}} +} + +void sls_fun_bad_4() { + if (getBool()) + sls_mu.Lock(); // \ + // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + else + sls_mu2.Lock(); // \ + // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}} +} + +void sls_fun_bad_5() { + sls_mu.Lock(); // \ + // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + if (getBool()) + sls_mu.Unlock(); +} + +void sls_fun_bad_6() { + if (getBool()) { + sls_mu.Lock(); // \ + // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + } else { + if (getBool()) { + getBool(); // EMPTY + } else { + getBool(); // EMPTY + } + } + sls_mu.Unlock(); // \ + // expected-warning{{unlocking 'sls_mu' that was not locked}} +} + +void sls_fun_bad_7() { + sls_mu.Lock(); // \ + // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + while (getBool()) { + sls_mu.Unlock(); + if (getBool()) { + if (getBool()) { + continue; + } + } + sls_mu.Lock(); // \ + // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + } + sls_mu.Unlock(); +} + +void sls_fun_bad_8() { + sls_mu.Lock(); // \ + // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + do { + 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}} + } while (getBool()); + sls_mu.Unlock(); +} + +void sls_fun_bad_10() { + sls_mu.Lock(); // \ + // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_10'}} \ + // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + while(getBool()) { + sls_mu.Unlock(); + } +} + +void sls_fun_bad_11() { + while (getBool()) { + sls_mu.Lock(); // \ + // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + } + sls_mu.Unlock(); // \ + // expected-warning{{unlocking 'sls_mu' that was not locked}} +} + +//-----------------------------------------// +// 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-warning{{mutex 'aa_mu' is still locked at the end of function 'aa_fun_bad_3'}} +} + +//--------------------------------------------------// +// Regression tests for unusual method names +//--------------------------------------------------// + +Mutex wmu; + +// Test diagnostics for other method names. +class WeirdMethods { + WeirdMethods() { + wmu.Lock(); // \ + // expected-warning {{mutex 'wmu' is still locked at the end of function 'WeirdMethods'}} + } + ~WeirdMethods() { + wmu.Lock(); // \ + // expected-warning {{mutex 'wmu' is still locked at the end of function '~WeirdMethods'}} + } + void operator++() { + wmu.Lock(); // \ + // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator++'}} + } + operator int*() { + wmu.Lock(); // \ + // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator int *'}} + return 0; + } +}; + +//-----------------------------------------------// +// 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 +// ----------------------------------------------// + +Mutex UPmu; +// FIXME: add support for lock expressions involving arrays. +Mutex mua[5]; + +int x __attribute__((guarded_by(UPmu = sls_mu))); // \ + // expected-warning{{cannot resolve lock expression to a specific lockable object}} +int y __attribute__((guarded_by(mua[0]))); // \ + // expected-warning{{cannot resolve lock expression to a specific lockable object}} + + +void testUnparse() { + // no errors, since the lock expressions are not resolved + x = 5; + y = 5; +} + +void testUnparse2() { + mua[0].Lock(); // \ + // expected-warning{{cannot resolve lock expression to a specific lockable object}} + (&(mua[0]) + 4)->Lock(); // \ + // expected-warning{{cannot resolve lock expression to a specific lockable object}} +} + + +//----------------------------------------------------------------------------// +// 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.2; + 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.3; + 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.5; + 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 + + diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp new file mode 100644 index 000000000000..67882d08996e --- /dev/null +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -0,0 +1,1255 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s + + +//-----------------------------------------// +// Helper fields +//-----------------------------------------// + +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-error {{'guarded_by' attribute requires arguments that are class type or point to class type}} +int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \ + // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}} +int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \ + // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}} +int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \ + // expected-error {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} + +//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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} +UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \ + // expected-error {{'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-error {{'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-error {{'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-error {{'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-error {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} +UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \ + // expected-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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 attribute takes at least 1 argument arguments}} + +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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'unlock_function' attribute requires arguments that are class type or point to class type}} +int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \ + // expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}} +int uf_function_bad_4() __attribute__((unlock_function(umu))); // \ + // expected-error {{'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-error {{'lock_returned' attribute requires arguments that are class type or point to class type}} +int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \ + // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}} +int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \ + // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}} +int lr_function_bad_4() __attribute__((lock_returned(umu))); // \ + // expected-error {{'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-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}} +int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \ + // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}} +int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \ + // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}} +int le_function_bad_4() __attribute__((locks_excluded(umu))); // \ + // expected-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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-error {{'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 {{invalid use of member 'mu' in static member function}} + + 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; +}; + diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index ea6755f2d6ce..604a3c0da381 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -45,8 +45,8 @@ void test3() { ? dead() : dead(); live(), - float // expected-warning {{will never be executed}} - (halt()); + float + (halt()); // expected-warning {{will never be executed}} } void test4() { @@ -73,6 +73,6 @@ void test6() { S(int i) { } }; live(), - S // expected-warning {{will never be executed}} - (halt()); + S + (halt()); // expected-warning {{will never be executed}} } diff --git a/test/SemaCXX/warn-unused-comparison.cpp b/test/SemaCXX/warn-unused-comparison.cpp new file mode 100644 index 000000000000..0153f213ba1f --- /dev/null +++ b/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/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp index 775c3cf01f24..80298ec6664a 100644 --- a/test/SemaCXX/warn-unused-value.cpp +++ b/test/SemaCXX/warn-unused-value.cpp @@ -15,3 +15,18 @@ namespace test0 { 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 +} diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp index c0cfd74a3e52..912622f5a7e4 100644 --- a/test/SemaCXX/warn-weak-vtables.cpp +++ b/test/SemaCXX/warn-weak-vtables.cpp @@ -29,3 +29,30 @@ void uses(A &a, B<int> &b, C &c) { 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(); +} |